sushi 6.6.6 → 6.6.8

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 (54) hide show
  1. package/_cjs/evm/config/subgraphs/subgraphs/sushiswap-v2.js +2 -7
  2. package/_cjs/evm/config/subgraphs/subgraphs/sushiswap-v2.js.map +1 -1
  3. package/_cjs/evm/config/subgraphs/subgraphs/sushiswap-v3.js +2 -7
  4. package/_cjs/evm/config/subgraphs/subgraphs/sushiswap-v3.js.map +1 -1
  5. package/_cjs/generic/currency/for-chain.js +66 -0
  6. package/_cjs/generic/currency/for-chain.js.map +1 -0
  7. package/_cjs/generic/currency/index.js +1 -0
  8. package/_cjs/generic/currency/index.js.map +1 -1
  9. package/_cjs/generic/utils/normalize-address.js +29 -1
  10. package/_cjs/generic/utils/normalize-address.js.map +1 -1
  11. package/_esm/evm/config/subgraphs/subgraphs/sushiswap-v2.js +2 -7
  12. package/_esm/evm/config/subgraphs/subgraphs/sushiswap-v2.js.map +1 -1
  13. package/_esm/evm/config/subgraphs/subgraphs/sushiswap-v3.js +2 -7
  14. package/_esm/evm/config/subgraphs/subgraphs/sushiswap-v3.js.map +1 -1
  15. package/_esm/generic/currency/for-chain.js +62 -0
  16. package/_esm/generic/currency/for-chain.js.map +1 -0
  17. package/_esm/generic/currency/index.js +1 -0
  18. package/_esm/generic/currency/index.js.map +1 -1
  19. package/_esm/generic/utils/normalize-address.js +29 -1
  20. package/_esm/generic/utils/normalize-address.js.map +1 -1
  21. package/_types/evm/config/subgraphs/subgraphs/sushiswap-v2.d.ts +1 -1
  22. package/_types/evm/config/subgraphs/subgraphs/sushiswap-v2.d.ts.map +1 -1
  23. package/_types/evm/config/subgraphs/subgraphs/sushiswap-v3.d.ts +1 -1
  24. package/_types/evm/config/subgraphs/subgraphs/sushiswap-v3.d.ts.map +1 -1
  25. package/_types/evm/currency/currency.d.ts +1 -1
  26. package/_types/evm/currency/currency.d.ts.map +1 -1
  27. package/_types/generic/currency/currency.d.ts +1 -1
  28. package/_types/generic/currency/currency.d.ts.map +1 -1
  29. package/_types/generic/currency/for-chain.d.ts +25 -0
  30. package/_types/generic/currency/for-chain.d.ts.map +1 -0
  31. package/_types/generic/currency/index.d.ts +1 -0
  32. package/_types/generic/currency/index.d.ts.map +1 -1
  33. package/_types/generic/types/for-chain.d.ts +4 -0
  34. package/_types/generic/types/for-chain.d.ts.map +1 -1
  35. package/_types/generic/utils/normalize-address.d.ts +2 -1
  36. package/_types/generic/utils/normalize-address.d.ts.map +1 -1
  37. package/_types/svm/currency/currency.d.ts +1 -1
  38. package/_types/svm/currency/currency.d.ts.map +1 -1
  39. package/evm/config/subgraphs/subgraphs/sushiswap-v2.ts +5 -8
  40. package/evm/config/subgraphs/subgraphs/sushiswap-v3.ts +5 -8
  41. package/evm/currency/currency.ts +1 -1
  42. package/generic/currency/currency.test-d.ts +41 -0
  43. package/generic/currency/currency.ts +1 -1
  44. package/generic/currency/for-chain.test-d.ts +224 -0
  45. package/generic/currency/for-chain.test.ts +108 -0
  46. package/generic/currency/for-chain.ts +133 -0
  47. package/generic/currency/index.ts +1 -0
  48. package/generic/types/for-chain.test-d.ts +100 -1
  49. package/generic/types/for-chain.ts +13 -0
  50. package/generic/utils/normalize-address.test-d.ts +110 -0
  51. package/generic/utils/normalize-address.test.ts +29 -0
  52. package/generic/utils/normalize-address.ts +58 -16
  53. package/package.json +1 -1
  54. package/svm/currency/currency.ts +1 -1
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import type { CurrencyMetadata } from '../../generic/currency/currency.js';
3
3
  import { type SvmNative } from './native.js';
4
4
  import { type SvmToken } from './token.js';
