UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

189 lines 7.47 kB
import { ProtocolType, addressToBytes32, assert, convertToProtocolAddress, isAddressCosmos, } from '@hyperlane-xyz/utils'; import { BaseCosmNativeAdapter } from '../../app/MultiProtocolApp.js'; import { PROTOCOL_TO_DEFAULT_NATIVE_TOKEN } from '../nativeTokenMetadata.js'; class CosmosModuleTokenAdapter extends BaseCosmNativeAdapter { chainName; multiProvider; addresses; properties; // use getter so Tokens which extend this base class // can overwrite this denom async getDenom() { return this.properties.denom; } constructor(chainName, multiProvider, addresses, properties) { if (!properties.denom) { 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 denom = await this.getDenom(); // if the address is a cosmos address we can simply read the account balance // of that address. The address can also be an ETH address format indicating // that the balance of a Hyp Token Contract should be returned. In this case // we get the token by it's id and return the bridged supply which equals the // balance the token has. if (isAddressCosmos(address)) { return provider.getBalance({ address, denom, }); } else { return provider.getBridgedSupply({ tokenAddress: address }); } } async getMetadata() { const token = await this.multiProvider.getNativeToken(this.chainName); return { symbol: token.symbol, name: token.name, decimals: token.decimals, }; } async getMinimumTransferAmount(_recipient) { return 0n; } async isApproveRequired() { return false; } populateApproveTx(_transferParams) { throw new Error('Approve not required for native tokens'); } async isRevokeApprovalRequired(_, __) { return false; } async populateTransferTx(transferParams) { const provider = await this.getProvider(); const denom = await this.getDenom(); assert(transferParams.fromAccountOwner, `no sender in transfer params`); return provider.getTransferTransaction({ signer: transferParams.fromAccountOwner, recipient: transferParams.recipient, denom, amount: transferParams.weiAmountOrId.toString(), }); } async getTotalSupply() { const provider = await this.getProvider(); const denom = await this.getDenom(); return provider.getTotalSupply({ denom }); } } export class CosmNativeHypCollateralAdapter extends CosmosModuleTokenAdapter { chainName; multiProvider; addresses; tokenAddress; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses, { denom: PROTOCOL_TO_DEFAULT_NATIVE_TOKEN[ProtocolType.CosmosNative].denom, }); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.tokenAddress = addresses.token; } async getDenom() { const provider = await this.getProvider(); const { denom } = await provider.getToken({ tokenAddress: this.tokenAddress, }); return denom; } async getDomains() { const provider = await this.getProvider(); const remoteRouters = await provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); return remoteRouters.remoteRouters.map((router) => router.receiverDomainId); } async getRouterAddress(domain) { const provider = await this.getProvider(); const remoteRouters = await provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); const router = remoteRouters.remoteRouters.find((router) => router.receiverDomainId === domain); if (!router) { throw new Error(`Router with domain "${domain}" not found`); } return Buffer.from(router.receiverAddress); } async getAllRouters() { const provider = await this.getProvider(); const remoteRouters = await provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); return remoteRouters.remoteRouters.map((router) => ({ domain: router.receiverDomainId, address: Buffer.from(router.receiverAddress), })); } async getBridgedSupply() { const provider = await this.getProvider(); return await provider.getBridgedSupply({ tokenAddress: this.tokenAddress, }); } async quoteTransferRemoteGas({ destination, customHook, }) { const provider = await this.getProvider(); const { denom: addressOrDenom, amount } = await provider.quoteRemoteTransfer({ tokenAddress: this.tokenAddress, destinationDomainId: destination, customHookAddress: customHook, }); return { igpQuote: { addressOrDenom, amount, }, }; } async populateTransferRemoteTx(params) { if (!params.interchainGas) { params.interchainGas = await this.quoteTransferRemoteGas({ destination: params.destination, customHook: params.customHook, }); } const provider = await this.getProvider(); const { remoteRouters } = await provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); const router = remoteRouters.find((router) => router.receiverDomainId === params.destination); if (!router) { throw new Error(`Failed to find remote router for token id and destination: ${this.tokenAddress},${params.destination}`); } const { igpQuote } = params.interchainGas; if (!igpQuote.addressOrDenom) { throw new Error(`Require denom for max fee, didn't receive and denom in the interchainGas quote`); } const destinationMetadata = this.multiProvider.getChainMetadata(params.destination); const destinationProtocol = destinationMetadata.protocol; return provider.getRemoteTransferTransaction({ signer: params.fromAccountOwner, tokenAddress: this.tokenAddress, destinationDomainId: params.destination, recipient: addressToBytes32(convertToProtocolAddress(params.recipient, destinationMetadata.protocol, destinationMetadata.bech32Prefix), destinationProtocol), amount: params.weiAmountOrId.toString(), customHookAddress: params.customHook, gasLimit: router.gas, maxFee: { denom: igpQuote.addressOrDenom || '', amount: igpQuote.amount.toString(), }, }); } } export class CosmNativeHypSyntheticAdapter extends CosmNativeHypCollateralAdapter { async getTokenDenom() { return `hyperlane/${this.tokenAddress}`; } } //# sourceMappingURL=CosmosModuleTokenAdapter.js.map