UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

193 lines 7.51 kB
import { BigNumber } from 'bignumber.js'; import { addressToBytes32, assert, fromWei, strip0x, } from '@hyperlane-xyz/utils'; import { BaseRadixAdapter } from '../../app/MultiProtocolApp.js'; export class RadixTokenAdapter extends BaseRadixAdapter { chainName; multiProvider; addresses; provider; tokenAddress; async getResourceAddress() { return this.tokenAddress; } constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; this.provider = this.getProvider(); this.tokenAddress = addresses.token; } async getBalance(address) { const denom = await this.getResourceAddress(); return this.provider.getBalance({ address, denom, }); } async getMetadata() { // Work around to access the base radix provider getMetadata method const { name, symbol, decimals } = await this.provider['base'].getMetadata({ resource: this.tokenAddress, }); assert(name !== undefined, `name on radix token ${this.tokenAddress} is undefined`); assert(symbol !== undefined, `symbol on radix token ${this.tokenAddress} is undefined`); assert(decimals !== undefined, `divisibility on radix token ${this.tokenAddress} is undefined`); return { name, symbol, 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 denom = await this.getResourceAddress(); const { decimals } = await this.getMetadata(); assert(decimals, `Token decimals not found for "${this.getResourceAddress()}" on chain "${this.chainName}"`); assert(transferParams.fromAccountOwner, `no sender in transfer params`); return this.provider.getTransferTransaction({ signer: transferParams.fromAccountOwner, recipient: transferParams.recipient, denom, amount: fromWei(transferParams.weiAmountOrId.toString(), decimals), }); } async getTotalSupply() { const denom = await this.getResourceAddress(); return this.provider.getTotalSupply({ denom, }); } } export class RadixNativeTokenAdapter extends RadixTokenAdapter { async getMetadata() { const { nativeToken } = this.multiProvider.getChainMetadata(this.chainName); assert(nativeToken, `Native token data is required for ${RadixNativeTokenAdapter.name}`); return { name: nativeToken.name, symbol: nativeToken.symbol, decimals: nativeToken.decimals, }; } } export class RadixHypCollateralAdapter extends RadixTokenAdapter { chainName; multiProvider; addresses; constructor(chainName, multiProvider, addresses) { super(chainName, multiProvider, addresses); this.chainName = chainName; this.multiProvider = multiProvider; this.addresses = addresses; } async getResourceAddress() { const { denom } = await this.provider.getToken({ tokenAddress: this.tokenAddress, }); return denom; } async getMetadata() { // Only works for HypTokens const { name, symbol, decimals } = await this.provider.getToken({ tokenAddress: this.tokenAddress, }); assert(name !== undefined, `name on radix token ${this.tokenAddress} is undefined`); assert(symbol !== undefined, `symbol on radix token ${this.tokenAddress} is undefined`); assert(decimals !== undefined, `divisibility on radix token ${this.tokenAddress} is undefined`); return { name, symbol, decimals, }; } async getDomains() { const { remoteRouters } = await this.provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); return remoteRouters.map((router) => router.receiverDomainId); } async getRouterAddress(domain) { const { remoteRouters } = await this.provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); const router = remoteRouters.find((router) => router.receiverDomainId === domain); if (!router) { throw new Error(`Router with domain "${domain}" not found`); } return Buffer.from(strip0x(router.receiverAddress), 'hex'); } async getAllRouters() { const { remoteRouters } = await this.provider.getRemoteRouters({ tokenAddress: this.tokenAddress, }); return remoteRouters.map((router) => ({ domain: router.receiverDomainId, address: Buffer.from(strip0x(router.receiverAddress), 'hex'), })); } async getBridgedSupply() { return this.provider.getBridgedSupply({ tokenAddress: this.tokenAddress, }); } async quoteTransferRemoteGas({ destination, }) { const { denom: addressOrDenom, amount } = await this.provider.quoteRemoteTransfer({ tokenAddress: this.tokenAddress, destinationDomainId: destination, }); return { igpQuote: { addressOrDenom, amount, }, }; } async populateTransferRemoteTx(params) { assert(params.fromAccountOwner, `no sender in remote transfer params`); if (!params.interchainGas) { params.interchainGas = await this.quoteTransferRemoteGas({ destination: params.destination, }); } const { remoteRouters } = await this.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}`); } if (!params.interchainGas.igpQuote?.addressOrDenom) { throw new Error(`Require denom for max fee, didn't receive and denom in the interchainGas quote`); } return this.provider.getRemoteTransferTransaction({ signer: params.fromAccountOwner, tokenAddress: this.tokenAddress, destinationDomainId: params.destination, recipient: strip0x(addressToBytes32(params.recipient)), amount: params.weiAmountOrId.toString(), customHookAddress: params.customHook, gasLimit: router.gas, maxFee: { denom: params.interchainGas.igpQuote?.addressOrDenom, // convert the attos back to a Decimal with scale 18 amount: new BigNumber(params.interchainGas.igpQuote?.amount.toString()) .div(new BigNumber(10).pow(18)) .toString(), }, }); } } export class RadixHypSyntheticAdapter extends RadixHypCollateralAdapter { } //# sourceMappingURL=RadixTokenAdapter.js.map