UNPKG

@wormhole-foundation/sdk-connect

Version:

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

236 lines 9.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TBTCRoute = void 0; const sdk_base_1 = require("@wormhole-foundation/sdk-base"); const route_js_1 = require("../route.js"); const sdk_definitions_1 = require("@wormhole-foundation/sdk-definitions"); const types_js_1 = require("../../types.js"); const wormhole_js_1 = require("../../wormhole.js"); const common_js_1 = require("../../common.js"); class TBTCRoute extends route_js_1.ManualRoute { static meta = { name: "ManualTBTC", }; static supportedNetworks() { return ["Mainnet"]; } static supportedChains(network) { return sdk_base_1.contracts.tokenBridgeChains(network); } static async supportedDestinationTokens(sourceToken, fromChain, toChain) { if (!(await this.isSourceTokenSupported(sourceToken, fromChain))) { return []; } const tbtcToken = sdk_definitions_1.TBTCBridge.getNativeTbtcToken(toChain.chain); if (tbtcToken) { return [tbtcToken]; } const tb = await toChain.getTokenBridge(); const ethTbtc = sdk_definitions_1.TBTCBridge.getNativeTbtcToken("Ethereum"); try { const wrappedTbtc = await tb.getWrappedAsset(ethTbtc); return [wormhole_js_1.Wormhole.tokenId(toChain.chain, wrappedTbtc.toString())]; } catch (e) { if (e.message.includes("not a wrapped asset")) return []; throw e; } } getDefaultOptions() { return {}; } async validate(request, params) { const amount = request.parseAmount(params.amount); const validatedParams = { normalizedParams: { amount, }, options: params.options ?? this.getDefaultOptions(), ...params, }; return { valid: true, params: validatedParams }; } async quote(request, params) { const eta = sdk_base_1.finality.estimateFinalityTime(request.fromChain.chain) + sdk_base_1.guardians.guardianAttestationEta; return { success: true, params, sourceToken: { token: request.source.id, amount: params.normalizedParams.amount, }, destinationToken: { token: request.destination.id, amount: params.normalizedParams.amount, }, eta, expires: sdk_base_1.time.expiration(24, 0, 0), }; } async initiate(request, signer, quote, to) { const amt = sdk_base_1.amount.units(quote.params.normalizedParams.amount); const isEthereum = request.fromChain.chain === "Ethereum"; const nativeTbtc = sdk_definitions_1.TBTCBridge.getNativeTbtcToken(request.fromChain.chain); const isNativeTbtc = nativeTbtc && (0, sdk_definitions_1.isSameToken)(quote.sourceToken.token, nativeTbtc); if (isNativeTbtc && !isEthereum) { return await this.transferNative(request, signer, to, amt); } if (!isNativeTbtc && isEthereum) { throw new Error("Only tbtc can be transferred on Ethereum"); } if (!isNativeTbtc) { const tb = await request.fromChain.getTokenBridge(); const originalAsset = await tb.getOriginalAsset(quote.sourceToken.token.address); const ethTbtc = sdk_definitions_1.TBTCBridge.getNativeTbtcToken("Ethereum"); if (!(0, sdk_definitions_1.isSameToken)(originalAsset, ethTbtc)) { throw new Error("Can only transfer wrapped tbtc"); } } return await this.transferWrapped(request, signer, to, amt); } async transferNative(request, signer, to, amt) { const sender = wormhole_js_1.Wormhole.parseAddress(signer.chain(), signer.address()); const bridge = await request.fromChain.getTBTCBridge(); const xfer = bridge.transfer(sender, to, amt); const txIds = await (0, common_js_1.signSendWait)(request.fromChain, xfer, signer); const receipt = { originTxs: txIds, state: types_js_1.TransferState.SourceInitiated, from: request.fromChain.chain, to: request.toChain.chain, }; return receipt; } async transferWrapped(request, signer, to, amt) { const sender = wormhole_js_1.Wormhole.parseAddress(signer.chain(), signer.address()); const toGateway = sdk_base_1.contracts.tbtc.get(request.fromChain.network, to.chain); const tb = await request.fromChain.getTokenBridge(); let xfer; if (toGateway) { // payload3 transfer to gateway contract xfer = tb.transfer(sender, wormhole_js_1.Wormhole.chainAddress(request.toChain.chain, toGateway), request.source.id.address, amt, // payload is the recipient address to.address.toUniversalAddress().toUint8Array()); } else { xfer = tb.transfer(sender, to, request.source.id.address, amt); } const txIds = await (0, common_js_1.signSendWait)(request.fromChain, xfer, signer); const receipt = { originTxs: txIds, state: types_js_1.TransferState.SourceInitiated, from: request.fromChain.chain, to: request.toChain.chain, }; return receipt; } async complete(signer, receipt) { if (!(0, types_js_1.isAttested)(receipt)) { throw new Error("The source must be finalized in order to complete the transfer"); } const sender = wormhole_js_1.Wormhole.parseAddress(signer.chain(), signer.address()); const vaa = receipt.attestation.attestation; const toChain = this.wh.getChain(receipt.to); let xfer; if (vaa.payloadLiteral === "TBTCBridge:GatewayTransfer") { const bridge = await toChain.getTBTCBridge(); xfer = bridge.redeem(sender, vaa); } else { const tb = await toChain.getTokenBridge(); // This is really a TokenBridge:Transfer VAA const serialized = (0, sdk_definitions_1.serialize)(vaa); const tbVaa = (0, sdk_definitions_1.deserialize)("TokenBridge:Transfer", serialized); xfer = tb.redeem(sender, tbVaa); } const dstTxIds = await (0, common_js_1.signSendWait)(toChain, xfer, signer); return { ...receipt, state: types_js_1.TransferState.DestinationInitiated, destinationTxs: dstTxIds, }; } async resume(txid) { const vaa = await this.wh.getVaa(txid.txid, sdk_definitions_1.TBTCBridge.getTransferDiscriminator()); if (!vaa) throw new Error("No VAA found for transaction: " + txid); const ethTbtc = sdk_definitions_1.TBTCBridge.getNativeTbtcToken("Ethereum"); const { chain, address } = vaa.payload.token; if (!(0, sdk_definitions_1.isSameToken)(ethTbtc, { chain, address })) { throw new Error("Can only resume tbtc transfers"); } return { originTxs: [txid], state: types_js_1.TransferState.Attested, from: vaa.emitterChain, to: vaa.payload.to.chain, attestation: { id: { chain: vaa.emitterChain, emitter: vaa.emitterAddress, sequence: vaa.sequence, }, attestation: vaa, }, }; } async *track(receipt, timeout) { if ((0, types_js_1.isSourceInitiated)(receipt) || (0, types_js_1.isSourceFinalized)(receipt)) { const { txid } = receipt.originTxs[receipt.originTxs.length - 1]; const vaa = await this.wh.getVaa(txid, sdk_definitions_1.TBTCBridge.getTransferDiscriminator(), timeout); if (!vaa) throw new Error("No VAA found for transaction: " + txid); const msgId = { chain: vaa.emitterChain, emitter: vaa.emitterAddress, sequence: vaa.sequence, }; receipt = { ...receipt, state: types_js_1.TransferState.Attested, attestation: { id: msgId, attestation: vaa, }, }; yield receipt; } if ((0, types_js_1.isAttested)(receipt)) { const toChain = this.wh.getChain(receipt.to); const toBridge = await toChain.getTokenBridge(); const isCompleted = await toBridge.isTransferCompleted(receipt.attestation.attestation); if (isCompleted) { receipt = { ...receipt, state: types_js_1.TransferState.DestinationFinalized, }; yield receipt; } } yield receipt; } static async isSourceTokenSupported(sourceToken, fromChain) { if ((0, sdk_definitions_1.isNative)(sourceToken.address)) { return false; } // Native tbtc is supported const nativeTbtc = sdk_definitions_1.TBTCBridge.getNativeTbtcToken(fromChain.chain); if (nativeTbtc && (0, sdk_definitions_1.isSameToken)(sourceToken, nativeTbtc)) { return true; } // Wormhole-wrapped Ethereum tbtc is supported const tb = await fromChain.getTokenBridge(); try { const originalAsset = await tb.getOriginalAsset(sourceToken.address); return (0, sdk_definitions_1.isSameToken)(originalAsset, sdk_definitions_1.TBTCBridge.getNativeTbtcToken("Ethereum")); } catch (e) { if (e.message.includes("not a wrapped asset")) return false; throw e; } } } exports.TBTCRoute = TBTCRoute; //# sourceMappingURL=tbtc.js.map