@mimicprotocol/lib-ts 0.0.1-rc.9 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/README.md +7 -7
  3. package/constants.d.ts +1 -0
  4. package/constants.js +1 -0
  5. package/index.ts +3 -0
  6. package/package.json +18 -4
  7. package/src/chains/Arbitrum.ts +14 -0
  8. package/src/chains/Avalanche.ts +15 -0
  9. package/src/chains/BNB.ts +15 -0
  10. package/src/chains/Base.ts +14 -0
  11. package/src/chains/BaseSepolia.ts +7 -0
  12. package/src/chains/Ethereum.ts +7 -7
  13. package/src/chains/Gnosis.ts +14 -0
  14. package/src/chains/Optimism.ts +7 -7
  15. package/src/chains/Polygon.ts +10 -7
  16. package/src/chains/Sonic.ts +13 -0
  17. package/src/chains/index.ts +7 -0
  18. package/src/context/Context.ts +102 -7
  19. package/src/environment.ts +165 -53
  20. package/src/evm.ts +5 -4
  21. package/src/helpers/BorshDeserializer.ts +133 -0
  22. package/src/helpers/consensus.ts +35 -0
  23. package/src/helpers/constants.ts +7 -1
  24. package/src/helpers/index.ts +5 -0
  25. package/src/helpers/math.ts +20 -0
  26. package/src/helpers/serialize.ts +5 -125
  27. package/src/helpers/strings.ts +82 -5
  28. package/src/intents/Call/EvmCall.ts +283 -0
  29. package/src/intents/Call/SvmCall.ts +278 -0
  30. package/src/intents/Call/index.ts +2 -0
  31. package/src/intents/Intent.ts +178 -5
  32. package/src/intents/Swap.ts +136 -44
  33. package/src/intents/Transfer.ts +103 -58
  34. package/src/log.ts +83 -0
  35. package/src/queries/EvmCallQuery.ts +43 -0
  36. package/src/queries/QueryResponse.ts +26 -0
  37. package/src/queries/RelevantTokensQuery.ts +82 -0
  38. package/src/queries/SubgraphQuery.ts +50 -0
  39. package/src/queries/SvmAccountsInfoQuery.ts +65 -0
  40. package/src/queries/TokenPriceQuery.ts +47 -0
  41. package/src/queries/index.ts +6 -1
  42. package/src/storage/index.ts +1 -0
  43. package/src/storage/storage.ts +46 -0
  44. package/src/svm.ts +27 -0
  45. package/src/tokens/BlockchainToken.ts +108 -0
  46. package/src/tokens/DenominationToken.ts +70 -0
  47. package/src/tokens/ERC20Token.ts +192 -0
  48. package/src/tokens/SPLToken.ts +162 -0
  49. package/src/tokens/Token.ts +55 -155
  50. package/src/tokens/TokenAmount.ts +72 -30
  51. package/src/tokens/TokenProvider.ts +54 -0
  52. package/src/tokens/Tokens.ts +186 -0
  53. package/src/tokens/USD.ts +9 -6
  54. package/src/tokens/index.ts +6 -0
  55. package/src/types/Address.ts +86 -14
  56. package/src/types/BigInt.ts +14 -22
  57. package/src/types/ByteArray.ts +41 -3
  58. package/src/types/Bytes.ts +7 -0
  59. package/src/types/ChainId.ts +9 -1
  60. package/src/types/Option.ts +35 -0
  61. package/src/types/Result.ts +68 -0
  62. package/src/types/TriggerType.ts +4 -0
  63. package/src/types/evm/EvmDecodeParam.ts +7 -0
  64. package/src/types/evm/EvmEncodeParam.ts +31 -0
  65. package/src/types/evm/index.ts +2 -0
  66. package/src/types/index.ts +8 -2
  67. package/src/types/svm/SvmAccountInfo.ts +32 -0
  68. package/src/types/svm/SvmAccountMeta.ts +28 -0
  69. package/src/types/svm/SvmFindProgramAddress.ts +32 -0
  70. package/src/types/svm/SvmMint.ts +44 -0
  71. package/src/types/svm/SvmPdaSeed.ts +19 -0
  72. package/src/types/svm/SvmTokenMetadataData.ts +29 -0
  73. package/src/types/svm/index.ts +5 -0
  74. package/src/intents/Call.ts +0 -238
  75. package/src/queries/Call.ts +0 -16
  76. package/src/types/EvmDecodeParam.ts +0 -30
  77. package/src/types/EvmEncodeParam.ts +0 -54
