@hyperlane-xyz/sdk
Version:
The official SDK for the Hyperlane Network
121 lines • 4.99 kB
JavaScript
import { ProtocolType, assert, eqAddress, } from '@hyperlane-xyz/utils';
import { TokenAmount } from './TokenAmount.js';
import { PROTOCOL_TO_HYP_NATIVE_STANDARD, PROTOCOL_TO_NATIVE_STANDARD, TOKEN_COLLATERALIZED_STANDARDS, TOKEN_CROSS_COLLATERAL_STANDARDS, TOKEN_HYP_STANDARDS, TOKEN_MULTI_CHAIN_STANDARDS, TOKEN_NFT_STANDARDS, TOKEN_STANDARD_TO_PROTOCOL, TokenStandard, XERC20_STANDARDS, } from './TokenStandard.js';
import { PROTOCOL_TO_DEFAULT_NATIVE_TOKEN } from './nativeTokenMetadata.js';
export function tokenIdentifiersEqual(left, right) {
if (left == null || right == null)
return left === right;
return left === right || eqAddress(left, right);
}
function matchesUnderlyingAsset(source, target) {
if (source.isCollateralized()) {
if (source.collateralAddressOrDenom &&
tokenIdentifiersEqual(source.collateralAddressOrDenom, target.addressOrDenom)) {
return true;
}
// Only HypNative collateral legitimately lacks collateralAddressOrDenom;
// any other collateralized token missing it is a config bug, not a native match.
if (!source.collateralAddressOrDenom &&
source.isHypNative() &&
(target.isNative() || target.isHypNative())) {
return true;
}
}
return (source.standard === TokenStandard.CosmosIbc &&
target.standard === TokenStandard.CosmosNative &&
tokenIdentifiersEqual(source.addressOrDenom, target.addressOrDenom));
}
export class TokenMetadata {
protocol;
constructor(args) {
Object.assign(this, args);
this.protocol = TOKEN_STANDARD_TO_PROTOCOL[this.standard];
}
static FromChainMetadataNativeToken(chainMetadata) {
const { protocol, name: chainName, logoURI, gasCurrencyCoinGeckoId, } = chainMetadata;
assert(protocol !== ProtocolType.Unknown, 'Cannot create native token for unknown protocol');
const knownProtocol = protocol;
const nativeToken = chainMetadata.nativeToken ||
PROTOCOL_TO_DEFAULT_NATIVE_TOKEN[knownProtocol];
// CAST: TypeScript cannot infer that `new this(...)` returns InstanceType<T>
// for a polymorphic static method bound via `this: T`.
return new this({
chainName,
standard: PROTOCOL_TO_NATIVE_STANDARD[knownProtocol],
addressOrDenom: nativeToken.denom ?? '',
decimals: nativeToken.decimals,
symbol: nativeToken.symbol,
name: nativeToken.name,
logoURI,
coinGeckoId: gasCurrencyCoinGeckoId,
});
}
amount(amount) {
return new TokenAmount(amount, this);
}
isNft() {
return TOKEN_NFT_STANDARDS.includes(this.standard);
}
isNative() {
return Object.values(PROTOCOL_TO_NATIVE_STANDARD).includes(this.standard);
}
isHypNative() {
return Object.values(PROTOCOL_TO_HYP_NATIVE_STANDARD).includes(this.standard);
}
isCollateralized() {
return TOKEN_COLLATERALIZED_STANDARDS.includes(this.standard);
}
isHypToken() {
return TOKEN_HYP_STANDARDS.includes(this.standard);
}
isXerc20() {
return XERC20_STANDARDS.includes(this.standard);
}
isIbcToken() {
return this.standard === TokenStandard.CosmosIbc;
}
isMultiChainToken() {
return TOKEN_MULTI_CHAIN_STANDARDS.includes(this.standard);
}
isCrossCollateralToken() {
return TOKEN_CROSS_COLLATERAL_STANDARDS.has(this.standard);
}
getConnections() {
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) {
const index = this.connections?.findIndex((t) => t.token.equals(token));
if (index !== undefined && index >= 0)
this.connections?.splice(index, 1);
return this;
}
equals(token) {
if (!token)
return false;
if ((this.warpRouteId || token.warpRouteId) &&
this.warpRouteId !== token.warpRouteId) {
return false;
}
return (this.protocol === token.protocol &&
this.chainName === token.chainName &&
this.standard === token.standard &&
this.decimals === token.decimals &&
tokenIdentifiersEqual(this.addressOrDenom, token.addressOrDenom) &&
tokenIdentifiersEqual(this.collateralAddressOrDenom, token.collateralAddressOrDenom));
}
isFungibleWith(token) {
if (!token || token.chainName !== this.chainName)
return false;
if (this.equals(token))
return true;
return (matchesUnderlyingAsset(this, token) || matchesUnderlyingAsset(token, this));
}
}
//# sourceMappingURL=TokenMetadata.js.map