@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
399 lines • 15 kB
JavaScript
;
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