import { isAddressEqual } from 'viem'; import type { BaseCurrencyParams, SerializableErc20TokenType } from './base-currency.js'; import type { Currency } from './currency-type.js'; import { BaseCurrency } from './base-currency.js'; import { invariant } from '../../utils.js'; /** * Parameters for creating a token */ type TokenParams = BaseCurrencyParams & { address: `0x${string}`; }; /** * Represents an ERC20 token with a unique address and some metadata. */ export class Token extends BaseCurrency { public readonly isNative: false = false as const; public readonly isToken: true = true as const; /** * The contract address on the chain on which this token lives */ public readonly address: `0x${string}`; /** * @param chainId {@link BaseCurrency#chainId} * @param address The contract address on the chain on which this token lives * @param decimals {@link BaseCurrency#decimals} * @param symbol {@link BaseCurrency#symbol} * @param name {@link BaseCurrency#name} * @param bypassChecksum If true it only checks for length === 42, startsWith 0x and contains only hex characters */ public constructor(params: TokenParams) { super(params); this.address = params.address; } /** * Returns true if the two tokens are equivalent, i.e. have the same chainId and address. * @param other other token to compare */ public equals(other: Currency): boolean { return other.isToken && this.chainId === other.chainId && isAddressEqual(this.address, other.address); } /** * Returns true if the address of this token sorts before the address of the other token * @param other other token to compare * @throws if the tokens have the same address * @throws if the tokens are on different chains */ public sortsBefore(other: Token): boolean { invariant(this.chainId === other.chainId, 'DIFFERENT_CHAIN_IDS'); invariant(this.address !== other.address, 'DIFFERENT_ADDRESSES'); return this.address.toLowerCase() < other.address.toLowerCase(); } /** * Return this token, which does not need to be wrapped */ public get wrapped(): Token { return this; } /** * Returns a serializable object representation of the token */ public toObject(): SerializableErc20TokenType { return { address: this.address, chainId: this.chainId, decimals: this.decimals, symbol: this.symbol, name: this.name, }; } public static fromObject(object: SerializableErc20TokenType) { return new Token({ address: object.address, chainId: object.chainId, decimals: object.decimals, symbol: object.symbol, name: object.name, }); } }