5
- export type SvmCurrency<TMetadata extends CurrencyMetadata = Record<string, unknown>> = SvmToken<TMetadata> | SvmNative;
5
+ export type SvmCurrency<TMetadata extends CurrencyMetadata = Record<string, unknown>> = SvmToken<TMetadata> | SvmNative<TMetadata>;
6
6
  export declare const serializedSvmCurrencySchema: <TMetadata extends {} = CurrencyMetadata>(opts?: {
7
7
  metadata?: z.ZodType<TMetadata>;
8
8
  }) => z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../../svm/currency/currency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAA;AAE1E,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,aAAa,CAAA;AACvE,OAAO,EAAE,KAAK,QAAQ,EAA4B,MAAM,YAAY,CAAA;AAEpE,MAAM,MAAM,WAAW,CACrB,SAAS,SAAS,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC1D,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;AAEnC,eAAO,MAAM,2BAA2B,GACtC,SAAS,SAAS,EAAE,GAAG,gBAAgB,EAEvC,OAAM;IAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;CAAO;;;;;;;;;;;;;;;2BAK5C,CAAA;AAEJ;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,6DAE1D;AAED,MAAM,MAAM,qBAAqB,CAC/B,SAAS,SAAS,gBAAgB,GAAG,gBAAgB,IACnD,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,2BAA2B,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../../svm/currency/currency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAA;AAE1E,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,aAAa,CAAA;AACvE,OAAO,EAAE,KAAK,QAAQ,EAA4B,MAAM,YAAY,CAAA;AAEpE,MAAM,MAAM,WAAW,CACrB,SAAS,SAAS,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC1D,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;AAE9C,eAAO,MAAM,2BAA2B,GACtC,SAAS,SAAS,EAAE,GAAG,gBAAgB,EAEvC,OAAM;IAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;CAAO;;;;;;;;;;;;;;;2BAK5C,CAAA;AAEJ;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,6DAE1D;AAED,MAAM,MAAM,qBAAqB,CAC/B,SAAS,SAAS,gBAAgB,GAAG,gBAAgB,IACnD,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,2BAA2B,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA"}
@@ -20,10 +20,6 @@ const SUSHISWAP_V2_DECENTRALIZED_DEPLOYMENT_IDS = {
20
20
  [EvmChainId.SONIC]: `QmTnVXE9wVJRDaxNdW1hnvzi8Cj1XBv3cMGXz6gHLacMVJ`,
21
21
  } as const satisfies Partial<Record<SushiSwapV2ChainId, string>>
22
22
 
