UNPKG

@anuragchvn-blip/mandatekit

Version:

Production-ready Web3 autopay SDK for crypto-based recurring payments using EIP-712 mandates

204 lines 5.63 kB
/** * Adapters for protocol integrations (Permit2, Vaults, Account Abstraction) * @module adapters */ /** * Permit2 contract address (same across all networks) */ export const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3'; /** * Create Permit2 approval data for a mandate * * @param mandate - Mandate requiring token approval * @param permit2Signature - Permit2 signature from user * @returns Permit2 data for batch processing * * @example * ```typescript * const permit2Data = createPermit2Approval(mandate, signature); * // Use this data when executing mandate to avoid separate approve tx * ``` */ export function createPermit2Approval(mandate, permit2Signature) { return { token: mandate.token, amount: BigInt(mandate.amount), expiration: mandate.validBefore, nonce: BigInt(mandate.nonce), signature: permit2Signature, }; } /** * Create a vault-backed mandate * * @param mandate - Base mandate * @param vaultConfig - Vault configuration * @returns Vault mandate with vault metadata * * @example * ```typescript * const vaultMandate = createVaultMandate(mandate, { * vaultAddress: '0x...', * vaultType: 'gnosis-safe', * threshold: 2, * }); * ``` */ export function createVaultMandate(mandate, vaultConfig) { return { ...mandate, vault: vaultConfig, // Subscriber should be the vault address subscriber: vaultConfig.vaultAddress, }; } /** * Gnosis Safe adapter helpers */ export const GnosisSafeAdapter = { /** * Encode mandate execution for Gnosis Safe */ encodeExecution(_mandate) { // In real implementation, this would encode the proper calldata return '0x...'; }, /** * Get required signers for a Safe transaction */ async getRequiredSigners(_safeAddress, _threshold) { // In real implementation, this would query the Safe contract return []; }, }; /** * Create a user operation for mandate execution with paymaster * * @param mandate - Mandate to execute * @param paymasterConfig - Paymaster configuration * @returns User operation for bundler submission * * @example * ```typescript * const userOp = await createMandateUserOp(mandate, { * paymasterAddress: '0x...', * type: 'verifying', * maxGasSponsorship: parseEther('0.01'), * }); * * // Submit to bundler * await bundler.sendUserOperation(userOp); * ``` */ export async function createMandateUserOp(mandate, paymasterConfig) { // In real implementation, this would construct full UserOperation return { sender: mandate.subscriber, nonce: BigInt(mandate.nonce), callData: '0x...', paymasterAndData: encodePaymasterData(paymasterConfig), }; } /** * Encode paymaster data */ function encodePaymasterData(config) { // In real implementation, this would encode proper paymaster data return `${config.paymasterAddress}000000000000000000000000`; } /** * Create a session key for mandate operations * * @param config - Session key configuration * @returns Session key data for storage * * @example * ```typescript * const sessionKey = createSessionKey({ * sessionKey: '0x...', * permissions: { * canSign: true, * canExecute: false, * canCancel: false, * }, * expiresAt: Date.now() / 1000 + 86400, // 24 hours * maxAmount: parseEther('100'), * allowedTokens: [USDC_ADDRESS], * }); * ``` */ export function createSessionKey(config) { return config; } /** * Validate session key permissions for an operation */ export function validateSessionKey(sessionKey, operation, mandate) { // Check expiration if (sessionKey.expiresAt < Date.now() / 1000) { return false; } // Check permissions const canPerform = { sign: sessionKey.permissions.canSign, execute: sessionKey.permissions.canExecute, cancel: sessionKey.permissions.canCancel, }[operation]; if (!canPerform) { return false; } // Check mandate-specific restrictions if (mandate) { // Check amount limit if (sessionKey.maxAmount && BigInt(mandate.amount) > sessionKey.maxAmount) { return false; } // Check allowed tokens if (sessionKey.allowedTokens && !sessionKey.allowedTokens.includes(mandate.token)) { return false; } } return true; } /** * DeFi protocol adapters */ /** * Aave adapter for subscription payments from lending positions */ export const AaveAdapter = { /** * Create mandate that pulls from Aave aToken balance */ createATokenMandate(baseMandate, aTokenAddress) { return { ...baseMandate, token: aTokenAddress, // Use aToken instead of underlying metadata: JSON.stringify({ protocol: 'aave', underlyingToken: baseMandate.token, ...JSON.parse(baseMandate.metadata ?? '{}'), }), }; }, }; /** * Compound adapter for subscription payments from lending positions */ export const CompoundAdapter = { /** * Create mandate that pulls from Compound cToken balance */ createCTokenMandate(baseMandate, cTokenAddress) { return { ...baseMandate, token: cTokenAddress, metadata: JSON.stringify({ protocol: 'compound', underlyingToken: baseMandate.token, ...JSON.parse(baseMandate.metadata ?? '{}'), }), }; }, }; //# sourceMappingURL=index.js.map