@hyperlane-xyz/sdk
Version:
The official SDK for the Hyperlane Network
189 lines • 7.47 kB
JavaScript
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