UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

192 lines 7.66 kB
import { assert } from '@hyperlane-xyz/utils'; import { BaseCosmosAdapter } from '../../app/MultiProtocolApp.js'; import { CwHypCollateralAdapter } from './CosmWasmTokenAdapter.js'; const COSMOS_IBC_TRANSFER_TIMEOUT = 600_000; // 10 minutes // Interacts with native tokens on a Cosmos chain (e.g TIA on Celestia) export class CosmNativeTokenAdapter extends BaseCosmosAdapter { chainName; multiProvider; addresses; properties; constructor(chainName, multiProvider, addresses, properties) { if (!properties.ibcDenom) throw new Error('Missing properties for CosmNativeTokenAdapter'); super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.properties = properties; } async getBalance(address) { const provider = await this.getProvider(); const coin = await provider.getBalance(address, this.properties.ibcDenom); return BigInt(coin.amount); } async getMetadata() { const { nativeToken } = this.multiProvider.getChainMetadata(this.chainName); assert(nativeToken, `Native token data is required for ${CosmNativeTokenAdapter.name}`); return { name: nativeToken.name, symbol: nativeToken.symbol, decimals: nativeToken.decimals, }; } async getMinimumTransferAmount(_recipient) { return 0n; } async isApproveRequired() { return false; } async isRevokeApprovalRequired(_owner, _spender) { return false; } populateApproveTx(_transferParams) { throw new Error('Approve not required for native tokens'); } async populateTransferTx(transferParams) { return { typeUrl: '/cosmos.bank.v1beta1.MsgSend', value: { fromAddress: transferParams.fromAccountOwner, toAddress: transferParams.recipient, amount: [ { amount: transferParams.weiAmountOrId.toString(), denom: this.properties.ibcDenom, }, ], }, }; } async getTotalSupply() { // Not implemented. return undefined; } } // Interacts with native tokens on a Cosmos chain and adds support for IBC transfers // This implements the IHypTokenAdapter interface but it's an imperfect fit as some // methods don't apply to IBC transfers the way they do for Warp transfers export class CosmIbcTokenAdapter extends CosmNativeTokenAdapter { chainName; multiProvider; addresses; properties; constructor(chainName, multiProvider, addresses, properties) { if (!properties.ibcDenom || !properties.sourcePort || !properties.sourceChannel) throw new Error('Missing properties for CosmNativeIbcTokenAdapter'); super(chainName, multiProvider, addresses, properties); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.properties = properties; } getDomains() { throw new Error('Method not applicable to IBC adapters'); } getRouterAddress(_domain) { throw new Error('Method not applicable to IBC adapters'); } getAllRouters() { throw new Error('Method not applicable to IBC adapters'); } getBridgedSupply() { throw new Error('Method not applicable to IBC adapters'); } async quoteTransferRemoteGas({ destination: _destination, }) { // TODO implement IBC interchain transfer gas estimation here return { igpQuote: { amount: 0n, addressOrDenom: this.properties.ibcDenom }, }; } getMetadata() { throw new Error('Metadata not available to native tokens'); } async populateTransferTx(_transferParams) { throw new Error('TODO not yet implemented'); } async populateTransferRemoteTx(transferParams, memo = '') { if (!transferParams.fromAccountOwner) throw new Error('fromAccountOwner is required for ibc transfers'); const value = { sourcePort: this.properties.sourcePort, sourceChannel: this.properties.sourceChannel, token: { denom: this.properties.ibcDenom, amount: transferParams.weiAmountOrId.toString(), }, sender: transferParams.fromAccountOwner, receiver: transferParams.recipient, // Represented as nano-seconds timeoutTimestamp: BigInt(new Date().getTime() + COSMOS_IBC_TRANSFER_TIMEOUT) * 1000000n, memo, }; return { typeUrl: '/ibc.applications.transfer.v1.MsgTransfer', value, }; } } // A wrapper for the CosmIbcTokenAdapter that adds support auto-initiated warp transfers // A.k.a. 'One-Click' cosmos to evm transfers export class CosmIbcToWarpTokenAdapter extends CosmIbcTokenAdapter { chainName; multiProvider; addresses; properties; constructor(chainName, multiProvider, addresses, properties) { super(chainName, multiProvider, addresses, properties); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.properties = properties; } async quoteTransferRemoteGas({ destination: _destination, }) { // TODO implement IBC interchain transfer gas estimation here return { igpQuote: { amount: 0n, addressOrDenom: this.properties.intermediateIbcDenom, }, }; } async populateTransferRemoteTx(transferParams) { const cwAdapter = new CwHypCollateralAdapter(this.properties.intermediateChainName, this.multiProvider, { token: this.properties.intermediateIbcDenom, warpRouter: this.addresses.intermediateRouterAddress, }); const { interchainGas } = transferParams; assert(interchainGas?.igpQuote.addressOrDenom === this.properties.ibcDenom, 'Only same-denom interchain gas is supported for IBC to Warp transfers'); // This transformation is necessary to ensure the CW adapter recognizes the gas // denom is the same as this adapter's denom (e.g. utia & igp/77...) const intermediateInterchainGas = { addressOrDenom: this.properties.intermediateIbcDenom, amount: interchainGas?.igpQuote.amount || 0n, }; const transfer = await cwAdapter.populateTransferRemoteTx({ ...transferParams, interchainGas: { igpQuote: intermediateInterchainGas }, }); const cwMemo = { wasm: { contract: transfer.contractAddress, msg: transfer.msg, funds: transfer.funds, }, }; const memo = JSON.stringify(cwMemo); if (transfer.funds?.length !== 1) { // Only transfers where the interchain gas denom matches the token are currently supported throw new Error('Expected exactly one denom for IBC to Warp transfer'); } // Grab amount from the funds details which accounts for interchain gas const weiAmountOrId = transfer.funds[0].amount; return super.populateTransferRemoteTx({ ...transferParams, weiAmountOrId, recipient: this.addresses.intermediateRouterAddress, }, memo); } } //# sourceMappingURL=CosmosTokenAdapter.js.map