UNPKG

@pushchain/core

Version:
275 lines 11.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toUniversal = toUniversal; exports.toChainAgnostic = toChainAgnostic; exports.fromChainAgnostic = fromChainAgnostic; exports.convertOriginToExecutor = convertOriginToExecutor; exports.convertExecutorToOriginAccount = convertExecutorToOriginAccount; const tslib_1 = require("tslib"); const viem_1 = require("viem"); const chain_1 = require("../../constants/chain"); const enums_1 = require("../../constants/enums"); const anchor_1 = require("@coral-xyz/anchor"); const abi_1 = require("../../constants/abi"); const push_client_1 = require("../../push-client/push-client"); const cache_1 = require("../../cache/cache"); const push_chain_1 = require("../../push-chain/push-chain"); /** * Formats a blockchain address based on the virtual machine type of the provided chain. * * - For EVM chains, it converts the address to its checksummed format. * - For non-EVM chains (e.g., Solana), the original address is returned as-is. - Can be changed in future * @param {CHAIN} chain - A fully qualified chain identifier (e.g., CHAIN.ETHEREUM_MAINNET). * @param {string} address - The raw address string to normalize. * @returns {string} - A VM-compliant formatted address. * * @throws {Error} If an invalid EVM address is provided. * * @example * // EVM address gets checksummed * formatAddress(CHAIN.ETHEREUM_SEPOLIA, "0xabcd...") // → "0xAbCd..." * * @example * // Non-EVM address is returned as-is * formatAddress(CHAIN.SOLANA_DEVNET, "solanaAddress123") // → "solanaAddress123" */ function formatAddress(chain, address) { if (chain_1.CHAIN_INFO[chain].vm === enums_1.VM.EVM) { try { return (0, viem_1.getAddress)(address.toLowerCase()); } catch (_a) { throw new Error('Invalid EVM address format'); } } return address; } /** * Creates a `UniversalAccount` object from an address and chain options. * Alternative to createUniversalAccount with a different parameter structure. * * @param {string} address - The account address. * @param {Object} options - The configuration options. * @param {CHAIN} options.chain - The chain the account is associated with. * @returns {UniversalAccount} A normalized account object with chain and address. * * @example * const universalAccount = toUniversal( * '0x35B84d6848D16415177c64D64504663b998A6ab4', * { chain: CHAIN.ETHEREUM_SEPOLIA } * ); * // → { chain: CHAIN.ETHEREUM_SEPOLIA, address: '0x35B84d6848D16415177c64D64504663b998A6ab4' } */ function toUniversal(address, options) { return { chain: options.chain, address: formatAddress(options.chain, address), }; } /** * Converts an address and chain into a CAIP-10 style address string. * * Format: `namespace:chainId:address` * Namespace is derived from the chain's VM type using VM_NAMESPACE. * * @param {string} address - The account address to convert. * @param {Object} options - The configuration options. * @param {CHAIN} options.chain - The chain the account is associated with. * @returns {string} A CAIP-10 formatted string. * * @example * Utils.account.toChainAgnostic('0xabc123...', { * chain: CHAIN.ETHEREUM_SEPOLIA * }) * // → 'eip155:11155111:0xabc123...' */ function toChainAgnostic(address, options) { const { chain } = options; const chainMeta = chain_1.CHAIN_INFO[chain]; if (!chainMeta) { throw new Error(`Unrecognized chain: ${chain}`); } const { chainId, vm } = chainMeta; const namespace = chain_1.VM_NAMESPACE[vm]; return `${namespace}:${chainId}:${formatAddress(chain, address)}`; } /** * Converts a CAIP-10 formatted string into a UniversalAccount. * * @param {string} caip - A CAIP-10 address string (e.g., 'eip155:1:0xabc...'). * @returns {UniversalAccount} The resolved account. * @throws {Error} If the CAIP string is invalid or unsupported. * * @example * Utils.account.fromChainAgnostic('eip155:11155111:0xabc...') * // → { chain: CHAIN.ETHEREUM_SEPOLIA, address: '0xabc...' } */ function fromChainAgnostic(caip) { var _a, _b; const [namespace, chainId, rawAddress] = caip.split(':'); const chain = ((_b = (_a = Object.entries(chain_1.CHAIN_INFO).find(([, info]) => info.chainId === chainId && chain_1.VM_NAMESPACE[info.vm] === namespace)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null); if (!chain) { throw new Error(`Unsupported or unknown CAIP address: ${caip}`); } return { chain, address: formatAddress(chain, rawAddress), }; } // Global cache instance for convertOriginToExecutor const accountCache = new cache_1.Cache(); /** * Determines the Push Network based on the chain type (testnet vs mainnet) */ function getPushNetworkFromChain(chain) { const testnetChains = [ enums_1.CHAIN.ETHEREUM_SEPOLIA, enums_1.CHAIN.SOLANA_TESTNET, enums_1.CHAIN.SOLANA_DEVNET, enums_1.CHAIN.PUSH_TESTNET_DONUT, enums_1.CHAIN.PUSH_TESTNET, enums_1.CHAIN.PUSH_LOCALNET, ]; const mainnetChains = [ enums_1.CHAIN.ETHEREUM_MAINNET, enums_1.CHAIN.SOLANA_MAINNET, enums_1.CHAIN.PUSH_MAINNET, ]; const localnetChains = [enums_1.CHAIN.PUSH_LOCALNET]; if (testnetChains.includes(chain)) { return enums_1.PUSH_NETWORK.TESTNET_DONUT; } else if (mainnetChains.includes(chain)) { return enums_1.PUSH_NETWORK.MAINNET; } else if (localnetChains.includes(chain)) { return enums_1.PUSH_NETWORK.LOCALNET; } else { throw new Error(`Unsupported chain for Push Network mapping: ${chain}`); } } function convertOriginToExecutor(account_1) { return tslib_1.__awaiter(this, arguments, void 0, function* (account, options = { onlyCompute: true }) { const { chain, address } = account; const { vm, chainId } = chain_1.CHAIN_INFO[chain]; if (isPushChain(chain)) { if (options.onlyCompute) { return { address: account.address, deployed: false }; } return { address: account.address }; } // Determine Push Network from the chain const pushNetwork = getPushNetworkFromChain(chain); // Check cache for computed address const cachedAddress = accountCache.get(cache_1.CacheKeys.ueaAddressOnchain(chain, address, pushNetwork, vm)); if (cachedAddress) { if (options.onlyCompute) { // Check cache for deployment status const cachedDeploymentStatus = accountCache.get(cache_1.CacheKeys.deploymentStatus(cachedAddress)); if (cachedDeploymentStatus !== null) { return { address: cachedAddress, deployed: cachedDeploymentStatus, }; } } else { return { address: cachedAddress }; } } let pushChain; if (pushNetwork === enums_1.PUSH_NETWORK.MAINNET) { pushChain = enums_1.CHAIN.PUSH_MAINNET; } else if (pushNetwork === enums_1.PUSH_NETWORK.TESTNET_DONUT || pushNetwork === enums_1.PUSH_NETWORK.TESTNET) { pushChain = enums_1.CHAIN.PUSH_TESTNET_DONUT; } else { pushChain = enums_1.CHAIN.PUSH_LOCALNET; } // Create PushClient to get factory address const pushClient = new push_client_1.PushClient({ rpcUrls: chain_1.CHAIN_INFO[pushChain].defaultRPC, network: pushNetwork, }); const computedAddress = yield pushClient.readContract({ address: pushClient.pushChainInfo.factoryAddress, abi: abi_1.FACTORY_V1, functionName: 'computeUEA', args: [ { chainNamespace: chain_1.VM_NAMESPACE[vm], chainId: chainId, /** * @dev - OwnerKey should be in bytes * for eth - convert hex to bytes * for sol - convert base64 to bytes * for others - not defined yet */ owner: vm === enums_1.VM.EVM ? address : vm === enums_1.VM.SVM ? (0, viem_1.bytesToHex)(anchor_1.utils.bytes.bs58.decode(address)) : address, }, ], }); // Cache the computed address accountCache.set(cache_1.CacheKeys.ueaAddressOnchain(chain, address, pushNetwork, vm), computedAddress); const byteCode = yield pushClient.publicClient.getCode({ address: computedAddress, }); const isDeployed = byteCode !== undefined; // Cache the deployment status accountCache.set(cache_1.CacheKeys.deploymentStatus(computedAddress), isDeployed); if (options.onlyCompute) { return { address: computedAddress, deployed: isDeployed }; } return { address: computedAddress }; }); } /** * Convert Executor to Origin Account * * Given a UEA (executor) address on Push Chain, returns the mapped origin * account and an existence flag. */ function convertExecutorToOriginAccount(ueaAddress) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const RPC_URL = chain_1.PUSH_CHAIN_INFO[enums_1.CHAIN.PUSH_TESTNET_DONUT].defaultRPC[0]; const FACTORY_ADDRESS = chain_1.PUSH_CHAIN_INFO[enums_1.CHAIN.PUSH_TESTNET_DONUT].factoryAddress; // Create viem public client const client = (0, viem_1.createPublicClient)({ transport: (0, viem_1.http)(RPC_URL), }); const originResult = (yield client.readContract({ address: FACTORY_ADDRESS, abi: abi_1.FACTORY_V1, functionName: 'getOriginForUEA', args: [ueaAddress], })); const [account, isUEA] = originResult; if (account.chainNamespace === '' || account.chainId === '' || account.owner === '0x') { return { account: null, exists: isUEA }; } const universalAccount = push_chain_1.PushChain.utils.account.fromChainAgnostic(`${account.chainNamespace}:${account.chainId}:${account.owner}`); if (isUEA) { if (universalAccount.chain.startsWith(chain_1.VM_NAMESPACE[enums_1.VM.SVM])) { // Convert hex-encoded owner to base58 address format const hexBytes = (0, viem_1.hexToBytes)(account.owner); universalAccount.address = anchor_1.utils.bytes.bs58.encode(hexBytes); } } return { account: universalAccount, exists: isUEA }; }); } function isPushChain(chain) { return (chain === enums_1.CHAIN.PUSH_MAINNET || chain === enums_1.CHAIN.PUSH_TESTNET_DONUT || chain === enums_1.CHAIN.PUSH_LOCALNET); } //# sourceMappingURL=account.js.map