23
- const SUSHISWAP_V2_DECENTRALIZED_SUBGRAPH_IDS = {
24
- [EvmChainId.KATANA]: `FYBTPY5uYPZ3oXpEriw9Pzn8RH9S1m7tpNwBwaNMuTNq`,
25
- } as const satisfies Partial<Record<SushiSwapV2ChainId, string>>
26
-
27
23
  const SUSHISWAP_V2_OTHER_URLS = {
28
24
  [EvmChainId.ARBITRUM_NOVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-0m/v2-arbitrum-nova/gn`,
29
25
  [EvmChainId.FILECOIN]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v2-filecoin/gn`,
@@ -31,12 +27,13 @@ const SUSHISWAP_V2_OTHER_URLS = {
31
27
  [EvmChainId.SKALE_EUROPA]: `${SKALE_HOST}/sushi/v2-skale-europa`,
32
28
  [EvmChainId.ROOTSTOCK]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v2-rootstock/gn`,
33
29
  [EvmChainId.HEMI]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v2-hemi/gn`,
30
+ [EvmChainId.KATANA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v2-katana/gn`,
34
31
  } as const satisfies Partial<Record<SushiSwapV2ChainId, string>>
35
32
 
36
33
  export const getSushiSwapV2SubgraphUrl = getSubgraphUrlWrapper({
37
- decentralizedIds: {
38
- ...wrapAsIdType(SUSHISWAP_V2_DECENTRALIZED_DEPLOYMENT_IDS, 'deploymentId'),
39
- ...wrapAsIdType(SUSHISWAP_V2_DECENTRALIZED_SUBGRAPH_IDS, 'subgraphId'),
40
- },
34
+ decentralizedIds: wrapAsIdType(
35
+ SUSHISWAP_V2_DECENTRALIZED_DEPLOYMENT_IDS,
36
+ 'deploymentId',
37
+ ),
41
38
  otherUrls: SUSHISWAP_V2_OTHER_URLS,
42
39
  })<SushiSwapV2ChainId, 'PARTIAL'>()
@@ -19,10 +19,6 @@ const SUSHISWAP_V3_DECENTRALIZED_DEPLOYMENT_IDS = {
19
19
  [EvmChainId.SONIC]: `Qmaa6gJsqzeSnDBjq4NnwerMGMSaSDLqRMDkrevGXwVUt1`,
20
20
  } as const satisfies Partial<Record<SushiSwapV3ChainId, string>>
21
21
 
22
- const SUSHISWAP_V3_DECENTRALIZED_SUBGRAPH_IDS = {
23
- [EvmChainId.KATANA]: `2YG7eSFHx1Wm9SHKdcrM8HR23JQpVe8fNNdmDHMXyVYR`,
24
- } as const satisfies Partial<Record<SushiSwapV3ChainId, string>>
25
-
26
22
  const SUSHISWAP_V3_OTHER_URLS = {
27
23
  [EvmChainId.ARBITRUM_NOVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-arbitrum-nova/gn`,
28
24
  [EvmChainId.FILECOIN]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-filecoin/gn`,
@@ -30,12 +26,13 @@ const SUSHISWAP_V3_OTHER_URLS = {
30
26
  [EvmChainId.SKALE_EUROPA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-skale-europa-2/gn`,
31
27
  [EvmChainId.ROOTSTOCK]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-rootstock-3/gn`,
32
28
  [EvmChainId.HEMI]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-hemi/gn`,
29
+ [EvmChainId.KATANA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-katana/gn`,
33
30
  } as const satisfies Partial<Record<SushiSwapV3ChainId, string>>
34
31
 
35
32
  export const getSushiSwapV3SubgraphUrl = getSubgraphUrlWrapper({
36
- decentralizedIds: {
37
- ...wrapAsIdType(SUSHISWAP_V3_DECENTRALIZED_DEPLOYMENT_IDS, 'deploymentId'),
38
- ...wrapAsIdType(SUSHISWAP_V3_DECENTRALIZED_SUBGRAPH_IDS, 'subgraphId'),
39
- },
33
+ decentralizedIds: wrapAsIdType(
34
+ SUSHISWAP_V3_DECENTRALIZED_DEPLOYMENT_IDS,
35
+ 'deploymentId',
36
+ ),
40
37
  otherUrls: SUSHISWAP_V3_OTHER_URLS,
41
38
  })<SushiSwapV3ChainId, 'PARTIAL'>()
@@ -6,7 +6,7 @@ import { type EvmToken, serializedEvmTokenSchema } from './token.js'
6
6
 
7
7
  export type EvmCurrency<
8
8
  TMetadata extends CurrencyMetadata = Record<string, unknown>,
9
- > = EvmToken<TMetadata> | EvmNative
9
+ > = EvmToken<TMetadata> | EvmNative<TMetadata>
10
10
 
11
11
  export const serializedEvmCurrencySchema = <
12
12
  TMetadata extends {} = CurrencyMetadata,
@@ -16,6 +16,7 @@ import { MvmToken } from '../../mvm/currency/token.js'
16
16
  import {
17
17
  type SvmAddress,
18
18
  type SvmChainId,
19
+ type SvmCurrency,
19
20
  SvmNative,
20
21
  SvmToken,
21
22
  } from '../../svm/index.js'
@@ -199,6 +200,46 @@ describe('generic/currency/currency.ts types', () => {
199
200
  })
200
201
  })
201
202
 
203
+ describe('metadata generics', () => {
204
+ type Metadata = {
205
+ coingeckoId: string
206
+ verified: boolean
207
+ }
208
+
209
+ it('should preserve metadata on generic currency variants', () => {
210
+ const mockCurrency = {} as Currency<EvmChainId, Metadata>
211
+
212
+ expectTypeOf(mockCurrency)
213
+ .extract<{ isNative: true }>()
214
+ .toEqualTypeOf<Native<EvmChainId, Metadata>>()
215
+ expectTypeOf(mockCurrency)
216
+ .extract<{ isToken: true }>()
217
+ .toEqualTypeOf<Token<EvmChainId, string, Metadata>>()
218
+ })
219
+
220
+ it('should preserve metadata on EVM currency variants', () => {
221
+ const mockCurrency = {} as EvmCurrency<Metadata>
222
+
223
+ expectTypeOf(mockCurrency)
224
+ .extract<{ isNative: true }>()
225
+ .toEqualTypeOf<EvmNative<Metadata>>()
226
+ expectTypeOf(mockCurrency)
227
+ .extract<{ isToken: true }>()
228
+ .toEqualTypeOf<EvmToken<Metadata>>()
229
+ })
230
+
231
+ it('should preserve metadata on SVM currency variants', () => {
232
+ const mockCurrency = {} as SvmCurrency<Metadata>
233
+
234
+ expectTypeOf(mockCurrency)
235
+ .extract<{ isNative: true }>()
236
+ .toEqualTypeOf<SvmNative<Metadata>>()
237
+ expectTypeOf(mockCurrency)
238
+ .extract<{ isToken: true }>()
239
+ .toEqualTypeOf<SvmToken<Metadata>>()
240
+ })
241
+ })
242
+
202
243
  describe('currency type extension', () => {
203
244
  type CustomAddress = `${EvmAddress}-${EvmAddress}`
204
245
  type SerializedCustomToken = {
@@ -69,4 +69,4 @@ export abstract class BaseCurrency<
69
69
  export type Currency<
70
70
  TChainId extends ChainId = ChainId,
71
71
  TMetadata extends CurrencyMetadata = Record<string, unknown>,
72
- > = Native<TChainId> | Token<TChainId, string, TMetadata>
72
+ > = Native<TChainId, TMetadata> | Token<TChainId, string, TMetadata>
@@ -0,0 +1,224 @@
1
+ import { describe, expectTypeOf, it } from 'vitest'
2
+ import { EvmChainId } from '../../evm/chain/chains.js'
3
+ import type { EvmNative } from '../../evm/currency/native.js'
4
+ import type {
5
+ EvmAddress,
6
+ EvmToken,
7
+ EvmTokenOrigin,
8
+ } from '../../evm/currency/token.js'
9
+ import { MvmChainId } from '../../mvm/chain/chains.js'
10
+ import type { MvmAddress, MvmToken } from '../../mvm/currency/token.js'
11
+ import type { StellarContractAddress } from '../../stellar/address.js'
12
+ import { StellarChainId } from '../../stellar/chain/chains.js'
13
+ import type { StellarToken } from '../../stellar/currency/token.js'
14
+ import { SvmChainId } from '../../svm/chain/chains.js'
15
+ import type { SvmNative } from '../../svm/currency/native.js'
16
+ import {
17
+ type SvmAddress,
18
+ type SvmToken,
19
+ svmAddress,
20
+ } from '../../svm/currency/token.js'
21
+ import type { NativeChainId } from '../types/for-chain.js'
22
+ import {
23
+ getNativeFor,
24
+ getTokenFor,
25
+ type TokenConstructorDataFor,
26
+ } from './for-chain.js'
27
+
28
+ describe('generic/currency/for-chain.ts types', () => {
29
+ type Metadata = {
30
+ coingeckoId: string
31
+ verified: boolean
32
+ }
33
+
34
+ describe('getNativeFor', () => {
35
+ it('returns the native currency class for each supported native chain family', () => {
36
+ const metadata: Metadata = { coingeckoId: 'ethereum', verified: true }
37
+
38
+ expectTypeOf(getNativeFor(EvmChainId.ETHEREUM, metadata)).toEqualTypeOf<
39
+ EvmNative<Metadata>
40
+ >()
41
+ expectTypeOf(getNativeFor(SvmChainId.SOLANA, metadata)).toEqualTypeOf<
42
+ SvmNative<Metadata>
43
+ >()
44
+ })
45
+
46
+ it('returns a native union for native chain id unions', () => {
47
+ const chainId = {} as NativeChainId
48
+ const metadata: Metadata = { coingeckoId: 'native', verified: true }
49
+
50
+ expectTypeOf(getNativeFor(chainId, metadata)).toEqualTypeOf<
51
+ EvmNative<Metadata> | SvmNative<Metadata>
52
+ >()
53
+ })
54
+
55
+ it('rejects chain families without native currency classes', () => {
56
+ // @ts-expect-error MVM currently models currencies as tokens only.
57
+ getNativeFor(MvmChainId.APTOS, {})
58
+
59
+ // @ts-expect-error Stellar currently models currencies as tokens only.
60
+ getNativeFor(StellarChainId.STELLAR, {})
61
+ })
62
+ })
63
+
64
+ describe('TokenConstructorDataFor', () => {
65
+ it('matches EVM token constructor data without chainId', () => {
66
+ expectTypeOf<
67
+ TokenConstructorDataFor<EvmChainId, Metadata>
68
+ >().toMatchTypeOf<{
69
+ chainId?: EvmChainId
70
+ address: EvmAddress
71
+ symbol: string
72
+ name: string
73
+ decimals: number
74
+ metadata?: Metadata
75
+ origin?: EvmTokenOrigin | undefined
76
+ }>()
77
+
78
+ const data = {
79
+ address: '0x1234567890abcdef1234567890abcdef12345678',
80
+ symbol: 'TEST',
81
+ name: 'Test Token',
82
+ decimals: 18,
83
+ metadata: { coingeckoId: 'test-token', verified: true },
84
+ } satisfies TokenConstructorDataFor<EvmChainId, Metadata>
85
+
86
+ expectTypeOf(data.metadata).toMatchTypeOf<Metadata>()
87
+ })
88
+
89
+ it('matches MVM token constructor data without EVM/SVM/Stellar-only fields', () => {
90
+ const data = {
91
+ address: '0x1::aptos_coin::AptosCoin',
92
+ symbol: 'APT',
93
+ name: 'Aptos Coin',
94
+ decimals: 8,
95
+ } satisfies TokenConstructorDataFor<MvmChainId>
96
+
97
+ expectTypeOf(data.address).toMatchTypeOf<MvmAddress>()
98
+
99
+ const dataWithOrigin = {
100
+ address: '0x1::aptos_coin::AptosCoin',
101
+ symbol: 'APT',
102
+ name: 'Aptos Coin',
103
+ decimals: 8,
104
+ // @ts-expect-error origin is not part of MVM token constructor data.
105
+ origin: 'native',
106
+ } satisfies TokenConstructorDataFor<MvmChainId>
107
+
108
+ void dataWithOrigin
109
+ })
110
+
111
+ it('matches SVM token constructor data and preserves branded addresses', () => {
112
+ const data = {
113
+ address: svmAddress('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
114
+ symbol: 'USDC',
115
+ name: 'USD Coin',
116
+ decimals: 6,
117
+ metadata: { coingeckoId: 'usd-coin', verified: true },
118
+ } satisfies TokenConstructorDataFor<SvmChainId, Metadata>
119
+
120
+ expectTypeOf(data.address).toMatchTypeOf<SvmAddress>()
121
+ expectTypeOf(data.metadata).toMatchTypeOf<Metadata>()
122
+ })
123
+
124
+ it('matches Stellar token constructor data including issuer and origin', () => {
125
+ const data = {
126
+ address: 'CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA',
127
+ issuer: 'GDMTVHLWJTHSUDMZVVMXXH6VJHA2ZV3HNG5LYNAZ6RTWB7GISM6PGTUV',
128
+ symbol: 'XLM',
129
+ name: 'XLM',
130
+ decimals: 7,
131
+ origin: 'stellar.org',
132
+ } satisfies TokenConstructorDataFor<StellarChainId>
133
+
134
+ expectTypeOf(data.address).toMatchTypeOf<StellarContractAddress>()
135
+ expectTypeOf(data.origin).toMatchTypeOf<string>()
136
+ })
137
+
138
+ it('accepts chainId for compatibility', () => {
139
+ const dataWithChainId = {
140
+ address: '0x1234567890abcdef1234567890abcdef12345678',
141
+ symbol: 'TEST',
142
+ name: 'Test Token',
143
+ decimals: 18,
144
+ chainId: EvmChainId.ETHEREUM,
145
+ } satisfies TokenConstructorDataFor<EvmChainId>
146
+
147
+ void dataWithChainId
148
+ })
149
+ })
150
+
151
+ describe('getTokenFor', () => {
152
+ it('returns the token class selected by the chain id', () => {
153
+ expectTypeOf(
154
+ getTokenFor(EvmChainId.ETHEREUM, {
155
+ chainId: EvmChainId.POLYGON,
156
+ address: '0x1234567890abcdef1234567890abcdef12345678',
157
+ symbol: 'TEST',
158
+ name: 'Test Token',
159
+ decimals: 18,
160
+ metadata: { coingeckoId: 'test-token', verified: true },
161
+ }),
162
+ ).toEqualTypeOf<EvmToken<Metadata>>()
163
+
164
+ expectTypeOf(
165
+ getTokenFor(MvmChainId.APTOS, {
166
+ address: '0x1::aptos_coin::AptosCoin',
167
+ symbol: 'APT',
168
+ name: 'Aptos Coin',
169
+ decimals: 8,
170
+ }),
171
+ ).toEqualTypeOf<MvmToken<Record<string, unknown>>>()
172
+
173
+ expectTypeOf(
174
+ getTokenFor(SvmChainId.SOLANA, {
175
+ address: svmAddress('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
176
+ symbol: 'USDC',
177
+ name: 'USD Coin',
178
+ decimals: 6,
179
+ metadata: { coingeckoId: 'usd-coin', verified: true },
180
+ }),
181
+ ).toEqualTypeOf<SvmToken<Metadata>>()
182
+
183
+ expectTypeOf(
184
+ getTokenFor(StellarChainId.STELLAR, {
185
+ address: 'CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA',
186
+ symbol: 'XLM',
187
+ name: 'XLM',
188
+ decimals: 7,
189
+ }),
190
+ ).toEqualTypeOf<StellarToken<Record<string, unknown>>>()
191
+ })
192
+
193
+ it('returns a token union for generic chain id unions', () => {
194
+ const chainId = {} as EvmChainId | SvmChainId
195
+ const data = {} as TokenConstructorDataFor<
196
+ EvmChainId | SvmChainId,
197
+ Metadata
198
+ >
199
+
200
+ expectTypeOf(getTokenFor(chainId, data)).toEqualTypeOf<
201
+ EvmToken<Metadata> | SvmToken<Metadata>
202
+ >()
203
+ })
204
+
205
+ it('rejects constructor data for a different chain family', () => {
206
+ getTokenFor(SvmChainId.SOLANA, {
207
+ // @ts-expect-error SVM token data requires an SVM address.
208
+ address: '0x1234567890abcdef1234567890abcdef12345678',
209
+ symbol: 'TEST',
210
+ name: 'Test Token',
211
+ decimals: 18,
212
+ })
213
+
214
+ getTokenFor(MvmChainId.APTOS, {
215
+ address: '0x1::aptos_coin::AptosCoin',
216
+ symbol: 'APT',
217
+ name: 'Aptos Coin',
218
+ decimals: 8,
219
+ // @ts-expect-error issuer is Stellar-specific token data.
220
+ issuer: 'GDMTVHLWJTHSUDMZVVMXXH6VJHA2ZV3HNG5LYNAZ6RTWB7GISM6PGTUV',
221
+ })
222
+ })
223
+ })
224
+ })
@@ -0,0 +1,108 @@
1
+ import { describe, expect, expectTypeOf, it } from 'vitest'
2
+ import { EvmChainId } from '../../evm/chain/chains.js'
3
+ import { EvmNative } from '../../evm/currency/native.js'
4
+ import { EvmToken } from '../../evm/currency/token.js'
5
+ import { MvmChainId } from '../../mvm/chain/chains.js'
6
+ import { MvmToken } from '../../mvm/currency/token.js'
7
+ import { StellarChainId } from '../../stellar/chain/chains.js'
8
+ import { StellarToken } from '../../stellar/currency/token.js'
9
+ import { SvmChainId } from '../../svm/chain/chains.js'
10
+ import { SvmNative } from '../../svm/currency/native.js'
11
+ import { SvmToken, svmAddress } from '../../svm/currency/token.js'
12
+ import { getNativeFor, getTokenFor } from './for-chain.js'
13
+
14
+ describe('generic/currency/for-chain.ts', () => {
15
+ describe('getNativeFor', () => {
16
+ it('creates EVM native currencies with metadata', () => {
17
+ type Metadata = { verified: boolean }
18
+ const metadata: Metadata = { verified: true }
19
+
20
+ const native = getNativeFor(EvmChainId.ETHEREUM, metadata)
21
+
22
+ expect(native).toBeInstanceOf(EvmNative)
23
+ expect(native.chainId).toBe(EvmChainId.ETHEREUM)
24
+ expect(native.metadata).toBe(metadata)
25
+ expectTypeOf(native).toEqualTypeOf<EvmNative<Metadata>>()
26
+ })
27
+
28
+ it('creates SVM native currencies with metadata', () => {
29
+ type Metadata = { coingeckoId: string }
30
+ const metadata: Metadata = { coingeckoId: 'solana' }
31
+
32
+ const native = getNativeFor(SvmChainId.SOLANA, metadata)
33
+
34
+ expect(native).toBeInstanceOf(SvmNative)
35
+ expect(native.chainId).toBe(SvmChainId.SOLANA)
36
+ expect(native.metadata).toBe(metadata)
37
+ expectTypeOf(native).toEqualTypeOf<SvmNative<Metadata>>()
38
+ })
39
+ })
40
+
41
+ describe('getTokenFor', () => {
42
+ it('creates EVM tokens from constructor data', () => {
43
+ type Metadata = { logoUrl: string }
44
+ const metadata: Metadata = { logoUrl: 'https://example.com/token.png' }
45
+
46
+ const token = getTokenFor(EvmChainId.ETHEREUM, {
47
+ chainId: EvmChainId.POLYGON,
48
+ address: '0x1234567890abcdef1234567890abcdef12345678',
49
+ symbol: 'TEST',
50
+ name: 'Test Token',
51
+ decimals: 18,
52
+ metadata,
53
+ })
54
+
55
+ expect(token).toBeInstanceOf(EvmToken)
56
+ expect(token.chainId).toBe(EvmChainId.ETHEREUM)
57
+ expect(token.metadata).toBe(metadata)
58
+ expectTypeOf(token).toEqualTypeOf<EvmToken<Metadata>>()
59
+ })
60
+
61
+ it('creates MVM tokens from constructor data', () => {
62
+ const token = getTokenFor(MvmChainId.APTOS, {
63
+ address: '0x1::aptos_coin::AptosCoin',
64
+ symbol: 'APT',
65
+ name: 'Aptos Coin',
66
+ decimals: 8,
67
+ })
68
+
69
+ expect(token).toBeInstanceOf(MvmToken)
70
+ expect(token.chainId).toBe(MvmChainId.APTOS)
71
+ expectTypeOf(token).toEqualTypeOf<MvmToken<Record<string, unknown>>>()
72
+ })
73
+
74
+ it('creates SVM tokens from constructor data', () => {
75
+ type Metadata = { tags: string[] }
76
+ const metadata: Metadata = { tags: ['stablecoin'] }
77
+
78
+ const token = getTokenFor(SvmChainId.SOLANA, {
79
+ address: svmAddress('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
80
+ symbol: 'USDC',
81
+ name: 'USD Coin',
82
+ decimals: 6,
83
+ metadata,
84
+ })
85
+
86
+ expect(token).toBeInstanceOf(SvmToken)
87
+ expect(token.chainId).toBe(SvmChainId.SOLANA)
88
+ expect(token.metadata).toBe(metadata)
89
+ expectTypeOf(token).toEqualTypeOf<SvmToken<Metadata>>()
90
+ })
91
+
92
+ it('creates Stellar tokens from constructor data', () => {
93
+ const token = getTokenFor(StellarChainId.STELLAR, {
94
+ address: 'CAS3J7GYLGXMF6TDJBBYYSE3HQ6BBSMLNUQ34T6TZMYMW2EVH34XOWMA',
95
+ issuer: 'GDMTVHLWJTHSUDMZVVMXXH6VJHA2ZV3HNG5LYNAZ6RTWB7GISM6PGTUV',
96
+ symbol: 'XLM',
97
+ name: 'XLM',
98
+ decimals: 7,
99
+ origin: 'stellar.org',
100
+ })
101
+
102
+ expect(token).toBeInstanceOf(StellarToken)
103
+ expect(token.chainId).toBe(StellarChainId.STELLAR)
104
+ expect(token.origin).toBe('stellar.org')
105
+ expectTypeOf(token).toEqualTypeOf<StellarToken<Record<string, unknown>>>()
106
+ })
107
+ })
108
+ })
@@ -0,0 +1,133 @@
1
+ import {
2
+ type EvmChainId,
3
+ getEvmChainById,
4
+ isEvmChainId,
5
+ } from '../../evm/chain/chains.js'
6
+ import { EvmNative } from '../../evm/currency/native.js'
7
+ import { EvmToken } from '../../evm/currency/token.js'
8
+ import { isMvmChainId, type MvmChainId } from '../../mvm/chain/chains.js'
9
+ import { MvmToken } from '../../mvm/currency/token.js'
10
+ import {
11
+ isStellarChainId,
12
+ type StellarChainId,
13
+ } from '../../stellar/chain/chains.js'
14
+ import { StellarToken } from '../../stellar/currency/token.js'
15
+ import {
16
+ getSvmChainById,
17
+ isSvmChainId,
18
+ type SvmChainId,
19
+ } from '../../svm/chain/chains.js'
20
+ import { SvmNative } from '../../svm/currency/native.js'
21
+ import { SvmToken } from '../../svm/currency/token.js'
22
+ import type { ChainId } from '../chain/chains.js'
23
+ import type { NativeChainId, NativeFor, TokenFor } from '../types/for-chain.js'
24
+ import { assertNever } from '../utils/assert-never.js'
25
+ import type { CurrencyMetadata } from './currency.js'
26
+
27
+ type ConstructorData<T extends abstract new (...args: any) => any> =
28
+ ConstructorParameters<T>[0] extends { chainId: infer TChainId }
29
+ ? Omit<ConstructorParameters<T>[0], 'chainId'> & { chainId?: TChainId }
30
+ : never
31
+
32
+ type EvmTokenConstructorData<TMetadata extends CurrencyMetadata> =
33
+ ConstructorData<typeof EvmToken<TMetadata>>
34
+ type MvmTokenConstructorData<TMetadata extends CurrencyMetadata> =
35
+ ConstructorData<typeof MvmToken<TMetadata>>
36
+ type SvmTokenConstructorData<TMetadata extends CurrencyMetadata> =
37
+ ConstructorData<typeof SvmToken<TMetadata>>
38
+ type StellarTokenConstructorData<TMetadata extends CurrencyMetadata> =
39
+ ConstructorData<typeof StellarToken<TMetadata>>
40
+
41
+ export type TokenConstructorDataFor<
42
+ TChainId extends ChainId,
43
+ TMetadata extends CurrencyMetadata = CurrencyMetadata,
44
+ > = TChainId extends EvmChainId
45
+ ? EvmTokenConstructorData<TMetadata>
46
+ : TChainId extends MvmChainId
47
+ ? MvmTokenConstructorData<TMetadata>
48
+ : TChainId extends SvmChainId
49
+ ? SvmTokenConstructorData<TMetadata>
50
+ : TChainId extends StellarChainId
51
+ ? StellarTokenConstructorData<TMetadata>
52
+ : never
53
+
54
+ export function getNativeFor<
55
+ TChainId extends NativeChainId,
56
+ TMetadata extends CurrencyMetadata,
57
+ >(chainId: TChainId, metadata: TMetadata): NativeFor<TChainId, TMetadata> {
58
+ if (isEvmChainId(chainId)) {
59
+ const chain = getEvmChainById(chainId)
60
+
61
+ return new EvmNative({
62
+ chainId,
63
+ symbol: chain.viemChain.nativeCurrency.symbol,
64
+ name: chain.viemChain.nativeCurrency.name,
65
+ decimals: chain.viemChain.nativeCurrency.decimals,
66
+ metadata,
67
+ }) as NativeFor<TChainId, TMetadata>
68
+ }
69
+
70
+ if (isSvmChainId(chainId)) {
71
+ const chain = getSvmChainById(chainId)
72
+
73
+ return new SvmNative({
74
+ chainId,
75
+ symbol: chain.nativeCurrency.symbol,
76
+ name: chain.nativeCurrency.name,
77
+ decimals: chain.nativeCurrency.decimals,
78
+ metadata,
79
+ }) as NativeFor<TChainId, TMetadata>
80
+ }
81
+
82
+ assertNever(chainId, `getNativeFor, unsupported chainId: ${chainId}`)
83
+ }
84
+
85
+ export function getTokenFor<
86
+ TChainId extends ChainId,
87
+ TMetadata extends CurrencyMetadata = Record<string, unknown>,
88
+ >(
89
+ chainId: TChainId,
90
+ data: TokenConstructorDataFor<TChainId, TMetadata>,
91
+ ): TokenFor<TChainId, TMetadata> {
92
+ if (isEvmChainId(chainId)) {
93
+ return new EvmToken({
94
+ ...data,
95
+ chainId,
96
+ } as ConstructorParameters<typeof EvmToken<TMetadata>>[0]) as TokenFor<
97
+ TChainId,
98
+ TMetadata
99
+ >
100
+ }
101
+
102
+ if (isMvmChainId(chainId)) {
103
+ return new MvmToken({
104
+ ...data,
105
+ chainId,
106
+ } as ConstructorParameters<typeof MvmToken<TMetadata>>[0]) as TokenFor<
107
+ TChainId,
108
+ TMetadata
109
+ >
110
+ }
111
+
112
+ if (isSvmChainId(chainId)) {
113
+ return new SvmToken({
114
+ ...data,
115
+ chainId,
116
+ } as ConstructorParameters<typeof SvmToken<TMetadata>>[0]) as TokenFor<
117
+ TChainId,
118
+ TMetadata
119
+ >
120
+ }
121
+
122
+ if (isStellarChainId(chainId)) {
123
+ return new StellarToken({
124
+ ...data,
125
+ chainId,
126
+ } as ConstructorParameters<typeof StellarToken<TMetadata>>[0]) as TokenFor<
127
+ TChainId,
128
+ TMetadata
129
+ >
130
+ }
131
+
132
+ assertNever(chainId, `getTokenFor, unsupported chainId: ${chainId}`)
133
+ }
@@ -1,5 +1,6 @@
1
1
  export * from './amount.js'
2
2
  export * from './currency.js'
3
+ export * from './for-chain.js'
3
4
  export * from './native.js'
4
5
  export * from './price.js'
5
6
  export * from './serialized-currency.js'