@@ -1,191 +1,91 @@
1
- import { environment } from '../environment'
2
- import { evm } from '../evm'
3
- import { join, NATIVE_ADDRESS, parseCSV, Serializable, serialize } from '../helpers'
4
- import { Address, ChainId, EvmDecodeParam } from '../types'
1
+ import { Address, ChainId } from '../types'
5
2
 
6
3
  /**
7
4
  * Represents a token on a blockchain network including data like symbol, decimals, and address.
8
- * Supports both ERC-20 and native tokens.
5
+ * Supports both ERC-20, SPL, and denomination tokens.
9
6
  */
10
- export class Token implements Serializable {
11
- public static readonly EMPTY_DECIMALS: u8 = u8.MAX_VALUE
12
- public static readonly EMPTY_SYMBOL: string = ''
13
- private static readonly SERIALIZED_PREFIX: string = 'Token'
14
-
15
- private _symbol: string
16
- private _address: Address
17
- private _chainId: ChainId
18
- private _decimals: u8
19
- private _timestamp: Date | null = null
20
-
21
- /**
22
- * Creates a Token instance from an Address object.
23
- * @param address - The contract address of the token
24
- * @param chainId - The blockchain network identifier
25
- * @param decimals - Number of decimal places (optional, will be queried if not provided)
26
- * @param symbol - Token symbol (optional, will be queried if not provided)
27
- * @param timestamp - Timestamp for historical queries (optional)
28
- * @returns A new Token instance
29
- */
30
- static fromAddress(
31
- address: Address,
32
- chainId: ChainId,
33
- decimals: u8 = Token.EMPTY_DECIMALS,
34
- symbol: string = Token.EMPTY_SYMBOL,
35
- timestamp: Date | null = null
36
- ): Token {
37
- return new Token(address, chainId, decimals, symbol, timestamp)
38
- }
39
-
40
- /**
41
- * Creates a Token instance from a string address.
42
- * @param address - The contract address as a hex string
43
- * @param chainId - The blockchain network identifier
44
- * @param decimals - Number of decimal places (optional, will be queried if not provided)
45
- * @param symbol - Token symbol (optional, will be queried if not provided)
46
- * @param timestamp - Timestamp for historical queries (optional)
47
- * @returns A new Token instance
48
- */
49
- static fromString(
50
- address: string,
51
- chainId: ChainId,
52
- decimals: u8 = Token.EMPTY_DECIMALS,
53
- symbol: string = Token.EMPTY_SYMBOL,
54
- timestamp: Date | null = null
55
- ): Token {
56
- return Token.fromAddress(Address.fromString(address), chainId, decimals, symbol, timestamp)
57
- }
58
-
59
- /**
60
- * Creates a Token instance representing the native token of the specified chain.
61
- * @param chainId - The blockchain network identifier
62
- * @returns A new Token instance for the native token
63
- */
64
- static native(chainId: ChainId): Token {
65
- switch (chainId) {
66
- case ChainId.ETHEREUM:
67
- case ChainId.OPTIMISM:
68
- return Token.fromString(NATIVE_ADDRESS, chainId, 18, 'ETH')
69
- case ChainId.POLYGON:
70
- return Token.fromString(NATIVE_ADDRESS, chainId, 18, 'POL')
71
- default:
72
- throw new Error(`Unsupported chainId: ${chainId}`)
73
- }
74
- }
75
-
76
- /**
77
- * Parses a serialized Token string and creates a Token instance.
78
- * @param serialized - The serialized token string in format: Token(address,chainId)
79
- * @returns A new Token instance parsed from the serialized data
80
- */
81
- static parse(serialized: string): Token {
82
- const isToken = serialized.startsWith(`${Token.SERIALIZED_PREFIX}(`) && serialized.endsWith(')')
83
- if (!isToken) throw new Error('Invalid serialized token')
84
-
85
- const elements = parseCSV(serialized.slice(Token.SERIALIZED_PREFIX.length + 1, -1))
86
- const areNull = elements.some((element) => element === null)
87
- if (areNull) throw new Error('Invalid serialized token')
88
-
89
- const address = elements[0]!
90
- const chainId = i32.parse(elements[1]!)
91
-
92
- return Token.fromString(address, chainId)
93
- }
7
+ export abstract class Token {
8
+ protected _symbol: string
9
+ protected _address: Address
10
+ protected _decimals: u8
94
11
 
95
12
  /**
96
13
  * Creates a new Token instance.
97
- * @param address - The contract address of the token
98
- * @param chainId - The blockchain network identifier
99
- * @param decimals - Number of decimal places (optional, will be queried if not provided)
100
- * @param symbol - Token symbol (optional, will be queried if not provided)
101
- * @param timestamp - Timestamp for historical queries (optional)
14
+ * @param address - The address of the token
15
+ * @param decimals - Number of decimal places
16
+ * @param symbol - Token symbol
102
17
  */
103
- constructor(
104
- address: Address,
105
- chainId: ChainId,
106
- decimals: u8 = Token.EMPTY_DECIMALS,
107
- symbol: string = Token.EMPTY_SYMBOL,
108
- timestamp: Date | null = null
109
- ) {
18
+ constructor(address: Address, decimals: u8, symbol: string) {
110
19
  this._address = address
111
- this._chainId = chainId
112
- this._timestamp = timestamp
113
- this._symbol = symbol
114
20
  this._decimals = decimals
115
- // Ensure symbol and decimals are set for native tokens.
116
- // Since queries return only the address and chainId, missing metadata must be filled
117
- // to prevent the symbol and decimals getters from failing for native tokens.
118
- if (
119
- this._address.equals(Address.fromString(NATIVE_ADDRESS)) &&
120
- (this._symbol === Token.EMPTY_SYMBOL || this._decimals === Token.EMPTY_DECIMALS)
121
- ) {
122
- const nativeToken = Token.native(this._chainId)
123
- if (this._symbol === Token.EMPTY_SYMBOL) {
124
- this._symbol = nativeToken.symbol
125
- }
126
- if (this._decimals === Token.EMPTY_DECIMALS) {
127
- this._decimals = nativeToken.decimals
128
- }
129
- }
21
+ this._symbol = symbol
130
22
  }
131
23
 
24
+ /**
25
+ * Gets the contract address of the token.
26
+ * The address is returned as a cloned `Address` object to ensure immutability of the internal state.
27
+ * @returns A cloned `Address` object representing the token’s address.
28
+ */
132
29
  get address(): Address {
133
30
  return this._address.clone()
134
31
  }
135
32
 
136
- get chainId(): ChainId {
137
- return this._chainId
138
- }
139
-
33
+ /**
34
+ * Gets the token’s symbol (e.g., "ETH", "USDC").
35
+ * @returns A string containing the token symbol.
36
+ */
140
37
  get symbol(): string {
141
- if (this._symbol === Token.EMPTY_SYMBOL) {
142
- const response = environment.contractCall(this.address, this.chainId, this._timestamp, '0x95d89b41')
143
- this._symbol = evm.decode(new EvmDecodeParam('string', response))
144
- }
145
38
  return this._symbol
146
39
  }
147
40
 
41
+ /**
42
+ * Gets the token’s decimals (number of decimal places used).
43
+ * @returns A `u8` representing the number of decimals of the token.
44
+ */
148
45
  get decimals(): u8 {
149
- if (this._decimals == Token.EMPTY_DECIMALS) {
150
- const result = environment.contractCall(this.address, this.chainId, this._timestamp, '0x313ce567')
151
- this._decimals = u8.parse(evm.decode(new EvmDecodeParam('uint8', result)))
152
- }
153
46
  return this._decimals
154
47
  }
155
48
 
156
- set decimals(value: u8) {
157
- this._decimals = value
158
- }
159
-
160
- set symbol(value: string) {
161
- this._symbol = value
162
- }
163
-
164
- set timestamp(value: Date) {
165
- this._timestamp = value
166
- }
167
-
168
49
  /**
169
50
  * Checks if this token is equal to another token.
170
- * Tokens are considered equal if they have the same address on the same chain.
51
+ * Tokens are considered equal if they have the same address.
171
52
  * @param other - The token to compare with
172
- * @returns True if both tokens represent the same asset
53
+ * @returns True if both tokens have the same address
173
54
  */
174
55
  equals(other: Token): boolean {
175
- const isSameChain = this.chainId === other.chainId
176
- const isSameAddress = this.address.equals(other.address)
177
- return isSameChain && isSameAddress
56
+ return this.address.equals(other.address)
178
57
  }
179
58
 
59
+ /**
60
+ * Checks if this token is the USD denomination.
61
+ * @returns True if the token is the USD denomination
62
+ */
63
+ abstract isUSD(): boolean
64
+
65
+ /**
66
+ * Checks if this token is the native token.
67
+ * @returns True if the token is the native token
68
+ */
69
+ abstract isNative(): boolean
70
+
71
+ /**
72
+ * Checks if this token belongs to the requested chain.
73
+ * @param chain - The chain ID asking for
74
+ * @returns True if the token belongs to the requested chain
75
+ */
76
+ abstract hasChain(chain: ChainId): boolean
77
+
180
78
  /**
181
79
  * Tells the string representation of this token.
182
- * @returns The token symbol
80
+ * @returns The string representation of the token
183
81
  */
184
- toString(): string {
185
- return this.symbol
186
- }
82
+ abstract toString(): string
83
+ }
187
84
 
188
- serialize(): string {
189
- return `${Token.SERIALIZED_PREFIX}(${join([serialize(this.address), serialize(this.chainId)])})`
190
- }
85
+ @json
86
+ export class SerializableToken {
87
+ constructor(
88
+ public address: string,
89
+ public chainId: i32
90
+ ) {}
191
91
  }
@@ -1,20 +1,28 @@
1
1
  import { environment } from '../environment'
2
- import { join, parseCSV, Serializable, serialize } from '../helpers'
3
- import { BigInt } from '../types'
2
+ import { BigInt, JSON, Result } from '../types'
4
3
 
5
- import { Token } from './Token'
4
+ import { BlockchainToken } from './BlockchainToken'
5
+ import { SerializableToken, Token } from './Token'
6
6
  import { USD } from './USD'
7
7
 
8
+ const BPS_SCALE = BigInt.fromI32(10_000)
9
+
8
10
  /**
9
11
  * Represents an amount of a specific token, combining the token metadata with a quantity.
10
12
  * Supports arithmetic operations, comparisons, and conversions between tokens and USD.
11
13
  */
12
- export class TokenAmount implements Serializable {
13
- private static readonly SERIALIZED_PREFIX: string = 'TokenAmount'
14
-
14
+ export class TokenAmount {
15
15
  private _token: Token
16
16
  private _amount: BigInt
17
17
 
18
+ /**
19
+ * Creates a TokenAmount instance representing zero.
20
+ * @returns A new TokenAmount instance with amount 0
21
+ */
22
+ static zero(token: Token): TokenAmount {
23
+ return this.fromBigInt(token, BigInt.zero())
24
+ }
25
+
18
26
  /**
19
27
  * Creates a TokenAmount from a decimal string representation.
20
28
  * @param token - The token to create an amount for
@@ -46,22 +54,14 @@ export class TokenAmount implements Serializable {
46
54
  }
47
55
 
48
56
  /**
49
- * Parses a serialized TokenAmount string and creates a TokenAmount instance.
50
- * @param serialized - The serialized string in format: TokenAmount(token,amount)
51
- * @returns A new TokenAmount instance parsed from the serialized data
57
+ * Creates a TokenAmount from a serialized string.
58
+ * @param serialized - The serialized string to parse
59
+ * @returns A new TokenAmount instance
52
60
  */
53
- static parse(serialized: string): TokenAmount {
54
- const isTokenAmount = serialized.startsWith(`${TokenAmount.SERIALIZED_PREFIX}(`) && serialized.endsWith(')')
55
- if (!isTokenAmount) throw new Error('Invalid serialized token amount')
56
-
57
- const elements = parseCSV(serialized.slice(TokenAmount.SERIALIZED_PREFIX.length + 1, -1))
58
- const areNull = elements.some((element) => element === null)
59
- if (areNull) throw new Error('Invalid serialized token amount')
60
-
61
- const token = Token.parse(elements[0]!)
62
- const amount = BigInt.parse(elements[1]!)
63
-
64
- return new TokenAmount(token, amount)
61
+ static fromSerializable(serialized: string): TokenAmount {
62
+ const data = JSON.parse<SerializableTokenAmount>(serialized)
63
+ const token = BlockchainToken.fromString(data.token.address, data.token.chainId)
64
+ return TokenAmount.fromStringDecimal(token, data.amount)
65
65
  }
66
66
 
67
67
  /**
@@ -217,11 +217,14 @@ export class TokenAmount implements Serializable {
217
217
  * Converts this TokenAmount to its USD equivalent.
218
218
  * @returns A USD instance representing the current USD value
219
219
  */
220
- toUsd(): USD {
221
- if (this.isZero()) return USD.zero()
222
- const tokenPrice = environment.getPrice(this.token)
220
+ toUsd(): Result<USD, string> {
221
+ if (this.isZero()) return Result.ok<USD, string>(USD.zero())
222
+ const tokenPriceResult = environment.tokenPriceQuery(this.token)
223
+ if (tokenPriceResult.isError) return Result.err<USD, string>(tokenPriceResult.error)
224
+
225
+ const tokenPrice = tokenPriceResult.unwrap()
223
226
  const amountUsd = this.amount.times(tokenPrice.value).downscale(this.decimals)
224
- return USD.fromBigInt(amountUsd)
227
+ return Result.ok<USD, string>(USD.fromBigInt(amountUsd))
225
228
  }
226
229
 
227
230
  /**
@@ -229,13 +232,39 @@ export class TokenAmount implements Serializable {
229
232
  * @param other - The target token to convert to
230
233
  * @returns A TokenAmount of the target token with equivalent USD value
231
234
  */
232
- toTokenAmount(other: Token): TokenAmount {
233
- if (this.isZero()) return TokenAmount.fromI32(other, 0)
234
- return this.toUsd().toTokenAmount(other)
235
+ toTokenAmount(other: Token): Result<TokenAmount, string> {
236
+ if (this.isZero()) return Result.ok<TokenAmount, string>(TokenAmount.fromI32(other, 0))
237
+ const usdResult = this.toUsd()
238
+ if (usdResult.isError) return Result.err<TokenAmount, string>(usdResult.error)
239
+
240
+ return usdResult.unwrap().toTokenAmount(other)
235
241
  }
236
242
 
237
- serialize(): string {
238
- return `${TokenAmount.SERIALIZED_PREFIX}(${join([serialize(this.token), serialize(this.amount)])})`
243
+ /**
244
+ * Calculates the minimum output amount using basis points (bps).
245
+ * Formula: minAmountOut = amountOut * (10000 - bps) / 10000
246
+ *
247
+ * @param slippage - Slippage in basis points (0-10000). Example: 50 = 0.5%
248
+ * @returns A new TokenAmount representing the minimum output amount
249
+ */
250
+ applySlippageBps(slippage: i32): TokenAmount {
251
+ const slippageBI = BigInt.fromI32(slippage)
252
+ if (slippageBI.isNegative() || slippageBI.gt(BPS_SCALE))
253
+ throw new Error(`Slippage bps must be between 0 and ${BPS_SCALE}`)
254
+ return this.applySlippage(slippageBI)
255
+ }
256
+
257
+ /**
258
+ * Calculates the minimum output amount from a percentage string.
259
+ * Formula: minAmountOut = amountOut * (100 - percent) / 100
260
+ *
261
+ * @param slippage - Slippage percentage as a decimal string. Example: '0.5' = 0.5%
262
+ * @returns A new TokenAmount representing the minimum output amount
263
+ */
264
+ applySlippagePercentage(slippage: string): TokenAmount {
265
+ const bps = BigInt.fromStringDecimal(slippage, 2)
266
+ if (bps.isNegative() || bps.gt(BPS_SCALE)) throw new Error('Slippage percentage must be between 0 and 100')
267
+ return this.applySlippage(bps)
239
268
  }
240
269
 
241
270
  private amountCompare(other: TokenAmount): i32 {
@@ -245,4 +274,17 @@ export class TokenAmount implements Serializable {
245
274
  private checkToken(other: Token, action: string): void {
246
275
  if (!this.token.equals(other)) throw new Error(`Cannot ${action} different tokens`)
247
276
  }
277
+
278
+ private applySlippage(value: BigInt): TokenAmount {
279
+ const factor = BPS_SCALE.minus(value)
280
+ return this.times(factor).div(BPS_SCALE)
281
+ }
282
+ }
283
+
284
+ @json
285
+ export class SerializableTokenAmount {
286
+ constructor(
287
+ public token: SerializableToken,
288
+ public amount: string
289
+ ) {}
248
290
  }
@@ -0,0 +1,54 @@
1
+ import { ChainId } from '../types'
2
+
3
+ import { BlockchainToken } from './BlockchainToken'
4
+
5
+ /**
6
+ * Represents a token provider that can resolve to a specific BlockchainToken instance
7
+ * based on the provided chain ID.
8
+ * This allows for convenient access to common tokens across different chains.
9
+ * Supports both ERC20Token (EVM chains) and SPLToken (Solana).
10
+ */
11
+ export class TokenProvider {
12
+ private _symbol: string
13
+ private _registry: Map<ChainId, BlockchainToken>
14
+
15
+ /**
16
+ * Creates a new TokenProvider instance.
17
+ * @param symbol - The token symbol (e.g., "USDC", "USDT")
18
+ */
19
+ constructor(symbol: string) {
20
+ this._symbol = symbol
21
+ this._registry = new Map<ChainId, BlockchainToken>()
22
+ }
23
+
24
+ /**
25
+ * Registers a token for a specific chain.
26
+ * @param chainId - The chain ID to register the token for
27
+ * @param token - The BlockchainToken instance for this chain (ERC20Token or SPLToken)
28
+ * @returns The TokenProvider instance for method chaining
29
+ */
30
+ register(chainId: ChainId, token: BlockchainToken): TokenProvider {
31
+ this._registry.set(chainId, token)
32
+ return this
33
+ }
34
+
35
+ /**
36
+ * Resolves the token provider to a specific BlockchainToken instance for the given chain.
37
+ * @param chainId - The chain ID to resolve the token for
38
+ * @returns The BlockchainToken instance for the specified chain
39
+ * @throws Error if the token is not supported on the requested chain
40
+ */
41
+ on(chainId: i32): BlockchainToken {
42
+ if (!this.isSupported(chainId)) throw new Error(`Token ${this._symbol} is not registered on chain ${chainId}`)
43
+ return this._registry.get(chainId)
44
+ }
45
+
46
+ /**
47
+ * Checks if the token is supported on the given chain.
48
+ * @param chainId - The chain ID to check
49
+ * @returns True if the token is supported on the chain, false otherwise
50
+ */
51
+ isSupported(chainId: i32): bool {
52
+ return this._registry.has(chainId)
53
+ }
54
+ }
@@ -0,0 +1,186 @@
1
+ import { Arbitrum, Avalanche, Base, BaseSepolia, BNB, Ethereum, Gnosis, Optimism, Polygon, Sonic } from '../chains'
2
+
3
+ import { TokenProvider } from './TokenProvider'
4
+
5
+ /**
6
+ * Token providers that can resolve to chain-specific BlockchainToken instances.
7
+ * Use the `.on(chainId)` method to get the token for a specific chain.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { Tokens, Ethereum } from '@mimicprotocol/lib-ts'
12
+ *
13
+ * const usdc = Tokens.USDC.on(inputs.chainId)
14
+ * const weth = Tokens.WETH.on(Ethereum.CHAIN_ID)
15
+ * ```
16
+ */
17
+ export class Tokens {
18
+ private static _instance: Tokens | null = null
19
+
20
+ private readonly usdc: TokenProvider = new TokenProvider('USDC')
21
+ private readonly usdt: TokenProvider = new TokenProvider('USDT')
22
+ private readonly dai: TokenProvider = new TokenProvider('DAI')
23
+ private readonly wbtc: TokenProvider = new TokenProvider('WBTC')
24
+ private readonly weth: TokenProvider = new TokenProvider('WETH')
25
+ private readonly eth: TokenProvider = new TokenProvider('ETH')
26
+ private readonly avax: TokenProvider = new TokenProvider('AVAX')
27
+ private readonly wavax: TokenProvider = new TokenProvider('WAVAX')
28
+ private readonly pol: TokenProvider = new TokenProvider('POL')
29
+ private readonly wpol: TokenProvider = new TokenProvider('WPOL')
30
+ private readonly bnb: TokenProvider = new TokenProvider('BNB')
31
+ private readonly wbnb: TokenProvider = new TokenProvider('WBNB')
32
+ private readonly xdai: TokenProvider = new TokenProvider('xDAI')
33
+ private readonly sonic: TokenProvider = new TokenProvider('SONIC')
34
+ private readonly wxdai: TokenProvider = new TokenProvider('WXDAI')
35
+ private readonly wsonic: TokenProvider = new TokenProvider('WSONIC')
36
+
37
+ private constructor() {
38
+ // Ethereum
39
+ this.usdc.register(Ethereum.CHAIN_ID, Ethereum.USDC)
40
+ this.usdt.register(Ethereum.CHAIN_ID, Ethereum.USDT)
41
+ this.dai.register(Ethereum.CHAIN_ID, Ethereum.DAI)
42
+ this.wbtc.register(Ethereum.CHAIN_ID, Ethereum.WBTC)
43
+ this.weth.register(Ethereum.CHAIN_ID, Ethereum.WETH)
44
+ this.eth.register(Ethereum.CHAIN_ID, Ethereum.ETH)
45
+
46
+ // Arbitrum
47
+ this.usdc.register(Arbitrum.CHAIN_ID, Arbitrum.USDC)
48
+ this.usdt.register(Arbitrum.CHAIN_ID, Arbitrum.USDT)
49
+ this.dai.register(Arbitrum.CHAIN_ID, Arbitrum.DAI)
50
+ this.wbtc.register(Arbitrum.CHAIN_ID, Arbitrum.WBTC)
51
+ this.weth.register(Arbitrum.CHAIN_ID, Arbitrum.WETH)
52
+ this.eth.register(Arbitrum.CHAIN_ID, Arbitrum.ETH)
53
+
54
+ // Avalanche
55
+ this.usdc.register(Avalanche.CHAIN_ID, Avalanche.USDC)
56
+ this.usdt.register(Avalanche.CHAIN_ID, Avalanche.USDT)
57
+ this.dai.register(Avalanche.CHAIN_ID, Avalanche.DAI)
58
+ this.wbtc.register(Avalanche.CHAIN_ID, Avalanche.WBTC)
59
+ this.weth.register(Avalanche.CHAIN_ID, Avalanche.WETH)
60
+ this.avax.register(Avalanche.CHAIN_ID, Avalanche.AVAX)
61
+ this.wavax.register(Avalanche.CHAIN_ID, Avalanche.WAVAX)
62
+
63
+ // Base
64
+ this.usdc.register(Base.CHAIN_ID, Base.USDC)
65
+ this.usdt.register(Base.CHAIN_ID, Base.USDT)
66
+ this.dai.register(Base.CHAIN_ID, Base.DAI)
67
+ this.wbtc.register(Base.CHAIN_ID, Base.WBTC)
68
+ this.weth.register(Base.CHAIN_ID, Base.WETH)
69
+ this.eth.register(Base.CHAIN_ID, Base.ETH)
70
+
71
+ // BNB
72
+ this.usdc.register(BNB.CHAIN_ID, BNB.USDC)
73
+ this.usdt.register(BNB.CHAIN_ID, BNB.USDT)
74
+ this.dai.register(BNB.CHAIN_ID, BNB.DAI)
75
+ this.wbtc.register(BNB.CHAIN_ID, BNB.WBTC)
76
+ this.weth.register(BNB.CHAIN_ID, BNB.WETH)
77
+ this.bnb.register(BNB.CHAIN_ID, BNB.BNB)
78
+ this.wbnb.register(BNB.CHAIN_ID, BNB.WBNB)
79
+
80
+ // Optimism
81
+ this.usdc.register(Optimism.CHAIN_ID, Optimism.USDC)
82
+ this.usdt.register(Optimism.CHAIN_ID, Optimism.USDT)
83
+ this.dai.register(Optimism.CHAIN_ID, Optimism.DAI)
84
+ this.wbtc.register(Optimism.CHAIN_ID, Optimism.WBTC)
85
+ this.weth.register(Optimism.CHAIN_ID, Optimism.WETH)
86
+ this.eth.register(Optimism.CHAIN_ID, Optimism.ETH)
87
+
88
+ // Gnosis
89
+ this.usdc.register(Gnosis.CHAIN_ID, Gnosis.USDC)
90
+ this.usdt.register(Gnosis.CHAIN_ID, Gnosis.USDT)
91
+ this.wbtc.register(Gnosis.CHAIN_ID, Gnosis.WBTC)
92
+ this.weth.register(Gnosis.CHAIN_ID, Gnosis.WETH)
93
+ this.xdai.register(Gnosis.CHAIN_ID, Gnosis.xDAI)
94
+ this.wxdai.register(Gnosis.CHAIN_ID, Gnosis.WXDAI)
95
+
96
+ // Polygon
97
+ this.usdc.register(Polygon.CHAIN_ID, Polygon.USDC)
98
+ this.usdt.register(Polygon.CHAIN_ID, Polygon.USDT)
99
+ this.dai.register(Polygon.CHAIN_ID, Polygon.DAI)
100
+ this.wbtc.register(Polygon.CHAIN_ID, Polygon.WBTC)
101
+ this.weth.register(Polygon.CHAIN_ID, Polygon.WETH)
102
+ this.pol.register(Polygon.CHAIN_ID, Polygon.POL)
103
+ this.wpol.register(Polygon.CHAIN_ID, Polygon.WPOL)
104
+
105
+ // Sonic
106
+ this.usdc.register(Sonic.CHAIN_ID, Sonic.USDC)
107
+ this.usdt.register(Sonic.CHAIN_ID, Sonic.USDT)
108
+ this.weth.register(Sonic.CHAIN_ID, Sonic.WETH)
109
+ this.sonic.register(Sonic.CHAIN_ID, Sonic.SONIC)
110
+ this.wsonic.register(Sonic.CHAIN_ID, Sonic.WSONIC)
111
+
112
+ // BaseSepolia
113
+ this.eth.register(BaseSepolia.CHAIN_ID, BaseSepolia.ETH)
114
+ }
115
+
116
+ private static getInstance(): Tokens {
117
+ if (Tokens._instance === null) {
118
+ Tokens._instance = new Tokens()
119
+ }
120
+ return Tokens._instance!
121
+ }
122
+
123
+ static get USDC(): TokenProvider {
124
+ return Tokens.getInstance().usdc
125
+ }
126
+
127
+ static get USDT(): TokenProvider {
128
+ return Tokens.getInstance().usdt
129
+ }
130
+
131
+ static get DAI(): TokenProvider {
132
+ return Tokens.getInstance().dai
133
+ }
134
+
135
+ static get WBTC(): TokenProvider {
136
+ return Tokens.getInstance().wbtc
137
+ }
138
+
139
+ static get WETH(): TokenProvider {
140
+ return Tokens.getInstance().weth
141
+ }
142
+
143
+ static get ETH(): TokenProvider {
144
+ return Tokens.getInstance().eth
145
+ }
146
+
147
+ static get AVAX(): TokenProvider {
148
+ return Tokens.getInstance().avax
149
+ }
150
+
151
+ static get WAVAX(): TokenProvider {
152
+ return Tokens.getInstance().wavax
153
+ }
154
+
155
+ static get POL(): TokenProvider {
156
+ return Tokens.getInstance().pol
157
+ }
158
+
159
+ static get WPOL(): TokenProvider {
160
+ return Tokens.getInstance().wpol
161
+ }
162
+
163
+ static get BNB(): TokenProvider {
164
+ return Tokens.getInstance().bnb
165
+ }
166
+
167
+ static get WBNB(): TokenProvider {
168
+ return Tokens.getInstance().wbnb
169
+ }
170
+
171
+ static get XDAI(): TokenProvider {
172
+ return Tokens.getInstance().xdai
173
+ }
174
+
175
+ static get SONIC(): TokenProvider {
176
+ return Tokens.getInstance().sonic
177
+ }
178
+
179
+ static get WXDAI(): TokenProvider {
180
+ return Tokens.getInstance().wxdai
181
+ }
182
+
183
+ static get WSONIC(): TokenProvider {
184
+ return Tokens.getInstance().wsonic
185
+ }
186
+ }
package/src/tokens/USD.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { environment } from '../environment'
2
2
  import { STANDARD_DECIMALS } from '../helpers'
3
3
  import { Token, TokenAmount } from '../tokens'
4
- import { BigInt } from '../types'
4
+ import { BigInt, Result } from '../types'
5
5
 
6
6
  /**
7
7
  * Represents a USD amount with fixed decimal precision.
@@ -42,7 +42,6 @@ export class USD {
42
42
  * @returns A new USD instance
43
43
  */
44
44
  static fromBigInt(amount: BigInt): USD {
45
- if (amount.isNegative()) throw new Error('USD cannot be negative')
46
45
  return new USD(amount)
47
46
  }
48
47
 
@@ -51,6 +50,7 @@ export class USD {
51
50
  * @param amount - The amount in 18 decimals precision (must be non-negative)
52
51
  */
53
52
  constructor(amount: BigInt) {
53
+ if (amount.isNegative()) throw new Error('USD cannot be negative')
54
54
  this._value = amount.clone()
55
55
  }
56
56
 
@@ -192,10 +192,13 @@ export class USD {
192
192
  * @param token - The target token to convert to
193
193
  * @returns A TokenAmount representing the equivalent value in the target token
194
194
  */
195
- toTokenAmount(token: Token): TokenAmount {
196
- if (this.isZero()) return TokenAmount.fromI32(token, 0)
197
- const tokenPrice = environment.getPrice(token)
195
+ toTokenAmount(token: Token): Result<TokenAmount, string> {
196
+ if (this.isZero()) return Result.ok<TokenAmount, string>(TokenAmount.fromI32(token, 0))
197
+ const tokenPriceResult = environment.tokenPriceQuery(token)
198
+ if (tokenPriceResult.isError) return Result.err<TokenAmount, string>(tokenPriceResult.error)
199
+
200
+ const tokenPrice = tokenPriceResult.unwrap()
198
201
  const tokenAmount = this.value.upscale(token.decimals).div(tokenPrice.value)
199
- return TokenAmount.fromBigInt(token, tokenAmount)
202
+ return Result.ok<TokenAmount, string>(TokenAmount.fromBigInt(token, tokenAmount))
200
203
  }
201
204
  }
@@ -1,3 +1,9 @@
1
+ export * from './BlockchainToken'
2
+ export * from './DenominationToken'
3
+ export * from './ERC20Token'
4
+ export * from './SPLToken'
1
5
  export * from './Token'
2
6
  export * from './TokenAmount'
7
+ export * from './TokenProvider'
8
+ export * from './Tokens'
3
9
  export * from './USD'