UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

332 lines 10.8 kB
import { addressToBytes32, assert, strip0x, } from '@hyperlane-xyz/utils'; import { BaseCosmWasmAdapter } from '../../app/MultiProtocolApp.js'; // Interacts with IBC denom tokens in CosmWasm export class CwNativeTokenAdapter extends BaseCosmWasmAdapter { chainName; multiProvider; addresses; denom; constructor(chainName, multiProvider, addresses, denom) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.denom = denom; } async getBalance(address) { const provider = await this.getProvider(); const balance = await provider.getBalance(address, this.denom); return BigInt(balance.amount); } async getMetadata() { throw new Error('Metadata not available to native tokens'); } async getMinimumTransferAmount(_recipient) { return 0n; } async isApproveRequired() { return false; } async isRevokeApprovalRequired(_owner, _spender) { return false; } async populateApproveTx(_params) { throw new Error('Approve not required for native tokens'); } async populateTransferTx({ recipient, weiAmountOrId, }) { // TODO: check if this works with execute instruction? (contract type, empty message) return { contractAddress: recipient, msg: {}, funds: [ { amount: weiAmountOrId.toString(), denom: this.denom, }, ], }; } async getTotalSupply() { // Not implemented. return undefined; } } // Interacts with CW20/721 contracts export class CwTokenAdapter extends BaseCosmWasmAdapter { chainName; multiProvider; addresses; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; } async queryToken(msg) { const provider = await this.getProvider(); const response = await provider.queryContractSmart(this.addresses.token, msg); return response; } prepareToken(msg, funds) { return { contractAddress: this.addresses.token, msg, funds, }; } async getBalance(address) { const provider = await this.getProvider(); const balance = await provider.getBalance(address, this.addresses.token); return BigInt(balance.amount); } async getMetadata() { return this.queryToken({ token_info: {}, }); } async getMinimumTransferAmount(_recipient) { return 0n; } async isApproveRequired() { return false; } async isRevokeApprovalRequired(_owner, _spender) { return false; } async populateApproveTx({ weiAmountOrId, recipient, }) { // TODO: check existing allowance return this.prepareToken({ increase_allowance: { spender: recipient, amount: weiAmountOrId.toString(), expires: { never: {}, }, }, }); } async populateTransferTx({ weiAmountOrId, recipient, }) { return this.prepareToken({ transfer: { recipient, amount: weiAmountOrId.toString(), }, }); } async getTotalSupply() { // Not implemented. return undefined; } } export class CwHypSyntheticAdapter extends CwTokenAdapter { chainName; multiProvider; addresses; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; } async queryRouter(msg) { const provider = await this.getProvider(); const response = await provider.queryContractSmart(this.addresses.warpRouter, msg); return response; } prepareRouter(msg, funds) { return { contractAddress: this.addresses.warpRouter, msg, funds, }; } async getTokenType() { const resp = await this.queryRouter({ token_default: { token_type: {}, }, }); return resp.type; } async getInterchainSecurityModule() { throw new Error('Router does not support ISM config yet.'); } async getOwner() { const resp = await this.queryRouter({ ownable: { get_owner: {}, }, }); return resp.owner; } async getDomains() { const resp = await this.queryRouter({ router: { domains: {}, }, }); return resp.domains; } async getRouterAddress(domain) { const resp = await this.queryRouter({ router: { get_route: { domain, }, }, }); const route = resp.route.route; if (!route) { throw new Error(`No route found for domain ${domain}`); } return Buffer.from(route, 'hex'); } async getAllRouters() { const resp = await this.queryRouter({ router: { list_routes: {}, }, }); return resp.routes .filter((r) => r.route != null) .map((r) => ({ domain: r.domain, address: Buffer.from(r.route, 'hex'), })); } getBridgedSupply() { return this.getTotalSupply(); } async quoteTransferRemoteGas(_destination) { // TODO this may require separate queries to get the hook and/or mailbox // before making a query for the QuoteDispatchResponse // Punting on this given that only static quotes are used for now // const resp = await this.queryRouter<QuoteDispatchResponse>({ // router: { // TODO: {}, // }, // }); // return { // amount: BigInt(resp.gas_amount?.amount || 0), // addressOrDenom: resp.gas_amount?.denom, // }; throw new Error('CW adapter quoteTransferRemoteGas method not implemented'); } async populateTransferRemoteTx({ destination, recipient, weiAmountOrId, interchainGas, }) { if (!interchainGas) interchainGas = await this.quoteTransferRemoteGas(destination); const { addressOrDenom: igpDenom, amount: igpAmount } = interchainGas; assert(igpDenom, 'Interchain gas denom required for Cosmos'); return this.prepareRouter({ transfer_remote: { dest_domain: destination, recipient: strip0x(addressToBytes32(recipient)), amount: weiAmountOrId.toString(), }, }, [ { amount: igpAmount.toString(), denom: igpDenom, }, ]); } } export class CwHypNativeAdapter extends CwNativeTokenAdapter { chainName; multiProvider; addresses; cw20adapter; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses, ''); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.cw20adapter = new CwHypSyntheticAdapter(chainName, multiProvider, { token: '', warpRouter: addresses.warpRouter, }); } async getBalance(address) { const provider = await this.getProvider(); const denom = await this.getDenom(); const balance = await provider.getBalance(address, denom); return BigInt(balance.amount); } async getInterchainSecurityModule() { return this.cw20adapter.getInterchainSecurityModule(); } async getOwner() { return this.cw20adapter.getOwner(); } async getDomains() { return this.cw20adapter.getDomains(); } async getRouterAddress(domain) { return this.cw20adapter.getRouterAddress(domain); } async getAllRouters() { return this.cw20adapter.getAllRouters(); } getBridgedSupply() { return this.getBalance(this.addresses.warpRouter); } quoteTransferRemoteGas(destination) { return this.cw20adapter.quoteTransferRemoteGas(destination); } async getDenom() { const tokenType = await this.cw20adapter.getTokenType(); if ('native' in tokenType) { if ('fungible' in tokenType.native) { return tokenType.native.fungible.denom; } } throw new Error(`Token type not supported: ${tokenType}`); } async populateTransferRemoteTx({ destination, recipient, weiAmountOrId, interchainGas, }) { const collateralDenom = await this.getDenom(); if (!interchainGas) interchainGas = await this.quoteTransferRemoteGas(destination); const { addressOrDenom: igpDenom, amount: igpAmount } = interchainGas; assert(igpDenom, 'Interchain gas denom required for Cosmos'); // If more than one denom is used as funds, they must be sorted by the denom const funds = collateralDenom === igpDenom ? [ { amount: (BigInt(weiAmountOrId) + igpAmount).toString(), denom: collateralDenom, }, ] : [ { amount: weiAmountOrId.toString(), denom: collateralDenom, }, { amount: igpAmount.toString(), denom: igpDenom, }, ].sort((a, b) => a.denom.localeCompare(b.denom)); return this.cw20adapter.prepareRouter({ transfer_remote: { dest_domain: destination, recipient: strip0x(addressToBytes32(recipient)), amount: weiAmountOrId.toString(), }, }, funds); } } export class CwHypCollateralAdapter extends CwHypNativeAdapter { chainName; multiProvider; addresses; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; } async isRevokeApprovalRequired(_owner, _spender) { return false; } } //# sourceMappingURL=CosmWasmTokenAdapter.js.map