UNPKG

@0xsequence/connect

Version:
395 lines 13.1 kB
import { ContractType, TxnTransferType } from '@0xsequence/indexer'; import { encodeFunctionData, getAddress, slice, toHex, zeroAddress } from 'viem'; export var DecodingType; (function (DecodingType) { DecodingType["APPROVE"] = "approve"; DecodingType["TRANSFER"] = "transfer"; DecodingType["SWAP"] = "swap"; DecodingType["AWARD_ITEM"] = "awardItem"; DecodingType["UNIMPLEMENTED"] = "unimplemented"; DecodingType["UNKNOWN"] = "unknown"; })(DecodingType || (DecodingType = {})); // Transform decoded contract call arguments to a object format const transformArgs = (args) => { return Object.fromEntries(args.map((arg, i) => [ arg.name && !arg.name.startsWith('unnamed') ? arg.name : `_${i}`, Array.isArray(arg.value) ? arg.type.startsWith('(') && (arg.type.endsWith(')') || arg.type.endsWith(')[]')) ? transformArgs(arg.value) : arg.value : arg.value ])); }; const createTxnData = (to, call, value, data) => { const args = transformArgs(call.args); const byteSignature = slice(data, 0, 4); let objs = []; switch (call.signature) { case 'execute((bool,bool,uint256,address,uint256,bytes)[],uint256,bytes)': case 'selfExecute((bool,bool,uint256,address,uint256,bytes)[])': { const txns = call.args[0].value; objs = txns.map(txn => { const data = toHex(txn.data); const value = toHex(BigInt(txn.value)); return txn.call ? createTxnData(txn.target, txn.call, value, data) : { to: txn.target, signature: '', byteSignature: slice(data, 0, 4), methodName: '', args: {}, objs: [], value, data }; }); } } return { to, signature: call.signature, byteSignature, methodName: call.function, args, objs, value: toHex(BigInt(value)), data: data }; }; export const encodeTransactions = (transactions) => { return transactions .map(transaction => { if ('target' in transaction) { return transaction; } else { return { ...transaction, target: transaction.to }; } }) .map(transaction => ({ delegateCall: transaction.delegateCall ?? false, revertOnError: transaction.revertOnError ?? false, gasLimit: transaction.gasLimit ?? 0, target: transaction.target ?? '0x0000000000000000000000000000000000000000', value: transaction.value ?? 0, data: transaction.data ?? '0x' })); }; export var ByteSignature; (function (ByteSignature) { ByteSignature["SEQUENCE_DEPLOY"] = "0x32c02a14"; ByteSignature["SEQUENCE_PUBLISH_CONFIG"] = "0x44d466c2"; ByteSignature["SEQUENCE_UPDATE_IMAGE_HASH"] = "0x29561426"; ByteSignature["SEQUENCE_UPDATE_IMPLEMENTATION"] = "0x025b22bc"; ByteSignature["SEQUENCE_REQUIRE_SESSION_NONCE"] = "0x8853baa0"; ByteSignature["EXECUTE"] = "0x7a9a1628"; ByteSignature["SELF_EXECUTE"] = "0x61c2926c"; ByteSignature["APPROVE"] = "0x095ea7b3"; ByteSignature["TRANSFER"] = "0xa9059cbb"; ByteSignature["DEPOSIT"] = "0xd0e30db0"; ByteSignature["WITHDRAW"] = "0x2e1a7d4d"; ByteSignature["ERC721_SAFE_TRANSFER_FROM"] = "0x42842e0e"; ByteSignature["ERC721_SAFE_TRANSFER_FROM_WITH_DATA"] = "0xb88d4fde"; ByteSignature["ERC1155_SAFE_TRANSFER_FROM"] = "0xf242432a"; ByteSignature["ERC1155_SAFE_BATCH_TRANSFER_FROM"] = "0x2eb2c2d6"; ByteSignature["NIFTYSWAP_BUY_TOKENS"] = "0xd93e8aaa"; ByteSignature["TRANSFORM_ERC20"] = "0x415565b0"; ByteSignature["OUTBOUND_TRANSFER_TO"] = "0xa44bbb15"; ByteSignature["CELER_SEND"] = "0xa5977fbb"; ByteSignature["UNISWAPV3_MULTICALL"] = "0x5ae401dc"; ByteSignature["UNISWAPV2_SWAP_EXACT_TOKENS_FOR_TOKENS"] = "0x38ed1739"; ByteSignature["UNISWAPV2_SWAP_TOKENS_FOR_EXACT_TOKENS"] = "0x8803dbee"; ByteSignature["UNISWAPV2_SWAP_EXACT_ETH_FOR_TOKENS"] = "0x7ff36ab5"; ByteSignature["UNISWAPV2_SWAP_ETH_FOR_EXACT_TOKENS"] = "0xfb3bdb41"; ByteSignature["UNISWAPV2_SWAP_TOKENS_FOR_EXACT_ETH"] = "0x4a25d94a"; ByteSignature["UNISWAPV2_SWAP_EXACT_TOKENS_FOR_ETH"] = "0x18cbafe5"; // For demo NFT contract ByteSignature["AWARD_ITEM"] = "0xcf378343"; })(ByteSignature || (ByteSignature = {})); const decodeTxnData = async (apiClient, txns) => { const callData = encodeFunctionData({ abi: mainModuleAbi, functionName: 'selfExecute', args: [txns] }); try { const { call } = await apiClient.decodeContractCall({ callData }); return createTxnData('', call, 0, callData); } catch (err) { throw err; } }; export const decodeTransactions = async (apiClient, accountAddress, txns) => { const encodedTxns = encodeTransactions(txns); const decodedTxnDatas = (await decodeTxnData(apiClient, encodedTxns)).objs; const from = getAddress(accountAddress); const txnProps = encodedTxns.map((txn, i) => { const decodedTxnData = decodedTxnDatas[i]; const data = txn.data.toString(); const value = BigInt(txn.value).toString(); const target = txn.target; if (data === '0x' || !data) { // this is a native token transfer return { signature: '', byteSignature: '', type: DecodingType.TRANSFER, methodName: 'nativeTokenTransfer', transferType: TxnTransferType.SEND, contractAddress: zeroAddress, contractType: ContractType.UNKNOWN, from, to: getAddress(txn.target), tokenIds: ['0'], amounts: [value], target, value }; } if (!decodedTxnData) { return undefined; } const contractAddress = getAddress(txn.target); const baseDecoding = { type: DecodingType.UNIMPLEMENTED, signature: decodedTxnData.signature, byteSignature: decodedTxnData.byteSignature, methodName: decodedTxnData.methodName, target, value }; switch (decodedTxnData.byteSignature) { case ByteSignature.TRANSFER: { const { args } = decodedTxnData; return { ...baseDecoding, type: DecodingType.TRANSFER, transferType: TxnTransferType.SEND, contractAddress, contractType: ContractType.ERC20, from, to: getAddress(args.recipient), tokenIds: ['0'], amounts: [String(args.amount)] }; } case ByteSignature.ERC721_SAFE_TRANSFER_FROM: case ByteSignature.ERC721_SAFE_TRANSFER_FROM_WITH_DATA: { const args = decodedTxnData.args; return { ...baseDecoding, type: DecodingType.TRANSFER, transferType: TxnTransferType.SEND, contractAddress, contractType: ContractType.ERC721, from, to: getAddress(args.to), tokenIds: [args.tokenId], amounts: ['1'] }; } case ByteSignature.ERC1155_SAFE_TRANSFER_FROM: { const args = decodedTxnData.args; return { ...baseDecoding, type: DecodingType.TRANSFER, transferType: TxnTransferType.SEND, contractAddress, contractType: ContractType.ERC1155, from, to: getAddress(args._to), tokenIds: [args._id], amounts: [args._amount] }; } case ByteSignature.ERC1155_SAFE_BATCH_TRANSFER_FROM: { const { args } = decodedTxnData; return { ...baseDecoding, type: DecodingType.TRANSFER, transferType: TxnTransferType.SEND, contractAddress, contractType: ContractType.ERC1155, from, to: getAddress(args._to), tokenIds: args._ids, amounts: args._amounts }; } case ByteSignature.AWARD_ITEM: { const { args } = decodedTxnData; return { ...baseDecoding, type: DecodingType.AWARD_ITEM, contractAddress, to: getAddress(args._0), amount: '1' }; } } return undefined; }); return txnProps.flatMap(txn => { if (txn) { return [txn]; } return []; }); }; const mainModuleAbi = [ { type: 'function', name: 'nonce', constant: true, inputs: [], outputs: [ { type: 'uint256' } ], payable: false, stateMutability: 'view' }, { type: 'function', name: 'readNonce', constant: true, inputs: [ { type: 'uint256' } ], outputs: [ { type: 'uint256' } ], payable: false, stateMutability: 'view' }, { type: 'function', name: 'updateImplementation', constant: false, inputs: [ { type: 'address' } ], outputs: [], payable: false, stateMutability: 'nonpayable' }, { type: 'function', name: 'selfExecute', constant: false, inputs: [ { components: [ { type: 'bool', name: 'delegateCall' }, { type: 'bool', name: 'revertOnError' }, { type: 'uint256', name: 'gasLimit' }, { type: 'address', name: 'target' }, { type: 'uint256', name: 'value' }, { type: 'bytes', name: 'data' } ], type: 'tuple[]' } ], outputs: [], payable: false, stateMutability: 'nonpayable' }, { type: 'function', name: 'execute', constant: false, inputs: [ { components: [ { type: 'bool', name: 'delegateCall' }, { type: 'bool', name: 'revertOnError' }, { type: 'uint256', name: 'gasLimit' }, { type: 'address', name: 'target' }, { type: 'uint256', name: 'value' }, { type: 'bytes', name: 'data' } ], type: 'tuple[]' }, { type: 'uint256' }, { type: 'bytes' } ], outputs: [], payable: false, stateMutability: 'nonpayable' }, { type: 'function', name: 'createContract', inputs: [ { type: 'bytes' } ], payable: true, stateMutability: 'payable' }, { type: 'function', name: 'setExtraImageHash', constant: false, inputs: [ { type: 'bytes32', name: 'imageHash' }, { type: 'uint256', name: 'expiration' } ], outputs: [], payable: false, stateMutability: 'nonpayable' } ]; //# sourceMappingURL=txnDecoding.js.map