@provex/utils 1.0.16 → 1.2.3
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.
- package/dist/src/chain.d.ts +436 -4
- package/dist/src/chain.js +80 -0
- package/dist/src/chain.test.d.ts +1 -0
- package/dist/src/chain.test.js +112 -0
- package/dist/src/contracts.d.ts +196 -20
- package/dist/src/contracts.js +245 -17
- package/dist/src/contracts.test.d.ts +1 -0
- package/dist/src/contracts.test.js +243 -0
- package/dist/src/conversionRates.d.ts +99 -8
- package/dist/src/conversionRates.js +74 -4
- package/dist/src/conversionRates.test.d.ts +1 -0
- package/dist/src/conversionRates.test.js +473 -0
- package/dist/src/currencies.d.ts +113 -9
- package/dist/src/currencies.js +119 -38
- package/dist/src/currencies.test.d.ts +1 -0
- package/dist/src/currencies.test.js +343 -0
- package/dist/src/data/countries.json +166 -166
- package/dist/src/deposit.d.ts +69 -1
- package/dist/src/deposit.js +52 -1
- package/dist/src/depositKeys.d.ts +154 -0
- package/dist/src/depositKeys.js +104 -0
- package/dist/src/depositKeys.test.d.ts +1 -0
- package/dist/src/depositKeys.test.js +231 -0
- package/dist/src/endpoints.d.ts +51 -0
- package/dist/src/endpoints.js +70 -0
- package/dist/src/endpoints.test.d.ts +1 -0
- package/dist/src/endpoints.test.js +54 -0
- package/dist/src/events.d.ts +40 -2
- package/dist/src/events.js +86 -10
- package/dist/src/events.test.d.ts +1 -0
- package/dist/src/events.test.js +111 -0
- package/dist/src/fees.d.ts +136 -0
- package/dist/src/fees.js +178 -0
- package/dist/src/fees.test.d.ts +1 -0
- package/dist/src/fees.test.js +165 -0
- package/dist/src/ids.d.ts +125 -22
- package/dist/src/ids.js +211 -61
- package/dist/src/ids.test.d.ts +1 -0
- package/dist/src/ids.test.js +607 -0
- package/dist/src/index.d.ts +30 -1
- package/dist/src/index.js +30 -1
- package/dist/src/input.d.ts +23 -4
- package/dist/src/input.js +23 -4
- package/dist/src/intent.d.ts +38 -2
- package/dist/src/intent.js +28 -1
- package/dist/src/intent.test.d.ts +1 -0
- package/dist/src/intent.test.js +119 -0
- package/dist/src/json.d.ts +38 -1
- package/dist/src/json.js +38 -2
- package/dist/src/normalization.d.ts +224 -0
- package/dist/src/normalization.js +119 -0
- package/dist/src/normalization.test.d.ts +1 -0
- package/dist/src/normalization.test.js +284 -0
- package/dist/src/participants.d.ts +19 -4
- package/dist/src/participants.js +19 -4
- package/dist/src/payment.d.ts +333 -16
- package/dist/src/payment.js +768 -58
- package/dist/src/payment.test.d.ts +1 -0
- package/dist/src/payment.test.js +272 -0
- package/dist/src/peer-types.d.ts +327 -0
- package/dist/src/peer-types.js +169 -0
- package/dist/src/profit.d.ts +26 -5
- package/dist/src/profit.js +31 -8
- package/dist/src/profit.test.d.ts +1 -0
- package/dist/src/profit.test.js +315 -0
- package/dist/src/reputation.d.ts +125 -0
- package/dist/src/reputation.js +188 -0
- package/dist/src/reputation.test.d.ts +1 -0
- package/dist/src/reputation.test.js +156 -0
- package/dist/src/sort.d.ts +49 -10
- package/dist/src/sort.js +40 -9
- package/dist/src/sort.test.d.ts +1 -0
- package/dist/src/sort.test.js +216 -0
- package/dist/src/stateKey.d.ts +35 -0
- package/dist/src/stateKey.js +36 -0
- package/dist/src/stats.d.ts +55 -1
- package/dist/src/stats.js +46 -1
- package/dist/src/stats.test.d.ts +1 -0
- package/dist/src/stats.test.js +104 -0
- package/dist/src/time.d.ts +59 -9
- package/dist/src/time.js +71 -15
- package/dist/src/time.test.d.ts +1 -0
- package/dist/src/time.test.js +231 -0
- package/dist/src/tokens.d.ts +11972 -145
- package/dist/src/tokens.js +98 -17
- package/dist/src/tokens.test.d.ts +1 -0
- package/dist/src/tokens.test.js +193 -0
- package/dist/src/units.d.ts +183 -0
- package/dist/src/units.js +206 -6
- package/dist/src/units.test.d.ts +1 -0
- package/dist/src/units.test.js +327 -0
- package/dist/src/zkp2p-types.d.ts +273 -4
- package/dist/src/zkp2p-types.js +169 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +116 -26
- package/scripts/convert-svg.ts +0 -22
- package/src/chain.ts +0 -27
- package/src/contracts.ts +0 -89
- package/src/conversionRates.ts +0 -356
- package/src/currencies.ts +0 -286
- package/src/data/countries.json +0 -1099
- package/src/deposit.ts +0 -2
- package/src/events.ts +0 -21
- package/src/flags/eur.svg +0 -4
- package/src/flags/usd.svg +0 -25
- package/src/flags.ts +0 -4
- package/src/global.d.ts +0 -9
- package/src/ids.ts +0 -137
- package/src/index.ts +0 -16
- package/src/input.ts +0 -35
- package/src/intent.ts +0 -15
- package/src/json.ts +0 -42
- package/src/participants.ts +0 -14
- package/src/payment.ts +0 -573
- package/src/profit.ts +0 -55
- package/src/sort.ts +0 -49
- package/src/stats.ts +0 -10
- package/src/time.ts +0 -123
- package/src/tokens.ts +0 -159
- package/src/units.ts +0 -120
- package/src/zkp2p-types.ts +0 -55
- package/tsconfig.json +0 -18
package/dist/src/tokens.js
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Token definitions and utilities for supported ERC20 tokens.
|
|
3
|
+
*
|
|
4
|
+
* This module defines the supported tokens (currently USDC) on each chain
|
|
5
|
+
* and provides utilities for token lookups and public client access.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* - USDC is the primary token used for escrow deposits
|
|
9
|
+
* - Each chain has its own USDC contract address
|
|
10
|
+
* - Base uses native USDC, Pulsechain uses bridged USDC from Ethereum
|
|
11
|
+
*
|
|
12
|
+
* @see {@link chain} for chain configuration
|
|
13
|
+
* @see {@link contracts} for escrow contract addresses
|
|
14
|
+
*/
|
|
1
15
|
import { createPublicClient, getAddress, http } from 'viem';
|
|
2
16
|
import { base, pulsechain } from 'viem/chains';
|
|
3
17
|
import { chains } from './chain.js';
|
|
18
|
+
/**
|
|
19
|
+
* Pre-configured public clients for supported chains.
|
|
20
|
+
* Used for read-only blockchain interactions (balances, contract reads).
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
const clients = {
|
|
25
|
+
[base.id]: createPublicClient({
|
|
26
|
+
chain: base,
|
|
27
|
+
transport: http(),
|
|
28
|
+
}),
|
|
29
|
+
[pulsechain.id]: createPublicClient({
|
|
30
|
+
chain: pulsechain,
|
|
31
|
+
transport: http(),
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Get a public client for a given chain.
|
|
36
|
+
* @param chain - The viem chain object
|
|
37
|
+
* @returns A viem public client instance for the chain
|
|
38
|
+
* @throws Error if chain is undefined or not configured
|
|
39
|
+
*/
|
|
40
|
+
export const publicClient = (chain) => {
|
|
41
|
+
if (!chain || !chain.id) {
|
|
42
|
+
throw new Error('Chain parameter is required and must have an id property');
|
|
43
|
+
}
|
|
44
|
+
const client = clients[chain.id];
|
|
45
|
+
if (!client) {
|
|
46
|
+
throw new Error(`No client configured for chainId ${chain.id}. Supported chains: ${Object.keys(clients).join(', ')}`);
|
|
47
|
+
}
|
|
48
|
+
return client;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* USDC token configuration for Base network.
|
|
52
|
+
* This is native Circle-issued USDC on Base.
|
|
53
|
+
*/
|
|
4
54
|
const BASE_USDC = {
|
|
5
55
|
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
6
56
|
decimals: 6,
|
|
@@ -8,6 +58,14 @@ const BASE_USDC = {
|
|
|
8
58
|
name: 'USD Coin',
|
|
9
59
|
chainId: base.id,
|
|
10
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* USDC token configuration for Pulsechain.
|
|
63
|
+
* This is bridged USDC from Ethereum mainnet.
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* The mainnetAddress field references the original Ethereum USDC contract,
|
|
67
|
+
* which can be useful for price oracle lookups and cross-chain verification.
|
|
68
|
+
*/
|
|
11
69
|
export const PULSECHAIN_USDC = {
|
|
12
70
|
address: '0x15D38573d2feeb82e7ad5187aB8c1D52810B1f07',
|
|
13
71
|
decimals: 6,
|
|
@@ -16,7 +74,19 @@ export const PULSECHAIN_USDC = {
|
|
|
16
74
|
chainId: pulsechain.id,
|
|
17
75
|
mainnetAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
18
76
|
};
|
|
19
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Registry of all supported tokens organized by chain ID and symbol.
|
|
79
|
+
* Currently only USDC is supported, but the structure allows for future expansion.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* // Get Base USDC
|
|
84
|
+
* const baseUsdc = allTokensInfo[8453].USDC
|
|
85
|
+
*
|
|
86
|
+
* // Get Pulsechain USDC
|
|
87
|
+
* const pulseUsdc = allTokensInfo[369].USDC
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
20
90
|
export const allTokensInfo = {
|
|
21
91
|
[base.id]: {
|
|
22
92
|
// Base Network Tokens
|
|
@@ -94,9 +164,36 @@ export const allTokensInfo = {
|
|
|
94
164
|
// mainnetAddress: '0x0000000000000000000000000000000000000000',
|
|
95
165
|
// } as TokenInfo,
|
|
96
166
|
};
|
|
167
|
+
/**
|
|
168
|
+
* Get the default token (USDC) for a given chain.
|
|
169
|
+
*
|
|
170
|
+
* @param chainId - The chain ID, or null to default to Pulsechain
|
|
171
|
+
* @returns TokenInfo for USDC on the specified chain, or null if chain not supported
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* const baseUsdc = getDefaultToken(8453)
|
|
176
|
+
* // { address: '0x833589...', decimals: 6, symbol: 'USDC', ... }
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
97
179
|
export const getDefaultToken = (chainId) => {
|
|
98
180
|
return allTokensInfo[chainId ?? pulsechain.id]?.USDC ?? null;
|
|
99
181
|
};
|
|
182
|
+
/**
|
|
183
|
+
* Get default tokens (USDC) for multiple chains.
|
|
184
|
+
*
|
|
185
|
+
* @param chainIds - Array of chain IDs. If empty, returns tokens for all supported chains.
|
|
186
|
+
* @returns Array of TokenInfo objects, one per chain
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* // Get USDC for Base and Pulsechain
|
|
191
|
+
* const tokens = getDefaultTokens([8453, 369])
|
|
192
|
+
*
|
|
193
|
+
* // Get USDC for all supported chains
|
|
194
|
+
* const allTokens = getDefaultTokens([])
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
100
197
|
export const getDefaultTokens = (chainIds) => {
|
|
101
198
|
return chainIds.length ? chainIds.map((chainId) => getDefaultToken(chainId)) : chains.map((chain) => getDefaultToken(chain.id));
|
|
102
199
|
};
|
|
@@ -116,19 +213,3 @@ export const getTokensByChainId = (chainId) => {
|
|
|
116
213
|
export const tokenByAddress = (chainId, address) => {
|
|
117
214
|
return !address ? null : Object.values(allTokensInfo[chainId] ?? {}).find(token => getAddress(token.address) === getAddress(address)) ?? null;
|
|
118
215
|
};
|
|
119
|
-
/**
|
|
120
|
-
* Create a public client for reading from contracts
|
|
121
|
-
* @param chain - The chain
|
|
122
|
-
* @returns The public client
|
|
123
|
-
*/
|
|
124
|
-
export const publicClient = (chain) => createPublicClient({
|
|
125
|
-
chain,
|
|
126
|
-
transport: http()
|
|
127
|
-
});
|
|
128
|
-
// export const pulseChainTokenToMainnet = (pulsechainToken: TokenInfo) => {
|
|
129
|
-
// const tokens = allTokensInfo[mainnet.id]
|
|
130
|
-
// const token = Object.values(tokens).find((t) => (
|
|
131
|
-
// getAddress(t.address) === getAddress(pulsechainToken.mainnetAddress!)
|
|
132
|
-
// ))
|
|
133
|
-
// return token!
|
|
134
|
-
// }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { base, pulsechain } from 'viem/chains';
|
|
4
|
+
import { publicClient, getDefaultToken, getDefaultTokens, getTokensByChainId, tokenByAddress, allTokensInfo, PULSECHAIN_USDC, } from './tokens.js';
|
|
5
|
+
import { chains, chainIds } from './chain.js';
|
|
6
|
+
describe('tokens', () => {
|
|
7
|
+
describe('allTokensInfo', () => {
|
|
8
|
+
it('should have token info for Base', () => {
|
|
9
|
+
const baseTokens = allTokensInfo[base.id];
|
|
10
|
+
assert.ok(baseTokens, 'Base tokens should exist');
|
|
11
|
+
assert.ok(baseTokens.USDC, 'Base should have USDC');
|
|
12
|
+
});
|
|
13
|
+
it('should have token info for Pulsechain', () => {
|
|
14
|
+
const pulseTokens = allTokensInfo[pulsechain.id];
|
|
15
|
+
assert.ok(pulseTokens, 'Pulsechain tokens should exist');
|
|
16
|
+
assert.ok(pulseTokens.USDC, 'Pulsechain should have USDC');
|
|
17
|
+
});
|
|
18
|
+
it('should have correct USDC address for Base', () => {
|
|
19
|
+
const baseUSDC = allTokensInfo[base.id].USDC;
|
|
20
|
+
assert.equal(baseUSDC.address, '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
21
|
+
assert.equal(baseUSDC.decimals, 6);
|
|
22
|
+
assert.equal(baseUSDC.symbol, 'USDC');
|
|
23
|
+
assert.equal(baseUSDC.name, 'USD Coin');
|
|
24
|
+
assert.equal(baseUSDC.chainId, base.id);
|
|
25
|
+
});
|
|
26
|
+
it('should have correct USDC address for Pulsechain', () => {
|
|
27
|
+
const pulseUSDC = allTokensInfo[pulsechain.id].USDC;
|
|
28
|
+
assert.equal(pulseUSDC.address, '0x15D38573d2feeb82e7ad5187aB8c1D52810B1f07');
|
|
29
|
+
assert.equal(pulseUSDC.decimals, 6);
|
|
30
|
+
assert.equal(pulseUSDC.symbol, 'USDC');
|
|
31
|
+
assert.equal(pulseUSDC.chainId, pulsechain.id);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('PULSECHAIN_USDC', () => {
|
|
35
|
+
it('should have mainnetAddress for bridged token', () => {
|
|
36
|
+
assert.ok(PULSECHAIN_USDC.mainnetAddress, 'Should have mainnet address');
|
|
37
|
+
assert.equal(PULSECHAIN_USDC.mainnetAddress, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48');
|
|
38
|
+
});
|
|
39
|
+
it('should have correct properties', () => {
|
|
40
|
+
assert.equal(PULSECHAIN_USDC.address, '0x15D38573d2feeb82e7ad5187aB8c1D52810B1f07');
|
|
41
|
+
assert.equal(PULSECHAIN_USDC.decimals, 6);
|
|
42
|
+
assert.equal(PULSECHAIN_USDC.symbol, 'USDC');
|
|
43
|
+
assert.equal(PULSECHAIN_USDC.name, 'USD Coin from Ethereum');
|
|
44
|
+
assert.equal(PULSECHAIN_USDC.chainId, pulsechain.id);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('publicClient', () => {
|
|
48
|
+
it('should return client for Base', () => {
|
|
49
|
+
const client = publicClient(base);
|
|
50
|
+
assert.ok(client, 'Client should exist');
|
|
51
|
+
assert.ok(client.readContract, 'Client should have readContract method');
|
|
52
|
+
});
|
|
53
|
+
it('should return client for Pulsechain', () => {
|
|
54
|
+
const client = publicClient(pulsechain);
|
|
55
|
+
assert.ok(client, 'Client should exist');
|
|
56
|
+
assert.ok(client.readContract, 'Client should have readContract method');
|
|
57
|
+
});
|
|
58
|
+
it('should throw for undefined chain', () => {
|
|
59
|
+
assert.throws(() => publicClient(undefined), { message: 'Chain parameter is required and must have an id property' });
|
|
60
|
+
});
|
|
61
|
+
it('should throw for chain without id', () => {
|
|
62
|
+
assert.throws(() => publicClient({}), { message: 'Chain parameter is required and must have an id property' });
|
|
63
|
+
});
|
|
64
|
+
it('should throw for unsupported chain', () => {
|
|
65
|
+
const unsupportedChain = { id: 99999, name: 'Unsupported' };
|
|
66
|
+
assert.throws(() => publicClient(unsupportedChain), /No client configured for chainId 99999/);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('getDefaultToken', () => {
|
|
70
|
+
it('should return USDC for Base', () => {
|
|
71
|
+
const token = getDefaultToken(base.id);
|
|
72
|
+
assert.ok(token, 'Token should exist');
|
|
73
|
+
assert.equal(token.symbol, 'USDC');
|
|
74
|
+
assert.equal(token.chainId, base.id);
|
|
75
|
+
});
|
|
76
|
+
it('should return USDC for Pulsechain', () => {
|
|
77
|
+
const token = getDefaultToken(pulsechain.id);
|
|
78
|
+
assert.ok(token, 'Token should exist');
|
|
79
|
+
assert.equal(token.symbol, 'USDC');
|
|
80
|
+
assert.equal(token.chainId, pulsechain.id);
|
|
81
|
+
});
|
|
82
|
+
it('should default to Pulsechain when chainId is null', () => {
|
|
83
|
+
const token = getDefaultToken(null);
|
|
84
|
+
assert.ok(token, 'Token should exist');
|
|
85
|
+
assert.equal(token.chainId, pulsechain.id);
|
|
86
|
+
});
|
|
87
|
+
it('should return null for unsupported chain', () => {
|
|
88
|
+
const token = getDefaultToken(99999);
|
|
89
|
+
assert.equal(token, null);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('getDefaultTokens', () => {
|
|
93
|
+
it('should return tokens for specified chains', () => {
|
|
94
|
+
const tokens = getDefaultTokens([base.id, pulsechain.id]);
|
|
95
|
+
assert.equal(tokens.length, 2);
|
|
96
|
+
assert.ok(tokens[0], 'First token should exist');
|
|
97
|
+
assert.ok(tokens[1], 'Second token should exist');
|
|
98
|
+
assert.equal(tokens[0].chainId, base.id);
|
|
99
|
+
assert.equal(tokens[1].chainId, pulsechain.id);
|
|
100
|
+
});
|
|
101
|
+
it('should return tokens for all chains when empty array provided', () => {
|
|
102
|
+
const tokens = getDefaultTokens([]);
|
|
103
|
+
assert.equal(tokens.length, chains.length);
|
|
104
|
+
});
|
|
105
|
+
it('should return tokens in order of chainIds', () => {
|
|
106
|
+
const tokens = getDefaultTokens([pulsechain.id, base.id]);
|
|
107
|
+
assert.equal(tokens[0].chainId, pulsechain.id);
|
|
108
|
+
assert.equal(tokens[1].chainId, base.id);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('getTokensByChainId', () => {
|
|
112
|
+
it('should return array of tokens for Base', () => {
|
|
113
|
+
const tokens = getTokensByChainId(base.id);
|
|
114
|
+
assert.ok(Array.isArray(tokens), 'Should return an array');
|
|
115
|
+
assert.ok(tokens.length > 0, 'Should have at least one token');
|
|
116
|
+
assert.ok(tokens.some(t => t.symbol === 'USDC'), 'Should include USDC');
|
|
117
|
+
});
|
|
118
|
+
it('should return array of tokens for Pulsechain', () => {
|
|
119
|
+
const tokens = getTokensByChainId(pulsechain.id);
|
|
120
|
+
assert.ok(Array.isArray(tokens), 'Should return an array');
|
|
121
|
+
assert.ok(tokens.length > 0, 'Should have at least one token');
|
|
122
|
+
assert.ok(tokens.some(t => t.symbol === 'USDC'), 'Should include USDC');
|
|
123
|
+
});
|
|
124
|
+
it('should return empty array for unsupported chain', () => {
|
|
125
|
+
const tokens = getTokensByChainId(99999);
|
|
126
|
+
assert.ok(Array.isArray(tokens), 'Should return an array');
|
|
127
|
+
assert.equal(tokens.length, 0);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe('tokenByAddress', () => {
|
|
131
|
+
it('should find Base USDC by address', () => {
|
|
132
|
+
const address = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
|
|
133
|
+
const token = tokenByAddress(base.id, address);
|
|
134
|
+
assert.ok(token, 'Token should be found');
|
|
135
|
+
assert.equal(token.symbol, 'USDC');
|
|
136
|
+
assert.equal(token.chainId, base.id);
|
|
137
|
+
});
|
|
138
|
+
it('should find Pulsechain USDC by address', () => {
|
|
139
|
+
const address = '0x15D38573d2feeb82e7ad5187aB8c1D52810B1f07';
|
|
140
|
+
const token = tokenByAddress(pulsechain.id, address);
|
|
141
|
+
assert.ok(token, 'Token should be found');
|
|
142
|
+
assert.equal(token.symbol, 'USDC');
|
|
143
|
+
assert.equal(token.chainId, pulsechain.id);
|
|
144
|
+
});
|
|
145
|
+
it('should be case-insensitive for address lookup', () => {
|
|
146
|
+
const lowerAddress = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913';
|
|
147
|
+
const upperAddress = '0x833589FCD6EDB6E08F4C7C32D4F71B54BDA02913';
|
|
148
|
+
const tokenLower = tokenByAddress(base.id, lowerAddress);
|
|
149
|
+
const tokenUpper = tokenByAddress(base.id, upperAddress);
|
|
150
|
+
assert.ok(tokenLower, 'Should find token with lowercase address');
|
|
151
|
+
assert.ok(tokenUpper, 'Should find token with uppercase address');
|
|
152
|
+
assert.deepEqual(tokenLower, tokenUpper);
|
|
153
|
+
});
|
|
154
|
+
it('should return null for undefined address', () => {
|
|
155
|
+
const token = tokenByAddress(base.id, undefined);
|
|
156
|
+
assert.equal(token, null);
|
|
157
|
+
});
|
|
158
|
+
it('should return null for non-existent address', () => {
|
|
159
|
+
const token = tokenByAddress(base.id, '0x0000000000000000000000000000000000000001');
|
|
160
|
+
assert.equal(token, null);
|
|
161
|
+
});
|
|
162
|
+
it('should return null for unsupported chain', () => {
|
|
163
|
+
const token = tokenByAddress(99999, '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
164
|
+
assert.equal(token, null);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe('TokenInfo interface', () => {
|
|
168
|
+
it('all tokens have required properties', () => {
|
|
169
|
+
for (const chainId of chainIds) {
|
|
170
|
+
const chainTokens = allTokensInfo[chainId];
|
|
171
|
+
if (!chainTokens)
|
|
172
|
+
continue;
|
|
173
|
+
for (const [symbol, token] of Object.entries(chainTokens)) {
|
|
174
|
+
assert.ok(token.address, `${symbol} should have address`);
|
|
175
|
+
assert.ok(typeof token.decimals === 'number', `${symbol} should have decimals`);
|
|
176
|
+
assert.ok(token.symbol, `${symbol} should have symbol`);
|
|
177
|
+
assert.ok(token.name, `${symbol} should have name`);
|
|
178
|
+
assert.ok(token.chainId, `${symbol} should have chainId`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
it('all token addresses are valid ethereum addresses', () => {
|
|
183
|
+
for (const chainId of chainIds) {
|
|
184
|
+
const chainTokens = allTokensInfo[chainId];
|
|
185
|
+
if (!chainTokens)
|
|
186
|
+
continue;
|
|
187
|
+
for (const [symbol, token] of Object.entries(chainTokens)) {
|
|
188
|
+
assert.match(token.address, /^0x[a-fA-F0-9]{40}$/, `${symbol} address should be valid`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
});
|
package/dist/src/units.d.ts
CHANGED
|
@@ -1,17 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Unit conversion and formatting utilities for token amounts.
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for converting between human-readable amounts
|
|
5
|
+
* and blockchain-native bigint values, with support for:
|
|
6
|
+
* - Decimal precision (6 for USDC, 18 for ETH)
|
|
7
|
+
* - Thousands separators for display
|
|
8
|
+
* - Truncation and padding options
|
|
9
|
+
* - Number abbreviation (k, M, B, T)
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* All amounts in smart contracts are stored as bigints without decimals.
|
|
13
|
+
* For example, 100 USDC = 100_000000n (6 decimals).
|
|
14
|
+
*
|
|
15
|
+
* @see {@link tokens} for token decimal configurations
|
|
16
|
+
* @see {@link currencies} for fiat currency decimals
|
|
17
|
+
*/
|
|
1
18
|
import type { TokenInfo } from './tokens.js';
|
|
19
|
+
/**
|
|
20
|
+
* Constant representing 1 ether in wei (10^18).
|
|
21
|
+
* Used for 18-decimal precision calculations.
|
|
22
|
+
*/
|
|
2
23
|
export declare const oneEther: bigint;
|
|
24
|
+
/**
|
|
25
|
+
* Add thousands separators to a number string for improved readability.
|
|
26
|
+
*
|
|
27
|
+
* @param numberString - The number string to format
|
|
28
|
+
* @param delimiter - The separator character (default: ',')
|
|
29
|
+
* @returns Formatted string with separators
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* addThousandsSeparator('1234567.89') // '1,234,567.89'
|
|
34
|
+
* addThousandsSeparator('1000', ' ') // '1 000'
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
3
37
|
export declare function addThousandsSeparator(numberString: string, delimiter?: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Options for formatting bigint amounts as human-readable strings.
|
|
40
|
+
*/
|
|
4
41
|
export interface FormatRateDisplayOptions {
|
|
42
|
+
/** Number of decimal places in the bigint (e.g., 6 for USDC, 18 for ETH) */
|
|
5
43
|
decimals: number;
|
|
44
|
+
/** Maximum decimal places to show (truncates excess precision) */
|
|
6
45
|
truncateDecimals?: number;
|
|
46
|
+
/** Minimum decimal places to show (pads with zeros) */
|
|
7
47
|
padDecimals?: number;
|
|
48
|
+
/** If amount is below this, display as "<cutoff" (e.g., "<0.01") */
|
|
8
49
|
cutoff?: bigint;
|
|
50
|
+
/** Thousands separator character (default: ',') */
|
|
9
51
|
delimiter?: string;
|
|
52
|
+
/** Whether to round up instead of truncating (default: false) */
|
|
10
53
|
roundUp?: boolean;
|
|
11
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Parse a human-readable amount string into a bigint.
|
|
57
|
+
* Handles thousands separators and decimal places.
|
|
58
|
+
*
|
|
59
|
+
* @param amount - Human-readable amount (e.g., '1,234.56')
|
|
60
|
+
* @param options - Parsing options with decimals and optional delimiter
|
|
61
|
+
* @returns BigInt representation of the amount
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* // Parse USDC amount (6 decimals)
|
|
66
|
+
* parseUnits('100.50', { decimals: 6 }) // 100_500000n
|
|
67
|
+
*
|
|
68
|
+
* // Parse with thousands separator
|
|
69
|
+
* parseUnits('1,234.56', { decimals: 6 }) // 1_234_560000n
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
12
72
|
export declare const parseUnits: (amount: string, options: Pick<FormatRateDisplayOptions, "decimals" | "delimiter">) => bigint;
|
|
73
|
+
/**
|
|
74
|
+
* Format a bigint amount as a human-readable string with configurable precision.
|
|
75
|
+
*
|
|
76
|
+
* @param amount - BigInt amount to format
|
|
77
|
+
* @param options - Formatting options
|
|
78
|
+
* @returns Formatted string with decimal point and thousands separators
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* // Basic formatting
|
|
83
|
+
* formatUnits(100_500000n, { decimals: 6, padDecimals: 2 }) // '100.50'
|
|
84
|
+
*
|
|
85
|
+
* // With truncation
|
|
86
|
+
* formatUnits(100_123456n, { decimals: 6, truncateDecimals: 2 }) // '100.12'
|
|
87
|
+
*
|
|
88
|
+
* // With cutoff for small amounts
|
|
89
|
+
* formatUnits(100n, { decimals: 6, cutoff: 1000n }) // '<0.001'
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
13
92
|
export declare function formatUnits(amount: bigint, options: FormatRateDisplayOptions): string;
|
|
93
|
+
/**
|
|
94
|
+
* Format a token amount for display with 2 decimal places.
|
|
95
|
+
* Convenience wrapper around formatUnits with truncateDecimals: 2.
|
|
96
|
+
*
|
|
97
|
+
* @param amount - BigInt amount to format
|
|
98
|
+
* @param options - Formatting options (truncateDecimals defaults to 2)
|
|
99
|
+
* @returns Formatted string with 2 decimal places
|
|
100
|
+
*/
|
|
14
101
|
export declare function formatTokenAmountForDisplay(amount: bigint, options: FormatRateDisplayOptions): string;
|
|
102
|
+
/**
|
|
103
|
+
* Safely parse a string to an integer without using Number() constructor.
|
|
104
|
+
* Uses parseInt which is more predictable for integer-only parsing.
|
|
105
|
+
*
|
|
106
|
+
* @param value - String value to parse
|
|
107
|
+
* @returns Parsed integer or null if invalid
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* parseIntegerSafe('123') // 123
|
|
112
|
+
* parseIntegerSafe('123.45') // 123 (truncates decimal)
|
|
113
|
+
* parseIntegerSafe('abc') // null
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
15
116
|
export declare function parseIntegerSafe(value: string): number | null;
|
|
117
|
+
/**
|
|
118
|
+
* Convert a blockchain timestamp (Unix seconds) to a JavaScript Date object.
|
|
119
|
+
*
|
|
120
|
+
* @param timestamp - Unix timestamp in seconds (string, number, or bigint)
|
|
121
|
+
* @returns Date object, or null if timestamp is falsy
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* timestampToDate(1704067200) // Date: 2024-01-01T00:00:00.000Z
|
|
126
|
+
* timestampToDate('1704067200') // Date: 2024-01-01T00:00:00.000Z
|
|
127
|
+
* timestampToDate(1704067200n) // Date: 2024-01-01T00:00:00.000Z
|
|
128
|
+
* timestampToDate(null) // null
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
16
131
|
export declare function timestampToDate(timestamp: string | number | bigint | undefined | null): Date | null;
|
|
132
|
+
/**
|
|
133
|
+
* Format a token amount using the token's decimal configuration.
|
|
134
|
+
*
|
|
135
|
+
* @param token - Token info with decimals
|
|
136
|
+
* @param amount - BigInt amount to format, or null
|
|
137
|
+
* @param options - Optional formatting overrides
|
|
138
|
+
* @returns Formatted string, or null if amount is null
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* const usdc = { decimals: 6, ... }
|
|
143
|
+
* formatAmount(usdc, 100_500000n) // '100.50'
|
|
144
|
+
* formatAmount(usdc, null) // null
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
17
147
|
export declare const formatAmount: (token: TokenInfo, amount: bigint | null, options?: Partial<FormatRateDisplayOptions>) => string | null;
|
|
148
|
+
/**
|
|
149
|
+
* Numeric abbreviation suffixes and their divisors.
|
|
150
|
+
* Used by abbreviateNumber() for compact number display.
|
|
151
|
+
*/
|
|
152
|
+
export declare const numericAbbreviations: readonly [{
|
|
153
|
+
readonly divisor: 1000000000000n;
|
|
154
|
+
readonly suffix: "T";
|
|
155
|
+
}, {
|
|
156
|
+
readonly divisor: 1000000000n;
|
|
157
|
+
readonly suffix: "B";
|
|
158
|
+
}, {
|
|
159
|
+
readonly divisor: 1000000n;
|
|
160
|
+
readonly suffix: "M";
|
|
161
|
+
}, {
|
|
162
|
+
readonly divisor: 1000n;
|
|
163
|
+
readonly suffix: "k";
|
|
164
|
+
}];
|
|
165
|
+
/**
|
|
166
|
+
* Formats a bigint value with a specific numeric abbreviation suffix
|
|
167
|
+
* @param value - The bigint value to format
|
|
168
|
+
* @param options - Configuration for formatting
|
|
169
|
+
* @returns Formatted string with suffix (e.g., "1.23k", "400M")
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* formatWithAbbreviation(1234567n, { decimals: 2, divisor: 1_000n, suffix: 'k' }) // "1234.57k"
|
|
173
|
+
* formatWithAbbreviation(400000000n, { decimals: 2, divisor: 1_000_000n, suffix: 'M' }) // "400M"
|
|
174
|
+
*/
|
|
175
|
+
export declare function formatWithAbbreviation(value: bigint, options: {
|
|
176
|
+
decimals: number;
|
|
177
|
+
divisor: bigint;
|
|
178
|
+
suffix: string;
|
|
179
|
+
maxDecimals?: number;
|
|
180
|
+
/** Minimum decimal places to show — prevents auto-reduction for large values. */
|
|
181
|
+
minDecimals?: number;
|
|
182
|
+
}): string;
|
|
183
|
+
/**
|
|
184
|
+
* Abbreviates large numbers using k, M, B, T suffixes
|
|
185
|
+
* @param value - The bigint value to abbreviate
|
|
186
|
+
* @param options - Optional configuration for decimal places and decimals precision
|
|
187
|
+
* @returns Abbreviated number string (e.g., "1.5k", "200k", "1.2M")
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* abbreviateNumber(1500n, { decimals: 0 }) // "1.5k"
|
|
191
|
+
* abbreviateNumber(200000n, { decimals: 0 }) // "200k"
|
|
192
|
+
* abbreviateNumber(1234567n, { decimals: 0 }) // "1.23M"
|
|
193
|
+
* abbreviateNumber(1000000000n, { decimals: 0 }) // "1B"
|
|
194
|
+
* abbreviateNumber(123456n, { decimals: 2 }) // "1.23k" (if input is 1234.56 with 2 decimals)
|
|
195
|
+
*/
|
|
196
|
+
export declare function abbreviateNumber(value: bigint, options: {
|
|
197
|
+
decimals: number;
|
|
198
|
+
maxDecimals?: number;
|
|
199
|
+
minDecimals?: number;
|
|
200
|
+
}): string;
|