UNPKG

@wormhole-foundation/sdk-connect

Version:

The core package for the Connect SDK, used in conjunction with 1 or more of the chain packages

356 lines 15.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Wormhole = void 0; const sdk_base_1 = require("@wormhole-foundation/sdk-base"); const sdk_definitions_1 = require("@wormhole-foundation/sdk-definitions"); const circle_api_js_1 = require("./circle-api.js"); const config_js_1 = require("./config.js"); const config_js_2 = require("./config.js"); const cctpTransfer_js_1 = require("./protocols/cctp/cctpTransfer.js"); const tokenTransfer_js_1 = require("./protocols/tokenBridge/tokenTransfer.js"); const resolver_js_1 = require("./routes/resolver.js"); const tasks_js_1 = require("./tasks.js"); const whscan_api_js_1 = require("./whscan-api.js"); class Wormhole { _network; _platforms; _chains; config; constructor(network, platforms, config) { this._network = network; this.config = (0, config_js_1.applyWormholeConfigOverrides)(network, config); this._chains = new Map(); this._platforms = new Map(); for (const p of platforms) { this._platforms.set(p._platform, new p(network, this.config.chains)); } } get network() { return this._network; } /** * Creates a CircleTransfer object to move Native USDC from one chain to another * @param amount the amount to transfer * @param from the address to transfer from * @param to the address to transfer to * @param automatic whether to use automatic delivery * @param payload the payload to send with the transfer * @param nativeGas the amount of native gas to send with the transfer * @returns the CircleTransfer object * @throws Errors if the chain or protocol is not supported */ async circleTransfer(amount, from, to, automatic, payload, nativeGas) { if (automatic && payload) throw new Error("Payload with automatic delivery is not supported"); if (!sdk_base_1.circle.isCircleChain(this.network, from.chain) || !sdk_base_1.circle.isCircleChain(this.network, to.chain) || !sdk_base_1.circle.isCircleSupported(this.network, from.chain) || !sdk_base_1.circle.isCircleSupported(this.network, to.chain)) throw new Error(`Network and chain not supported: ${this.network} ${from.chain} `); // ensure the amount is > fee + native gas if (automatic) { const acb = await this.getChain(from.chain).getAutomaticCircleBridge(); const relayerFee = await acb.getRelayerFee(to.chain); const minAmount = relayerFee + (nativeGas ? nativeGas : 0n); if (amount < minAmount) throw new Error(`Amount must be > ${minAmount} (relayerFee + nativeGas)`); } return await cctpTransfer_js_1.CircleTransfer.from(this, { amount, from, to, automatic, payload, nativeGas, }); } /** * Creates a TokenTransfer object to move a token from one chain to another * @param token the token to transfer * @param amount the amount to transfer * @param from the address to transfer from * @param to the address to transfer to * @param automatic whether to use automatic delivery * @param payload the payload to send with the transfer * @param nativeGas the amount of native gas to send with the transfer * @returns the TokenTransfer object * @throws Errors if the chain or protocol is not supported */ async tokenTransfer(token, amount, from, to, automatic, payload, nativeGas) { return await tokenTransfer_js_1.TokenTransfer.from(this, { token, amount, from, to, automatic, payload, nativeGas, }); } /** * Gets a RouteResolver configured with the routes passed * @param routes the list RouteConstructors to use * @returns the RouteResolver */ resolver(routes) { return new resolver_js_1.RouteResolver(this, routes); } /** * Gets the contract addresses for a given chain * @param chain the chain name * @returns the contract addresses */ getContracts(chain) { return this.config.chains[chain]?.contracts; } /** * Returns the platform object, i.e. the class with platform-specific logic and methods * @param chain the platform name * @returns the platform context class * @throws Errors if platform is not found */ getPlatform(platformName) { const platform = this._platforms.get(platformName); if (!platform) throw new Error(`Not able to retrieve platform ${platformName}. Did it get registered in the constructor?`); return platform; } /** * Returns the chain "context", i.e. the class with chain-specific logic and methods * @param chain the chain name * @returns the chain context class * @throws Errors if context is not found */ getChain(chain) { const platform = (0, sdk_base_1.chainToPlatform)(chain); if (!this._chains.has(chain)) this._chains.set(chain, this.getPlatform(platform).getChain(chain)); return this._chains.get(chain); } /** * Gets the TokenId for a token representation on any chain * These are the Wormhole wrapped token addresses, not necessarily * the canonical version of that token * * @param chain The chain name to get the wrapped token address * @param tokenId The Token ID (chain/address) of the original token * @returns The TokenId on the given chain, null if it does not exist * @throws Errors if the chain is not supported or the token does not exist */ async getWrappedAsset(chain, token) { const ctx = this.getChain(chain); const tb = await ctx.getTokenBridge(); return { chain, address: await tb.getWrappedAsset(token) }; } /** * Taking the original TokenId for some wrapped token chain * These are the Wormhole wrapped token addresses, not necessarily * the canonical version of that token * * @param tokenId The Token ID of the token we're looking up the original asset for * @returns The Original TokenId corresponding to the token id passed, * @throws Errors if the chain is not supported or the token does not exist */ async getOriginalAsset(token) { const ctx = this.getChain(token.chain); const tb = await ctx.getTokenBridge(); return await tb.getOriginalAsset(token.address); } /** * Returns the UniversalAddress of the token. This may require fetching on-chain data. * @param chain The chain to get the UniversalAddress for * @param token The address to get the UniversalAddress for * @returns The UniversalAddress of the token */ async getTokenUniversalAddress(chain, token) { const ctx = this.getChain(chain); const tb = await ctx.getTokenBridge(); return await tb.getTokenUniversalAddress(token); } /** * Returns the native address of the token. This may require fetching on-chain data. * @param chain The chain to get the native address for * @param originChain The chain the token is from / native to * @param token The address to get the native address for * @returns The native address of the token */ async getTokenNativeAddress(chain, originChain, token) { const ctx = this.getChain(chain); const tb = await ctx.getTokenBridge(); return await tb.getTokenNativeAddress(originChain, token); } /** * Gets the number of decimals for a token on a given chain * * @param chain The chain name or id of the token/representation * @param token The token address * @returns The number of decimals */ async getDecimals(chain, token) { const ctx = this.getChain(chain); return await ctx.getDecimals(token); } /** * Fetches the balance of a given token for a wallet * * @param walletAddress The wallet address * @param tokenId The token ID (its home chain and address on the home chain) * @param chain The chain name or id * @returns The token balance of the wormhole asset as a BigNumber */ async getBalance(chain, token, walletAddress) { const ctx = this.getChain(chain); return ctx.getBalance(walletAddress, token); } /** * Gets the associated token account for chains that require it (only Solana currently). * * @param token the TokenId of the token to get the token account for * @param recipient the address of the primary account that may require a separate token account * @returns */ async getTokenAccount(recipient, token) { return this.getChain(recipient.chain).getTokenAccount(recipient.address, token.address); } /** * Gets the Raw VAA Bytes from the API or Guardian RPC, finality must be met before the VAA will be available. * * @param wormholeMessageId The WormholeMessageId corresponding to the VAA to be fetched * @param timeout The total amount of time to wait for the VAA to be available * @returns The VAA bytes if available * @throws Errors if the VAA is not available after the retries */ async getVaaBytes(wormholeMessageId, timeout = config_js_2.DEFAULT_TASK_TIMEOUT) { return await (0, whscan_api_js_1.getVaaBytesWithRetry)(this.config.api, wormholeMessageId, timeout); } /** * Gets a VAA from the API or Guardian RPC, finality must be met before the VAA will be available. * * @param id The WormholeMessageId or Transaction hash corresponding to the VAA to be fetched * @param decodeAs The VAA type to decode the bytes as * @param timeout The total amount of time to wait for the VAA to be available * @returns The VAA if available * @throws Errors if the VAA is not available after the retries */ async getVaa(id, decodeAs, timeout = config_js_2.DEFAULT_TASK_TIMEOUT) { if (typeof id === "string") return await (0, whscan_api_js_1.getVaaByTxHashWithRetry)(this.config.api, id, decodeAs, timeout); return await (0, whscan_api_js_1.getVaaWithRetry)(this.config.api, id, decodeAs, timeout); } /** * Gets if the token bridge transfer VAA has been enqueued by the Governor. * @param id The WormholeMessageId corresponding to the token bridge transfer VAA to check * @returns True if the transfer has been enqueued, false otherwise */ async getIsVaaEnqueued(id) { return await (0, whscan_api_js_1.getIsVaaEnqueued)(this.config.api, id); } /** * Gets the CircleAttestation corresponding to the message hash logged in the transfer transaction. * @param msgHash The keccak256 hash of the message emitted by the circle contract * @param timeout The total amount of time to wait for the VAA to be available * @returns The CircleAttestation as a string, if available * @throws Errors if the CircleAttestation is not available after the retries */ async getCircleAttestation(msgHash, timeout = config_js_2.DEFAULT_TASK_TIMEOUT) { return (0, circle_api_js_1.getCircleAttestationWithRetry)(this.config.circleAPI, msgHash, timeout); } /** * Get the status of a transaction, identified by the chain, emitter address, and sequence number * * @param id the message id for the Wormhole Message to get transaction status for or originating Transaction hash * @returns the TransactionStatus */ async getTransactionStatus(id, timeout = config_js_2.DEFAULT_TASK_TIMEOUT) { let msgid; // No txid endpoint exists to get the status by txhash yet if (typeof id === "string") { const vaa = await (0, whscan_api_js_1.getVaaByTxHashWithRetry)(this.config.api, id, "Uint8Array", timeout); if (!vaa) return null; msgid = { emitter: vaa.emitterAddress, chain: vaa.emitterChain, sequence: vaa.sequence }; } else { msgid = id; } return await (0, whscan_api_js_1.getTransactionStatusWithRetry)(this.config.api, msgid, timeout); } /** * Get recent transactions for an address * * @param address the string formatted address to get transactions for * @returns the TransactionStatus */ async getTransactionsForAddress(address, pageSize = 50, page = 0) { return (0, whscan_api_js_1.getTxsByAddress)(this.config.api, address, pageSize, page); } /** * Parse an address from its canonical string format to a NativeAddress * * @param chain The chain the address is for * @param address The address in canonical string format * @returns The address in the NativeAddress format */ static parseAddress(chain, address) { return (0, sdk_definitions_1.toNative)(chain, address); } /** * Return a string in the canonical chain format representing the address * of a token or account * * @param chainAddress The ChainAddress or TokenId to get a string address * @returns The string address in canonical format for the chain */ static canonicalAddress(chainAddress) { return (0, sdk_definitions_1.canonicalAddress)(chainAddress); } /** * Parse an address from its canonical string format to a NativeAddress * * @param chain The chain the address is for * @param address The native address in canonical string format * @returns The ChainAddress */ static chainAddress(chain, address) { return { chain, address: Wormhole.parseAddress(chain, address) }; } /** * Parse an address from its canonical string format to a NativeAddress * * @param chain The chain the address is for * @param address The native address in canonical string format or the string "native" * @returns The ChainAddress */ static tokenId(chain, address) { return (0, sdk_definitions_1.isNative)(address) ? (0, sdk_definitions_1.nativeTokenId)(chain) : this.chainAddress(chain, address); } /** * Parses all relevant information from a transaction given the sending tx hash and sending chain * * @param chain The sending chain name or context * @param tx The sending transaction hash * @returns The parsed WormholeMessageId */ static async parseMessageFromTx(chain, txid, timeout = config_js_2.DEFAULT_TASK_TIMEOUT) { const task = async () => { try { const msgs = await chain.parseTransaction(txid); // possible the node we hit does not have this data yet // return null to signal retry if (msgs.length === 0) return null; return msgs; } catch (e) { console.error(e); return null; } }; const parsed = await (0, tasks_js_1.retry)(task, chain.config.blockTime, timeout, "WormholeCore:ParseMessageFromTransaction"); if (!parsed) throw new Error(`No WormholeMessageId found for ${txid}`); return parsed; } } exports.Wormhole = Wormhole; //# sourceMappingURL=wormhole.js.map