@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
125 lines • 5.15 kB
JavaScript
import { CHAIN_ID, DELEGATOR_CONTRACTS, createCaveatBuilder, createOpenDelegation } from "@metamask/delegation-toolkit";
import { concatHex, encodeAbiParameters, encodeFunctionData, encodePacked, erc20Abi } from "viem";
const MM_DTK_PREFIX = "0x177eee03";
/**
* Signs a permit quote using EIP-2612 permit signatures. This enables gasless
* approvals for ERC20 tokens that implement the permit extension.
*
* @param client - The Mee client instance
* @param parameters - Parameters for signing the permit quote
* @param parameters.fusionQuote - The permit quote to sign
* @param [parameters.account] - Optional account to use for signing
*
* @returns Promise resolving to the quote payload with permit signature
*
* @example
* ```typescript
* const signedMMDtkQuote = await signMMDtkQuote(meeClient, {
* fusionQuote: {
* quote: quotePayload,
* trigger: {
* tokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
* chainId: 1,
* amount: 1000000n // 1 USDC
* }
* },
* delegatorSmartAccount: mmDtkAccount
* });
* ```
*/
export const signMMDtkQuote = async (client, parameters) => {
const { companionAccount: account_ = client.account, delegatorSmartAccount, fusionQuote: { quote, trigger } } = parameters;
if (trigger.call) {
throw new Error("Custom triggers are not supported for fusion transactions");
}
if (!trigger.amount)
throw new Error("Amount is required to sign a MM DTK quote");
// prepare the delegation to sign
const environment = delegatorSmartAccount.environment;
const caveatBuilder = createCaveatBuilder(environment);
const approvedCallData = concatHex([
encodeFunctionData({
abi: erc20Abi,
functionName: "approve",
args: [
account_.addressOn(trigger.chainId, true), // spender
trigger.amount // amount
]
}),
quote.hash // SuperTxn Hash
]);
const caveats = caveatBuilder.addCaveat("exactExecution", {
target: trigger.tokenAddress,
value: 0n, // 0 ETH
callData: approvedCallData
});
const openRootDelegation = createOpenDelegation({
from: delegatorSmartAccount.address,
caveats
});
const signature = await delegatorSmartAccount.signDelegation({
delegation: openRootDelegation
});
const delegationManager = getDelegationManager(trigger.chainId);
const redeemDelegationErc7579ExecutionCalldata = encodePacked(["address", "uint256", "bytes"], [trigger.tokenAddress, 0n, approvedCallData]);
const encodedSignature = encodeAbiParameters([
{ name: "delegationManager", type: "address" },
{
name: "delegation",
type: "tuple",
components: [
{ name: "delegate", type: "address" },
{ name: "delegator", type: "address" },
{ name: "authority", type: "bytes32" },
{
name: "caveats",
type: "tuple[]",
components: [
{ name: "enforcer", type: "address" },
{ name: "terms", type: "bytes" },
{ name: "args", type: "bytes" }
]
},
{ name: "salt", type: "uint256" },
{ name: "signature", type: "bytes" }
]
},
{ name: "redeemDelegationErc7579ExecutionCalldata", type: "bytes" }
], [
delegationManager,
{
delegate: openRootDelegation.delegate,
delegator: openRootDelegation.delegator,
authority: openRootDelegation.authority,
caveats: openRootDelegation.caveats.map((caveat) => ({
enforcer: caveat.enforcer,
terms: caveat.terms,
args: caveat.args
})),
salt: openRootDelegation.salt === "0x"
? BigInt(0)
: BigInt(openRootDelegation.salt),
signature: signature
},
redeemDelegationErc7579ExecutionCalldata
]);
return { ...quote, signature: concatHex([MM_DTK_PREFIX, encodedSignature]) };
};
export default signMMDtkQuote;
const getDelegationManager = (chainId) => {
// Try to find the delegation manager in the latest version first (1.3.0)
if (DELEGATOR_CONTRACTS["1.3.0"][chainId]?.DelegationManager) {
return DELEGATOR_CONTRACTS["1.3.0"][chainId].DelegationManager;
}
// Fallback to version 1.1.0
if (DELEGATOR_CONTRACTS["1.1.0"][chainId]?.DelegationManager) {
return DELEGATOR_CONTRACTS["1.1.0"][chainId].DelegationManager;
}
// Fallback to version 1.0.0
if (DELEGATOR_CONTRACTS["1.0.0"][chainId]?.DelegationManager) {
return DELEGATOR_CONTRACTS["1.0.0"][chainId].DelegationManager;
}
// If no delegation manager is found for the chainId, throw an error
throw new Error(`No delegation manager found for chainId ${chainId}. Supported chains are: ${Object.values(CHAIN_ID).join(", ")}`);
};
//# sourceMappingURL=signMmDtkQuote.js.map