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