@hyperlane-xyz/sdk
Version:
The official SDK for the Hyperlane Network
222 lines • 10.6 kB
JavaScript
import { ProtocolType, assert, isEVMLike, } from '@hyperlane-xyz/utils';
import { TokenAmount } from './TokenAmount.js';
import { TokenConnectionType } from './TokenConnection.js';
import { TokenStandard } from './TokenStandard.js';
import { TokenMetadata } from './TokenMetadata.js';
import { AleoNativeTokenAdapter } from './adapters/AleoTokenAdapter.js';
import { CwNativeTokenAdapter, CwTokenAdapter, } from './adapters/CosmWasmTokenAdapter.js';
import { CosmIbcToWarpTokenAdapter, CosmIbcTokenAdapter, CosmNativeTokenAdapter, } from './adapters/CosmosTokenAdapter.js';
import { EvmNativeTokenAdapter, EvmTokenAdapter, } from './adapters/EvmTokenAdapter.js';
import { M0PortalLiteTokenAdapter } from './adapters/M0PortalLiteTokenAdapter.js';
import { M0PortalTokenAdapter } from './adapters/M0PortalTokenAdapter.js';
import { RadixNativeTokenAdapter, RadixTokenAdapter, } from './adapters/RadixTokenAdapter.js';
import { SealevelNativeTokenAdapter, SealevelTokenAdapter, } from './adapters/SealevelTokenAdapter.js';
import { StarknetTokenAdapter } from './adapters/StarknetTokenAdapter.js';
import { createAleoHypAdapter } from './adapters/aleoHyp.js';
import { createCosmosHypAdapter } from './adapters/cosmosHyp.js';
import { createEvmHypAdapter } from './adapters/evmHyp.js';
import { hasOnlyHyperlaneConnections } from './adapters/hypTokenAdapterUtils.js';
import { createRadixHypAdapter } from './adapters/radixHyp.js';
import { createSealevelHypAdapter } from './adapters/sealevelHyp.js';
import { createStarknetHypAdapter } from './adapters/starknetHyp.js';
import { createTronHypAdapter } from './adapters/tronHyp.js';
export class Token extends TokenMetadata {
amount(amount) {
return new TokenAmount(amount, this);
}
getConnections() {
// CAST: Token instances only store TokenConnection<IToken>; the base
// TokenMetadata type widens this to ITokenMetadata for shared read paths.
return (this.connections || []);
}
getConnectionForChain(chain) {
return this.getConnections().filter((t) => t.token.chainName === chain)[0];
}
addConnection(connection) {
this.connections = [...(this.connections || []), connection];
return this;
}
removeConnection(token) {
super.removeConnection(token);
return this;
}
/**
* Returns a TokenAdapter for the token and multiProvider
* @throws If multiProvider does not contain this token's chain.
* @throws If token is an NFT (TODO NFT Adapter support)
*/
getAdapter(multiProvider) {
const { standard, chainName, addressOrDenom } = this;
assert(!this.isNft(), 'NFT adapters not yet supported');
assert(multiProvider.tryGetChainMetadata(chainName), `Token chain ${chainName} not found in multiProvider`);
if (standard === TokenStandard.ERC20 || standard === TokenStandard.TRC20) {
return new EvmTokenAdapter(chainName, multiProvider, {
token: addressOrDenom,
});
}
else if (standard === TokenStandard.EvmNative ||
standard === TokenStandard.TronNative) {
return new EvmNativeTokenAdapter(chainName, multiProvider, {});
}
else if (standard === TokenStandard.SealevelSpl ||
standard === TokenStandard.SealevelSpl2022) {
return new SealevelTokenAdapter(chainName, multiProvider, {
token: addressOrDenom,
});
}
else if (standard === TokenStandard.SealevelNative) {
return new SealevelNativeTokenAdapter(chainName, multiProvider, {});
}
else if (standard === TokenStandard.CosmosIcs20) {
throw new Error('Cosmos ICS20 token adapter not yet supported');
}
else if (standard === TokenStandard.CosmosNative) {
return new CosmNativeTokenAdapter(chainName, multiProvider, {}, { ibcDenom: addressOrDenom });
}
else if (standard === TokenStandard.CW20) {
return new CwTokenAdapter(chainName, multiProvider, {
token: addressOrDenom,
});
}
else if (standard === TokenStandard.CWNative) {
return new CwNativeTokenAdapter(chainName, multiProvider, {}, addressOrDenom);
}
else if (standard === TokenStandard.StarknetNative) {
return new StarknetTokenAdapter(chainName, multiProvider, {
tokenAddress: addressOrDenom,
});
}
else if (standard === TokenStandard.RadixNative) {
return new RadixNativeTokenAdapter(chainName, multiProvider, {
token: addressOrDenom,
});
}
else if (standard === TokenStandard.AleoNative) {
return new AleoNativeTokenAdapter(chainName, multiProvider, {
token: addressOrDenom,
});
}
else if (this.isHypToken()) {
return this.getHypAdapter(multiProvider);
}
else if (this.isIbcToken()) {
// Passing in a stub connection here because it's not required
// for an IBC adapter to fulfill the ITokenAdapter interface
return this.getIbcAdapter(multiProvider, {
token: this,
sourcePort: 'transfer',
sourceChannel: 'channel-0',
type: TokenConnectionType.Ibc,
});
}
else {
throw new Error(`No adapter found for token standard: ${standard}`);
}
}
/**
* Returns a HypTokenAdapter for the token and multiProvider
* @throws If not applicable to this token's standard.
* @throws If multiProvider does not contain this token's chain.
* @throws If token is an NFT (TODO NFT Adapter support)
*/
getHypAdapter(multiProvider, destination) {
const { standard, chainName, addressOrDenom, collateralAddressOrDenom } = this;
const chainMetadata = multiProvider.tryGetChainMetadata(chainName);
const isConnectedNativeToken = (standard === TokenStandard.EvmNative ||
standard === TokenStandard.TronNative) &&
hasOnlyHyperlaneConnections(this);
assert(this.isMultiChainToken() || isConnectedNativeToken, `Token standard ${standard} not applicable to hyp adapter`);
assert(!this.isNft(), 'NFT adapters not yet supported');
assert(chainMetadata, `Token chain ${chainName} not found in multiProvider`);
const hypAdapter = createEvmHypAdapter(multiProvider, this) ||
createTronHypAdapter(multiProvider, this) ||
createSealevelHypAdapter(multiProvider, this) ||
createCosmosHypAdapter(multiProvider, this) ||
createStarknetHypAdapter(multiProvider, this) ||
createRadixHypAdapter(multiProvider, this) ||
createAleoHypAdapter(multiProvider, this);
if (hypAdapter) {
return hypAdapter;
}
else if (standard === TokenStandard.CosmosIbc) {
assert(destination, 'destination required for IBC token adapters');
const connection = this.getConnectionForChain(destination);
assert(connection, `No connection found for chain ${destination}`);
return this.getIbcAdapter(multiProvider, connection);
}
else if (standard === TokenStandard.EvmM0PortalLite ||
standard === TokenStandard.TronM0PortalLite) {
assert(collateralAddressOrDenom, 'collateralAddressOrDenom (mToken address) required for M0PortalLite');
return new M0PortalLiteTokenAdapter(multiProvider, chainName, addressOrDenom, // portal address
collateralAddressOrDenom);
}
else if (standard === TokenStandard.EvmM0Portal) {
assert(collateralAddressOrDenom, 'collateralAddressOrDenom (mToken address) required for M0Portal');
return new M0PortalTokenAdapter(multiProvider, chainName, addressOrDenom, // portal address
collateralAddressOrDenom);
}
else {
throw new Error(`No hyp adapter found for token standard: ${standard}`);
}
}
getIbcAdapter(multiProvider, connection) {
if (connection.type === TokenConnectionType.Ibc) {
const { sourcePort, sourceChannel } = connection;
return new CosmIbcTokenAdapter(this.chainName, multiProvider, {}, { ibcDenom: this.addressOrDenom, sourcePort, sourceChannel });
}
else if (connection.type === TokenConnectionType.IbcHyperlane) {
const { sourcePort, sourceChannel, intermediateChainName, intermediateIbcDenom, intermediateRouterAddress, } = connection;
const destinationRouterAddress = connection.token.addressOrDenom;
return new CosmIbcToWarpTokenAdapter(this.chainName, multiProvider, {
intermediateRouterAddress,
destinationRouterAddress,
}, {
ibcDenom: this.addressOrDenom,
sourcePort,
sourceChannel,
intermediateIbcDenom,
intermediateChainName,
});
}
else {
throw new Error(`Unsupported IBC connection type: ${connection.type}`);
}
}
/**
* Convenience method to create an adapter and return an account balance
*/
async getBalance(multiProvider, address) {
const adapter = this.getAdapter(multiProvider);
const balance = await adapter.getBalance(address);
return new TokenAmount(balance, this);
}
}
export function getCollateralTokenAdapter({ chainName, multiProvider, tokenAddress, }) {
const protocolType = multiProvider.getProtocol(chainName);
// ERC20s
if (isEVMLike(protocolType)) {
return new EvmTokenAdapter(chainName, multiProvider, {
token: tokenAddress,
});
}
// SPL and SPL2022
else if (protocolType === ProtocolType.Sealevel) {
return new SealevelTokenAdapter(chainName, multiProvider, {
token: tokenAddress,
});
}
else if (protocolType === ProtocolType.Starknet) {
return new StarknetTokenAdapter(chainName, multiProvider, {
tokenAddress,
});
}
else if (protocolType === ProtocolType.Radix) {
return new RadixTokenAdapter(chainName, multiProvider, {
token: tokenAddress,
});
}
else {
throw new Error(`Unsupported protocol ${protocolType} for retrieving collateral token adapter on chain ${chainName}`);
}
}
//# sourceMappingURL=Token.js.map