UNPKG

@wormhole-foundation/sdk-cosmwasm-tokenbridge

Version:

SDK for EVM chains, used in conjunction with @wormhole-foundation/sdk

239 lines 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CosmwasmTokenBridge = void 0; const sdk_connect_1 = require("@wormhole-foundation/sdk-connect"); const sdk_cosmwasm_1 = require("@wormhole-foundation/sdk-cosmwasm"); require("@wormhole-foundation/sdk-cosmwasm-core"); class CosmwasmTokenBridge { network; chain; rpc; contracts; tokenBridge; translator; constructor(network, chain, rpc, contracts) { this.network = network; this.chain = chain; this.rpc = rpc; this.contracts = contracts; const tokenBridgeAddress = this.contracts.tokenBridge; if (!tokenBridgeAddress) throw new Error(`Wormhole Token Bridge contract for domain ${chain} not found`); this.tokenBridge = tokenBridgeAddress; // May be undefined, thats ok this.translator = this.contracts.translator; // But it cannot be an empty string (misconfiguration) if (this.translator !== undefined && this.translator === "") throw new Error("Translator address may be undefined but not empty string"); } static async fromRpc(rpc, config) { const [network, chain] = await sdk_cosmwasm_1.CosmwasmPlatform.chainFromRpc(rpc); const conf = config[chain]; if (conf.network !== network) throw new Error(`Network mismatch: ${conf.network} != ${network}`); return new CosmwasmTokenBridge(network, chain, rpc, config[chain].contracts); } async isWrappedAsset(token) { try { await this.getOriginalAsset(token); return true; } catch { } return false; } async hasWrappedAsset(token) { try { await this.getWrappedAsset(token); return true; } catch { } return false; } async getWrappedAsset(token) { if (token.chain === this.chain) throw new Error(`Expected foreign chain, got ${token.chain}`); if ((0, sdk_connect_1.isNative)(token.address)) throw new Error("Native asset cannot be a wrapped asset"); const base64Addr = sdk_connect_1.encoding.b64.encode(token.address.toUniversalAddress().toUint8Array()); const { address } = await this.rpc.queryContractSmart(this.tokenBridge, { wrapped_registry: { chain: (0, sdk_connect_1.toChainId)(token.chain), address: base64Addr, }, }); return (0, sdk_connect_1.toNative)(this.chain, address); } async getOriginalAsset(token) { let wrappedAddress = new sdk_cosmwasm_1.CosmwasmAddress(token); if (wrappedAddress.denomType === "factory") wrappedAddress = sdk_cosmwasm_1.Gateway.factoryToCw20(wrappedAddress); const response = await this.rpc.queryContractSmart(wrappedAddress.toString(), { wrapped_asset_info: {}, }); const origChain = (0, sdk_connect_1.toChain)(response.asset_chain); const origAddress = sdk_connect_1.encoding.b64.decode(response.asset_address); return { chain: origChain, address: new sdk_connect_1.UniversalAddress(new Uint8Array(origAddress)), }; } async getTokenUniversalAddress(token) { return new sdk_cosmwasm_1.CosmwasmAddress(token).toUniversalAddress(); } async getTokenNativeAddress(originChain, token) { return new sdk_cosmwasm_1.CosmwasmAddress(token).toNative(); } async isTransferCompleted(vaa) { const data = sdk_connect_1.encoding.b64.encode((0, sdk_connect_1.serialize)(vaa)); const result = await this.rpc.queryContractSmart(this.tokenBridge, { is_vaa_redeemed: { vaa: data }, }); return result.is_redeemed; } async *createAttestation(token, payer) { if (!payer) throw new Error("Payer required to create attestation"); const tokenStr = new sdk_cosmwasm_1.CosmwasmAddress(token).toString(); const payerStr = new sdk_cosmwasm_1.CosmwasmAddress(payer).toString(); // TODO nonce? const nonce = 0; const assetInfo = (0, sdk_connect_1.isNative)(token) ? { native_token: { denom: sdk_cosmwasm_1.CosmwasmPlatform.getNativeDenom(this.network, this.chain), }, } : { token: { contract_addr: tokenStr }, }; yield this.createUnsignedTx({ msgs: [ (0, sdk_cosmwasm_1.buildExecuteMsg)(payerStr, this.tokenBridge, { create_asset_meta: { asset_info: assetInfo, nonce }, }), ], fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain), memo: "Wormhole - Create Attestation", }, "TokenBridge.createAttestation"); } async *submitAttestation(vaa, payer) { if (!payer) throw new Error("Payer required to submit attestation"); const payerStr = new sdk_cosmwasm_1.CosmwasmAddress(payer).toString(); yield this.createUnsignedTx({ msgs: [ (0, sdk_cosmwasm_1.buildExecuteMsg)(payerStr, this.tokenBridge, { submit_vaa: { data: (0, sdk_connect_1.serialize)(vaa) }, }), ], fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain), memo: "Wormhole - Submit Attestation", }, "TokenBridge.submitAttestation"); } async *transfer(sender, recipient, token, amount, payload) { const nonce = Math.round(Math.random() * 100000); const relayerFee = "0"; const recipientChainId = (0, sdk_connect_1.toChainId)(recipient.chain); // TODO: do we need to use the _native_ address for cosmos chains? const encodedRecipient = sdk_connect_1.encoding.b64.encode(recipient.address.toUniversalAddress().toUint8Array()); const denom = sdk_cosmwasm_1.CosmwasmPlatform.getNativeDenom(this.network, this.chain); const isNativeToken = (0, sdk_connect_1.isNative)(token); let tokenAddress = isNativeToken ? denom : token.toString(); if (tokenAddress.startsWith("factory")) tokenAddress = sdk_cosmwasm_1.Gateway.factoryToCw20(new sdk_cosmwasm_1.CosmwasmAddress(tokenAddress)).toString(); const senderAddress = new sdk_cosmwasm_1.CosmwasmAddress(sender).toString(); const mk_initiate_transfer = (info) => { const common = { asset: { amount: amount.toString(), info, }, recipient_chain: recipientChainId, recipient: encodedRecipient, fee: relayerFee, nonce: nonce, }; return payload ? { initiate_transfer_with_payload: { ...common, payload: sdk_connect_1.encoding.b64.encode(payload) }, } : { initiate_transfer: common, }; }; // this.createConvertAndTransferMessage( // senderAddress, // targetChain, // targetAddress, // relayerFee, // { denom: Gateway.cw20ToFactory(token), amount }, // ) if (isNativeToken) { const msgs = [ (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, { deposit_tokens: {} }, [ { amount: amount.toString(), denom: tokenAddress }, ]), (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, mk_initiate_transfer({ native_token: { denom: tokenAddress }, })), ]; yield this.createUnsignedTx({ msgs, fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain), memo: "Wormhole - Initiate Native Transfer", }, "TokenBridge.transferNative"); } else { const msgs = [ (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, tokenAddress, { increase_allowance: { spender: this.tokenBridge, amount: amount.toString(), expires: { never: {} }, }, }), (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, mk_initiate_transfer({ token: { contract_addr: tokenAddress }, }), [{ amount: amount.toString(), denom: tokenAddress }]), ]; yield this.createUnsignedTx({ msgs, fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain), memo: "Wormhole - Initiate Transfer", }, "TokenBridge.transfer"); } } async *redeem(sender, vaa, unwrapNative = true) { // TODO: unwrapNative const data = sdk_connect_1.encoding.b64.encode((0, sdk_connect_1.serialize)(vaa)); const senderAddress = new sdk_cosmwasm_1.CosmwasmAddress(sender).toString(); const toTranslator = this.translator && new sdk_cosmwasm_1.CosmwasmAddress(this.translator).toUniversalAddress().equals(vaa.payload.to.address); const msg = toTranslator ? (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.translator, { complete_transfer_and_convert: { vaa: data, }, }) : (0, sdk_cosmwasm_1.buildExecuteMsg)(senderAddress, this.tokenBridge, { submit_vaa: { data }, }); yield this.createUnsignedTx({ msgs: [msg], fee: (0, sdk_cosmwasm_1.computeFee)(this.network, this.chain), memo: "Wormhole - Complete Transfer", }, "TokenBridge.redeem"); return; } async parseTransactionDetails(txid) { throw new Error("Not implemented"); } async getWrappedNative() { return (0, sdk_connect_1.toNative)(this.chain, sdk_cosmwasm_1.CosmwasmPlatform.getNativeDenom(this.network, this.chain)); } createUnsignedTx(txReq, description, parallelizable = false) { return new sdk_cosmwasm_1.CosmwasmUnsignedTransaction(txReq, this.network, this.chain, description, parallelizable); } } exports.CosmwasmTokenBridge = CosmwasmTokenBridge; //# sourceMappingURL=tokenBridge.js.map