UNPKG

@biconomy/abstractjs

Version:

SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.

399 lines 15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllowance = exports.safeMultiplier = exports.getTenderlyDetails = exports.playgroundTrue = exports.inProduction = exports.getAccountDomainStructFields = exports.eip712WrapHash = exports.getAccountMeta = exports.unwrapSignature6492 = exports.wrapSignatureWith6492 = exports.ERC6492_MAGIC_BYTES = exports.isNativeToken = exports.addressEquals = exports.isValidRpcUrl = exports.sanitizeUrl = exports.toBytes32 = exports.isBigInt = exports.isNullOrUndefined = void 0; exports.percentage = percentage; exports.convertToFactor = convertToFactor; exports.makeInstallDataAndHash = makeInstallDataAndHash; exports._hashTypedData = _hashTypedData; exports.getTypesForEIP712Domain = getTypesForEIP712Domain; exports.typeToString = typeToString; exports.bigIntReplacer = bigIntReplacer; exports.numberTo3Bytes = numberTo3Bytes; exports.toHexString = toHexString; exports.parseRequestArguments = parseRequestArguments; exports.supportsCancun = supportsCancun; exports.calculateNonceStorageSlot = calculateNonceStorageSlot; exports.validateConsistentMeeVersions = validateConsistentMeeVersions; const viem_1 = require("viem"); const Constants_1 = require("../../account/utils/Constants.js"); const constants_1 = require("../../constants/index.js"); const abi_1 = require("../../constants/abi/index.js"); const Types_1 = require("../../modules/utils/Types.js"); const getVersion_1 = require("./getVersion.js"); const isNullOrUndefined = (value) => { return value === null || value === undefined; }; exports.isNullOrUndefined = isNullOrUndefined; const isBigInt = (value) => { try { BigInt(value); return true; } catch { return false; } }; exports.isBigInt = isBigInt; const toBytes32 = (value) => { if (typeof value === "boolean") { return (0, viem_1.padHex)((0, viem_1.toHex)(value ? 1n : 0n), { size: 32 }); } if (typeof value === "bigint") { return (0, viem_1.padHex)((0, viem_1.toHex)(value), { size: 32 }); } if ((0, viem_1.isAddress)(value)) { return (0, viem_1.padHex)(value, { size: 32 }); } if ((0, viem_1.isHex)(value)) { return (0, viem_1.padHex)(value, { size: 32 }); } throw new Error("Invalid value: must be boolean, bigint, address, or hex string"); }; exports.toBytes32 = toBytes32; const sanitizeUrl = (value) => { return value.replace(/https?:\/\/[^\s]+/g, ""); }; exports.sanitizeUrl = sanitizeUrl; const isValidRpcUrl = (url) => { const regex = /^(http:\/\/|wss:\/\/|https:\/\/).*/; return regex.test(url); }; exports.isValidRpcUrl = isValidRpcUrl; const addressEquals = (a, b) => !!a && !!b && a?.toLowerCase() === b.toLowerCase(); exports.addressEquals = addressEquals; const isNativeToken = (tokenAddress) => (0, exports.addressEquals)(tokenAddress, "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") || (0, exports.addressEquals)(tokenAddress, "0x0000000000000000000000000000000000000000"); exports.isNativeToken = isNativeToken; exports.ERC6492_MAGIC_BYTES = "0x6492649264926492649264926492649264926492649264926492649264926492"; const wrapSignatureWith6492 = ({ factoryAddress, factoryCalldata, signature }) => { return (0, viem_1.concat)([ (0, viem_1.encodeAbiParameters)((0, viem_1.parseAbiParameters)("address, bytes, bytes"), [ factoryAddress, factoryCalldata, signature ]), exports.ERC6492_MAGIC_BYTES ]); }; exports.wrapSignatureWith6492 = wrapSignatureWith6492; const unwrapSignature6492 = (wrappedSignature) => { if (!wrappedSignature.endsWith(exports.ERC6492_MAGIC_BYTES.slice(2))) { return { isWrapped: false, originalSignature: wrappedSignature }; } const signatureWithoutMagic = wrappedSignature.slice(0, -64); const decoded = (0, viem_1.decodeAbiParameters)((0, viem_1.parseAbiParameters)("address, bytes, bytes"), signatureWithoutMagic); return { isWrapped: true, factoryAddress: decoded[0], factoryCalldata: decoded[1], originalSignature: decoded[2] }; }; exports.unwrapSignature6492 = unwrapSignature6492; function percentage(partialValue, totalValue) { return (100 * partialValue) / totalValue; } function convertToFactor(percentage) { if (percentage) { if (percentage < 1 || percentage > 100) { throw new Error("The percentage value should be between 1 and 100."); } const factor = percentage / 100 + 1; return factor; } return 1; } function makeInstallDataAndHash(accountOwner, modules, domainName = Constants_1.NEXUS_DOMAIN_NAME, domainVersion = Constants_1.NEXUS_DOMAIN_VERSION) { const types = modules.map((module) => BigInt(Types_1.moduleTypeIds[module.type])); const initDatas = modules.map((module) => (0, viem_1.toHex)((0, viem_1.concat)([(0, viem_1.toBytes)(BigInt(Types_1.moduleTypeIds[module.type])), module.config]))); const multiInstallData = (0, viem_1.encodeAbiParameters)([{ type: "uint256[]" }, { type: "bytes[]" }], [types, initDatas]); const structHash = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([{ type: "bytes32" }, { type: "address" }, { type: "bytes32" }], [ Constants_1.MODULE_ENABLE_MODE_TYPE_HASH, Constants_1.MOCK_MULTI_MODULE_ADDRESS, (0, viem_1.keccak256)(multiInstallData) ])); const hashToSign = _hashTypedData(structHash, domainName, domainVersion, accountOwner); return [multiInstallData, hashToSign]; } function _hashTypedData(structHash, name, version, verifyingContract) { const DOMAIN_SEPARATOR = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([ { type: "bytes32" }, { type: "bytes32" }, { type: "bytes32" }, { type: "address" } ], [ (0, viem_1.keccak256)((0, viem_1.stringToBytes)(Constants_1.NEXUS_DOMAIN_TYPEHASH)), (0, viem_1.keccak256)((0, viem_1.stringToBytes)(name)), (0, viem_1.keccak256)((0, viem_1.stringToBytes)(version)), verifyingContract ])); return (0, viem_1.keccak256)((0, viem_1.concat)([ (0, viem_1.stringToBytes)("\x19\x01"), (0, viem_1.hexToBytes)(DOMAIN_SEPARATOR), (0, viem_1.hexToBytes)(structHash) ])); } function getTypesForEIP712Domain({ domain }) { return [ typeof domain?.name === "string" && { name: "name", type: "string" }, domain?.version && { name: "version", type: "string" }, typeof domain?.chainId === "number" && { name: "chainId", type: "uint256" }, domain?.verifyingContract && { name: "verifyingContract", type: "address" }, domain?.salt && { name: "salt", type: "bytes32" } ].filter(Boolean); } const getAccountMeta = async (client, accountAddress) => { try { const domain = await client.request({ method: "eth_call", params: [ { to: accountAddress, data: (0, viem_1.encodeFunctionData)({ abi: abi_1.EIP1271Abi, functionName: "eip712Domain" }) }, "latest" ] }); if (domain !== "0x") { const decoded = (0, viem_1.decodeFunctionResult)({ abi: abi_1.EIP1271Abi, functionName: "eip712Domain", data: domain }); return { name: decoded?.[1], version: decoded?.[2], chainId: decoded?.[3] }; } } catch (error) { } return { name: Constants_1.NEXUS_DOMAIN_NAME, version: Constants_1.NEXUS_DOMAIN_VERSION, chainId: client.chain ? BigInt(client.chain.id) : BigInt(await client.extend(viem_1.publicActions).getChainId()) }; }; exports.getAccountMeta = getAccountMeta; const eip712WrapHash = (typedHash, appDomainSeparator) => (0, viem_1.keccak256)((0, viem_1.concat)(["0x1901", appDomainSeparator, typedHash])); exports.eip712WrapHash = eip712WrapHash; function typeToString(typeDef) { return Object.entries(typeDef).map(([key, fields]) => { const fieldStrings = (fields ?? []) .map((field) => `${field.type} ${field.name}`) .join(","); return `${key}(${fieldStrings})`; }); } function bigIntReplacer(_key, value) { return typeof value === "bigint" ? value.toString() : value; } function numberTo3Bytes(key) { const buffer = new Uint8Array(3); buffer[0] = Number((key >> 16n) & 0xffn); buffer[1] = Number((key >> 8n) & 0xffn); buffer[2] = Number(key & 0xffn); return buffer; } function toHexString(byteArray) { return Array.from(byteArray) .map((byte) => byte.toString(16).padStart(2, "0")) .join(""); } const getAccountDomainStructFields = async (publicClient, accountAddress) => { const accountDomainStructFields = (await publicClient.readContract({ address: accountAddress, abi: (0, viem_1.parseAbi)([ "function eip712Domain() public view returns (bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions)" ]), functionName: "eip712Domain" })); const [, name, version, chainId, verifyingContract, salt] = accountDomainStructFields; const params = (0, viem_1.parseAbiParameters)([ "bytes32", "bytes32", "uint256", "address", "bytes32" ]); return (0, viem_1.encodeAbiParameters)(params, [ (0, viem_1.keccak256)((0, viem_1.toBytes)(name)), (0, viem_1.keccak256)((0, viem_1.toBytes)(version)), chainId, verifyingContract, salt ]); }; exports.getAccountDomainStructFields = getAccountDomainStructFields; const inProduction = () => { try { return process?.env?.environment === "production"; } catch (e) { return true; } }; exports.inProduction = inProduction; const playgroundTrue = () => { try { return process?.env?.RUN_PLAYGROUND === "true"; } catch (e) { return false; } }; exports.playgroundTrue = playgroundTrue; const getTenderlyDetails = () => { try { const accountSlug = process?.env?.TENDERLY_ACCOUNT_SLUG; const projectSlug = process?.env?.TENDERLY_PROJECT_SLUG; const apiKey = process?.env?.TENDERLY_API_KEY; if (!accountSlug || !projectSlug || !apiKey) { return null; } return { accountSlug, projectSlug, apiKey }; } catch (e) { return null; } }; exports.getTenderlyDetails = getTenderlyDetails; const safeMultiplier = (bI, multiplier) => BigInt(Math.round(Number(bI) * multiplier)); exports.safeMultiplier = safeMultiplier; const getAllowance = async (client, owner, tokenAddress, spender = Constants_1.BICONOMY_TOKEN_PAYMASTER) => { const approval = await client.readContract({ address: tokenAddress, abi: viem_1.erc20Abi, functionName: "allowance", args: [owner, spender] }); return approval; }; exports.getAllowance = getAllowance; function parseRequestArguments(input) { const fieldsToOmit = [ "callGasLimit", "preVerificationGas", "maxFeePerGas", "maxPriorityFeePerGas", "paymasterAndData", "verificationGasLimit" ]; const argsString = input.slice(1).join(""); const lines = argsString.split("\n").filter((line) => line.trim()); const result = lines.reduce((acc, line) => { const [key, value] = line.split(":").map((s) => s.trim()); const cleanKey = key.trim(); const cleanValue = value.replace("gwei", "").trim(); if (fieldsToOmit.includes(cleanKey)) { return acc; } acc[cleanKey] = cleanValue; return acc; }, {}); return result; } async function supportsCancun({ transport, chain }) { const cancunSupportedChains = { "1": true, "11155111": true, "8453": true, "84532": true, "137": true, "80002": true, "42161": true, "421614": true, "10": true, "11155420": true, "56": true, "97": true, "146": true, "57054": true, "534352": true, "534351": true, "100": true, "10200": true, "43114": true, "43113": true, "33139": true, "33111": true, "999": true, "1116": true, "267": true, "1329": true, "1328": true, "130": true, "1301": true, "747474": true, "1135": true, "480": true, "4801": true, "20993": true, "10143": true, "143": true, "88882": false, "531050204": true, "5010405": true }; if (cancunSupportedChains[chain.id.toString()]) { return cancunSupportedChains[chain.id.toString()]; } const client = (0, viem_1.createPublicClient)({ chain, transport }); const block = await client.getBlock({ blockTag: "latest" }); if (block.blobGasUsed !== undefined || block.excessBlobGas !== undefined) { return true; } return false; } function calculateNonceStorageSlot(sender, key = 0n) { const BASE_SLOT = 1; const firstLevelSlot = (0, viem_1.keccak256)((0, viem_1.concat)([ (0, viem_1.pad)(sender, { size: 32 }), (0, viem_1.pad)((0, viem_1.numberToHex)(BASE_SLOT), { size: 32 }) ])); const finalSlot = (0, viem_1.keccak256)((0, viem_1.concat)([ (0, viem_1.pad)((0, viem_1.numberToHex)(key), { size: 32 }), firstLevelSlot ])); return finalSlot; } function validateConsistentMeeVersions(meeVersions) { let hasPersonalSignVersion = false; let hasEIP712Version = false; for (const { version: meeVersionConfig } of meeVersions) { const meeVersion = meeVersionConfig.version; const isCurrentVersionPersonalSign = (0, getVersion_1.isVersionOlder)(meeVersion, constants_1.MEEVersion.V2_2_1); const isCurrentVersionEIP712 = (0, getVersion_1.versionIsAtLeast)(meeVersion, constants_1.MEEVersion.V2_2_1); hasPersonalSignVersion = hasPersonalSignVersion || isCurrentVersionPersonalSign; hasEIP712Version = hasEIP712Version || isCurrentVersionEIP712; if (hasPersonalSignVersion && hasEIP712Version) { throw new Error("MEE versions on all chains should be whether less than 2.2.0 or greater than or equal to 2.2.0. " + "Otherwise Multichain account won't be able to consume the same signature across all chains involved in the quote request."); } } } //# sourceMappingURL=Utils.js.map