agentwallet-sdk 6.0.1 → 6.0.2
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/README.md +256 -4
- package/dist/bridge/__tests__/solana.test.js +1 -1
- package/dist/bridge/__tests__/solana.test.js.map +1 -1
- package/dist/escrow/MutualStakeEscrow.d.ts.map +1 -1
- package/dist/escrow/MutualStakeEscrow.js +3 -5
- package/dist/escrow/MutualStakeEscrow.js.map +1 -1
- package/dist/index.d.ts +49 -253
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -6
- package/dist/index.js.map +1 -1
- package/dist/policy/SpendingPolicy.test.js.map +1 -1
- package/dist/swap/SwapModule.d.ts.map +1 -1
- package/dist/swap/SwapModule.js +3 -3
- package/dist/swap/SwapModule.js.map +1 -1
- package/dist/swap/index.d.ts +1 -1
- package/dist/swap/index.d.ts.map +1 -1
- package/dist/swap/index.js +1 -1
- package/dist/swap/index.js.map +1 -1
- package/dist/swap/types.d.ts +0 -2
- package/dist/swap/types.d.ts.map +1 -1
- package/dist/swap/types.js +0 -2
- package/dist/swap/types.js.map +1 -1
- package/dist/tokens/__tests__/decimals.test.d.ts +2 -0
- package/dist/tokens/__tests__/decimals.test.d.ts.map +1 -0
- package/dist/tokens/__tests__/decimals.test.js +107 -0
- package/dist/tokens/__tests__/decimals.test.js.map +1 -0
- package/dist/tokens/__tests__/registry.test.d.ts +2 -0
- package/dist/tokens/__tests__/registry.test.d.ts.map +1 -0
- package/dist/tokens/__tests__/registry.test.js +191 -0
- package/dist/tokens/__tests__/registry.test.js.map +1 -0
- package/dist/tokens/__tests__/transfers.test.d.ts +2 -0
- package/dist/tokens/__tests__/transfers.test.d.ts.map +1 -0
- package/dist/tokens/__tests__/transfers.test.js +103 -0
- package/dist/tokens/__tests__/transfers.test.js.map +1 -0
- package/dist/tokens/decimals.d.ts +65 -0
- package/dist/tokens/decimals.d.ts.map +1 -0
- package/dist/tokens/decimals.js +112 -0
- package/dist/tokens/decimals.js.map +1 -0
- package/dist/tokens/index.d.ts +14 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +14 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/registry.d.ts +82 -0
- package/dist/tokens/registry.d.ts.map +1 -0
- package/dist/tokens/registry.js +293 -0
- package/dist/tokens/registry.js.map +1 -0
- package/dist/tokens/solana.d.ts +108 -0
- package/dist/tokens/solana.d.ts.map +1 -0
- package/dist/tokens/solana.js +306 -0
- package/dist/tokens/solana.js.map +1 -0
- package/dist/tokens/transfers.d.ts +95 -0
- package/dist/tokens/transfers.d.ts.map +1 -0
- package/dist/tokens/transfers.js +196 -0
- package/dist/tokens/transfers.js.map +1 -0
- package/dist/x402/chains/abstract/index.d.ts.map +1 -1
- package/dist/x402/chains/abstract/index.js.map +1 -1
- package/dist/x402/chains/stellar/index.d.ts.map +1 -1
- package/dist/x402/chains/stellar/index.js +2 -0
- package/dist/x402/chains/stellar/index.js.map +1 -1
- package/dist/x402/client.d.ts +7 -1
- package/dist/x402/client.d.ts.map +1 -1
- package/dist/x402/client.js +25 -25
- package/dist/x402/client.js.map +1 -1
- package/dist/x402/index.d.ts +1 -0
- package/dist/x402/index.d.ts.map +1 -1
- package/dist/x402/index.js +2 -0
- package/dist/x402/index.js.map +1 -1
- package/dist/x402/middleware.d.ts.map +1 -1
- package/dist/x402/middleware.js +0 -3
- package/dist/x402/middleware.js.map +1 -1
- package/dist/x402/multi-asset.d.ts +54 -0
- package/dist/x402/multi-asset.d.ts.map +1 -0
- package/dist/x402/multi-asset.js +123 -0
- package/dist/x402/multi-asset.js.map +1 -0
- package/package.json +13 -5
- package/dist/plugins/elizaos.d.ts +0 -52
- package/dist/plugins/elizaos.d.ts.map +0 -1
- package/dist/plugins/elizaos.js +0 -89
- package/dist/plugins/elizaos.js.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for token decimal normalization utilities.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { toRaw, toHuman, formatBalance, parseAmount } from '../decimals.js';
|
|
6
|
+
describe('toRaw', () => {
|
|
7
|
+
it('converts "1.5" with 6 decimals to 1500000n (USDC)', () => {
|
|
8
|
+
expect(toRaw('1.5', 6)).toBe(1500000n);
|
|
9
|
+
});
|
|
10
|
+
it('converts "1.0" with 18 decimals to 1000000000000000000n (WETH)', () => {
|
|
11
|
+
expect(toRaw('1.0', 18)).toBe(1000000000000000000n);
|
|
12
|
+
});
|
|
13
|
+
it('converts "0.001" with 8 decimals to 100000n (WBTC)', () => {
|
|
14
|
+
expect(toRaw('0.001', 8)).toBe(100000n);
|
|
15
|
+
});
|
|
16
|
+
it('converts integer "100" with 6 decimals correctly', () => {
|
|
17
|
+
expect(toRaw('100', 6)).toBe(100000000n);
|
|
18
|
+
});
|
|
19
|
+
it('converts "0" to 0n', () => {
|
|
20
|
+
expect(toRaw('0', 6)).toBe(0n);
|
|
21
|
+
});
|
|
22
|
+
it('handles string with more fractional digits than decimals (truncates)', () => {
|
|
23
|
+
// 1.9999999 with 6 decimals should truncate to 1.999999 → 1999999n
|
|
24
|
+
expect(toRaw('1.9999999', 6)).toBe(1999999n);
|
|
25
|
+
});
|
|
26
|
+
it('handles fractional-only strings', () => {
|
|
27
|
+
expect(toRaw('0.5', 6)).toBe(500000n);
|
|
28
|
+
});
|
|
29
|
+
it('handles bigint passthrough', () => {
|
|
30
|
+
expect(toRaw(12345n, 6)).toBe(12345n);
|
|
31
|
+
});
|
|
32
|
+
it('handles zero-padding short fractions', () => {
|
|
33
|
+
// "1.5" with 18 decimals → 1500000000000000000n
|
|
34
|
+
expect(toRaw('1.5', 18)).toBe(1500000000000000000n);
|
|
35
|
+
});
|
|
36
|
+
it('throws on invalid amount string', () => {
|
|
37
|
+
expect(() => toRaw('abc', 6)).toThrow();
|
|
38
|
+
expect(() => toRaw('1.2.3', 6)).toThrow();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('toHuman', () => {
|
|
42
|
+
it('converts 1500000n with 6 decimals to "1.5"', () => {
|
|
43
|
+
expect(toHuman(1500000n, 6)).toBe('1.5');
|
|
44
|
+
});
|
|
45
|
+
it('converts 1000000000000000000n with 18 decimals to "1.0"', () => {
|
|
46
|
+
expect(toHuman(1000000000000000000n, 18)).toBe('1.0');
|
|
47
|
+
});
|
|
48
|
+
it('converts 0n to "0.0"', () => {
|
|
49
|
+
expect(toHuman(0n, 6)).toBe('0.0');
|
|
50
|
+
expect(toHuman(0n, 18)).toBe('0.0');
|
|
51
|
+
});
|
|
52
|
+
it('converts 100000000n with 6 decimals to "100.0"', () => {
|
|
53
|
+
expect(toHuman(100000000n, 6)).toBe('100.0');
|
|
54
|
+
});
|
|
55
|
+
it('trims trailing zeros but keeps at least one decimal', () => {
|
|
56
|
+
expect(toHuman(1500000n, 6)).toBe('1.5');
|
|
57
|
+
expect(toHuman(1000000n, 6)).toBe('1.0');
|
|
58
|
+
});
|
|
59
|
+
it('handles 0 decimals', () => {
|
|
60
|
+
expect(toHuman(12345n, 0)).toBe('12345');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('formatBalance', () => {
|
|
64
|
+
it('formats USDC (6 decimals) with 2 decimal places', () => {
|
|
65
|
+
const token = { symbol: 'USDC', decimals: 6, address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' };
|
|
66
|
+
expect(formatBalance(1500000n, token)).toBe('1.50 USDC');
|
|
67
|
+
});
|
|
68
|
+
it('formats WETH (18 decimals) with 4 decimal places', () => {
|
|
69
|
+
const token = { symbol: 'WETH', decimals: 18, address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' };
|
|
70
|
+
expect(formatBalance(1000000000000000000n, token)).toBe('1.0000 WETH');
|
|
71
|
+
});
|
|
72
|
+
it('formats 0 balance correctly', () => {
|
|
73
|
+
const token = { symbol: 'USDC', decimals: 6, address: '0x0000000000000000000000000000000000000000' };
|
|
74
|
+
expect(formatBalance(0n, token)).toBe('0.00 USDC');
|
|
75
|
+
});
|
|
76
|
+
it('accepts custom displayDecimals', () => {
|
|
77
|
+
const token = { symbol: 'WETH', decimals: 18, address: '0x0000000000000000000000000000000000000000' };
|
|
78
|
+
expect(formatBalance(1000000000000000000n, token, 2)).toBe('1.00 WETH');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('parseAmount', () => {
|
|
82
|
+
it('parses string to raw bigint', () => {
|
|
83
|
+
expect(parseAmount('1.5', 6)).toBe(1500000n);
|
|
84
|
+
});
|
|
85
|
+
it('passes through bigint unchanged', () => {
|
|
86
|
+
expect(parseAmount(1500000n, 6)).toBe(1500000n);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('round-trip consistency', () => {
|
|
90
|
+
it('toRaw(toHuman(x)) === x for USDC amounts', () => {
|
|
91
|
+
const cases = [0n, 1n, 1000000n, 1500000n, 100000000n, 999999n];
|
|
92
|
+
for (const raw of cases) {
|
|
93
|
+
const human = toHuman(raw, 6);
|
|
94
|
+
const backToRaw = toRaw(human, 6);
|
|
95
|
+
expect(backToRaw).toBe(raw);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
it('toRaw(toHuman(x)) === x for ETH amounts (selected)', () => {
|
|
99
|
+
const cases = [0n, 1000000000000000000n, 500000000000000000n];
|
|
100
|
+
for (const raw of cases) {
|
|
101
|
+
const human = toHuman(raw, 18);
|
|
102
|
+
const backToRaw = toRaw(human, 18);
|
|
103
|
+
expect(backToRaw).toBe(raw);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=decimals.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimals.test.js","sourceRoot":"","sources":["../../../src/tokens/__tests__/decimals.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../../src/tokens/__tests__/registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the TokenRegistry — pre-populated multi-chain token registry.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { TokenRegistry, getGlobalRegistry, BASE_REGISTRY, ETHEREUM_REGISTRY } from '../registry.js';
|
|
6
|
+
import { zeroAddress } from 'viem';
|
|
7
|
+
// Chain IDs
|
|
8
|
+
const ETH = 1;
|
|
9
|
+
const BASE = 8453;
|
|
10
|
+
const ARB = 42161;
|
|
11
|
+
const OP = 10;
|
|
12
|
+
const POLY = 137;
|
|
13
|
+
const AVAX = 43114;
|
|
14
|
+
const SONIC = 146;
|
|
15
|
+
describe('TokenRegistry — construction', () => {
|
|
16
|
+
it('creates a registry and has tokens pre-populated', () => {
|
|
17
|
+
const r = new TokenRegistry();
|
|
18
|
+
expect(r.size()).toBeGreaterThan(0);
|
|
19
|
+
});
|
|
20
|
+
it('populates tokens for Ethereum mainnet', () => {
|
|
21
|
+
const r = new TokenRegistry();
|
|
22
|
+
const tokens = r.listTokens(ETH);
|
|
23
|
+
expect(tokens.length).toBeGreaterThanOrEqual(10);
|
|
24
|
+
const symbols = tokens.map(t => t.symbol);
|
|
25
|
+
expect(symbols).toContain('USDC');
|
|
26
|
+
expect(symbols).toContain('WETH');
|
|
27
|
+
expect(symbols).toContain('WBTC');
|
|
28
|
+
expect(symbols).toContain('LINK');
|
|
29
|
+
expect(symbols).toContain('UNI');
|
|
30
|
+
expect(symbols).toContain('AAVE');
|
|
31
|
+
expect(symbols).toContain('DAI');
|
|
32
|
+
expect(symbols).toContain('MKR');
|
|
33
|
+
expect(symbols).toContain('ETH'); // native
|
|
34
|
+
});
|
|
35
|
+
it('populates tokens for Base mainnet', () => {
|
|
36
|
+
const r = new TokenRegistry();
|
|
37
|
+
const tokens = r.listTokens(BASE);
|
|
38
|
+
const symbols = tokens.map(t => t.symbol);
|
|
39
|
+
expect(symbols).toContain('USDC');
|
|
40
|
+
expect(symbols).toContain('WETH');
|
|
41
|
+
expect(symbols).toContain('cbETH');
|
|
42
|
+
});
|
|
43
|
+
it('populates ARB on Arbitrum', () => {
|
|
44
|
+
const r = new TokenRegistry();
|
|
45
|
+
const token = r.getToken('ARB', ARB);
|
|
46
|
+
expect(token).toBeDefined();
|
|
47
|
+
expect(token.address.toLowerCase()).toBe('0x912ce59144191c1204e64559fe8253a0e49e6548');
|
|
48
|
+
});
|
|
49
|
+
it('populates OP on Optimism', () => {
|
|
50
|
+
const r = new TokenRegistry();
|
|
51
|
+
const token = r.getToken('OP', OP);
|
|
52
|
+
expect(token).toBeDefined();
|
|
53
|
+
expect(token.address.toLowerCase()).toBe('0x4200000000000000000000000000000000000042');
|
|
54
|
+
});
|
|
55
|
+
it('populates WMATIC on Polygon', () => {
|
|
56
|
+
const r = new TokenRegistry();
|
|
57
|
+
const token = r.getToken('WMATIC', POLY);
|
|
58
|
+
expect(token).toBeDefined();
|
|
59
|
+
expect(token.address.toLowerCase()).toBe('0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270');
|
|
60
|
+
});
|
|
61
|
+
it('populates WAVAX on Avalanche', () => {
|
|
62
|
+
const r = new TokenRegistry();
|
|
63
|
+
const token = r.getToken('WAVAX', AVAX);
|
|
64
|
+
expect(token).toBeDefined();
|
|
65
|
+
expect(token.address.toLowerCase()).toBe('0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7');
|
|
66
|
+
});
|
|
67
|
+
it('includes native gas tokens with isNative=true and zeroAddress', () => {
|
|
68
|
+
const r = new TokenRegistry();
|
|
69
|
+
const eth = r.getToken('ETH', BASE);
|
|
70
|
+
expect(eth).toBeDefined();
|
|
71
|
+
expect(eth.isNative).toBe(true);
|
|
72
|
+
expect(eth.address).toBe(zeroAddress);
|
|
73
|
+
const pol = r.getToken('POL', POLY);
|
|
74
|
+
expect(pol).toBeDefined();
|
|
75
|
+
expect(pol.isNative).toBe(true);
|
|
76
|
+
const avax = r.getToken('AVAX', AVAX);
|
|
77
|
+
expect(avax).toBeDefined();
|
|
78
|
+
expect(avax.isNative).toBe(true);
|
|
79
|
+
const s = r.getToken('S', SONIC);
|
|
80
|
+
expect(s).toBeDefined();
|
|
81
|
+
expect(s.isNative).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('TokenRegistry — getToken', () => {
|
|
85
|
+
it('returns undefined for unknown symbol', () => {
|
|
86
|
+
const r = new TokenRegistry();
|
|
87
|
+
expect(r.getToken('FAKECOIN', ETH)).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
it('is case-insensitive for symbol lookup', () => {
|
|
90
|
+
const r = new TokenRegistry();
|
|
91
|
+
expect(r.getToken('usdc', ETH)).toBeDefined();
|
|
92
|
+
expect(r.getToken('USDC', ETH)).toBeDefined();
|
|
93
|
+
expect(r.getToken('Usdc', ETH)).toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
it('USDC on Ethereum is correct address', () => {
|
|
96
|
+
const r = new TokenRegistry();
|
|
97
|
+
const usdc = r.getToken('USDC', ETH);
|
|
98
|
+
expect(usdc.address.toLowerCase()).toBe('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48');
|
|
99
|
+
expect(usdc.decimals).toBe(6);
|
|
100
|
+
});
|
|
101
|
+
it('USDC on Base is correct address', () => {
|
|
102
|
+
const r = new TokenRegistry();
|
|
103
|
+
const usdc = r.getToken('USDC', BASE);
|
|
104
|
+
expect(usdc.address.toLowerCase()).toBe('0x833589fcd6edb6e08f4c7c32d4f71b54bda02913');
|
|
105
|
+
});
|
|
106
|
+
it('WETH on Ethereum is correct address', () => {
|
|
107
|
+
const r = new TokenRegistry();
|
|
108
|
+
const weth = r.getToken('WETH', ETH);
|
|
109
|
+
expect(weth.address.toLowerCase()).toBe('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2');
|
|
110
|
+
expect(weth.decimals).toBe(18);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe('TokenRegistry — addToken (custom)', () => {
|
|
114
|
+
it('adds a custom token and retrieves it', () => {
|
|
115
|
+
const r = new TokenRegistry();
|
|
116
|
+
r.addToken({
|
|
117
|
+
symbol: 'MYTOKEN',
|
|
118
|
+
address: '0xDeadBeefDeadBeefDeadBeefDeadBeefDeadBeef',
|
|
119
|
+
decimals: 18,
|
|
120
|
+
chainId: BASE,
|
|
121
|
+
name: 'My Custom Token',
|
|
122
|
+
});
|
|
123
|
+
const t = r.getToken('MYTOKEN', BASE);
|
|
124
|
+
expect(t).toBeDefined();
|
|
125
|
+
expect(t.name).toBe('My Custom Token');
|
|
126
|
+
expect(t.decimals).toBe(18);
|
|
127
|
+
});
|
|
128
|
+
it('overwriting a token with addToken replaces it', () => {
|
|
129
|
+
const r = new TokenRegistry();
|
|
130
|
+
r.addToken({
|
|
131
|
+
symbol: 'USDC',
|
|
132
|
+
address: '0x1234567890123456789012345678901234567890',
|
|
133
|
+
decimals: 6,
|
|
134
|
+
chainId: BASE,
|
|
135
|
+
name: 'Test USDC',
|
|
136
|
+
});
|
|
137
|
+
const usdc = r.getToken('USDC', BASE);
|
|
138
|
+
expect(usdc.address.toLowerCase()).toBe('0x1234567890123456789012345678901234567890');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('TokenRegistry — listTokens', () => {
|
|
142
|
+
it('returns all tokens for a chain', () => {
|
|
143
|
+
const r = new TokenRegistry();
|
|
144
|
+
const tokens = r.listTokens(ARB);
|
|
145
|
+
expect(tokens.length).toBeGreaterThan(0);
|
|
146
|
+
// Every returned token should have chainId === ARB
|
|
147
|
+
for (const t of tokens) {
|
|
148
|
+
expect(t.chainId).toBe(ARB);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
it('returns empty array for unknown chainId', () => {
|
|
152
|
+
const r = new TokenRegistry();
|
|
153
|
+
const tokens = r.listTokens(99999);
|
|
154
|
+
expect(tokens).toEqual([]);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe('TokenRegistry — getTokenByAddress', () => {
|
|
158
|
+
it('finds a token by its address', () => {
|
|
159
|
+
const r = new TokenRegistry();
|
|
160
|
+
const usdc = r.getTokenByAddress('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', ETH);
|
|
161
|
+
expect(usdc).toBeDefined();
|
|
162
|
+
expect(usdc.symbol).toBe('USDC');
|
|
163
|
+
});
|
|
164
|
+
it('is case-insensitive for address lookup', () => {
|
|
165
|
+
const r = new TokenRegistry();
|
|
166
|
+
const usdc = r.getTokenByAddress('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // lower
|
|
167
|
+
ETH);
|
|
168
|
+
expect(usdc).toBeDefined();
|
|
169
|
+
});
|
|
170
|
+
it('returns undefined for unknown address', () => {
|
|
171
|
+
const r = new TokenRegistry();
|
|
172
|
+
const t = r.getTokenByAddress('0xDeadBeefDeadBeefDeadBeefDeadBeefDeadBeef', ETH);
|
|
173
|
+
expect(t).toBeUndefined();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('Pre-built registry exports', () => {
|
|
177
|
+
it('BASE_REGISTRY has Base tokens', () => {
|
|
178
|
+
const tokens = BASE_REGISTRY.listTokens(BASE);
|
|
179
|
+
expect(tokens.length).toBeGreaterThan(0);
|
|
180
|
+
});
|
|
181
|
+
it('ETHEREUM_REGISTRY has Ethereum tokens', () => {
|
|
182
|
+
const tokens = ETHEREUM_REGISTRY.listTokens(ETH);
|
|
183
|
+
expect(tokens.length).toBeGreaterThan(0);
|
|
184
|
+
});
|
|
185
|
+
it('getGlobalRegistry() returns consistent instance', () => {
|
|
186
|
+
const r1 = getGlobalRegistry();
|
|
187
|
+
const r2 = getGlobalRegistry();
|
|
188
|
+
expect(r1).toBe(r2);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
//# sourceMappingURL=registry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.test.js","sourceRoot":"","sources":["../../../src/tokens/__tests__/registry.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfers.test.d.ts","sourceRoot":"","sources":["../../../src/tokens/__tests__/transfers.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for ERC-20 and native transfer encoding.
|
|
3
|
+
* Uses mocked publicClient/walletClient to avoid real RPC calls.
|
|
4
|
+
*
|
|
5
|
+
* NOTE: viem enforces EIP-55 checksummed addresses. All addresses here
|
|
6
|
+
* are checksummed via `getAddress()` from viem.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
9
|
+
import { encodeERC20Transfer } from '../transfers.js';
|
|
10
|
+
import { toRaw } from '../decimals.js';
|
|
11
|
+
// Checksummed test addresses (verified via viem's getAddress)
|
|
12
|
+
// These are real EIP-55 addresses used only in tests
|
|
13
|
+
const TO = '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'; // BBBB... checksummed
|
|
14
|
+
const ACCOUNT = '0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa'; // AAAA... checksummed
|
|
15
|
+
const USDC_ETH = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
|
|
16
|
+
const FAKE_HASH = ('0x' + 'a'.repeat(64));
|
|
17
|
+
// ─── encodeERC20Transfer tests ────────────────────────────────────────────────
|
|
18
|
+
describe('encodeERC20Transfer', () => {
|
|
19
|
+
it('produces correct 4-byte selector for transfer()', () => {
|
|
20
|
+
const data = encodeERC20Transfer(TO, 1000000n);
|
|
21
|
+
// transfer(address,uint256) selector = 0xa9059cbb
|
|
22
|
+
expect(data.slice(0, 10).toLowerCase()).toBe('0xa9059cbb');
|
|
23
|
+
});
|
|
24
|
+
it('encodes the recipient address in the calldata', () => {
|
|
25
|
+
const data = encodeERC20Transfer(TO, 1000000n);
|
|
26
|
+
// Recipient is ABI-encoded as 32-byte padded address starting at byte 4
|
|
27
|
+
const lowerTo = TO.toLowerCase().slice(2); // strip 0x
|
|
28
|
+
expect(data.toLowerCase()).toContain(lowerTo);
|
|
29
|
+
});
|
|
30
|
+
it('encodes the amount correctly', () => {
|
|
31
|
+
const amount = 1500000n; // 1.5 USDC
|
|
32
|
+
const data = encodeERC20Transfer(TO, amount);
|
|
33
|
+
// Amount 1500000 = 0x16e360
|
|
34
|
+
expect(data.toLowerCase()).toContain('16e360');
|
|
35
|
+
});
|
|
36
|
+
it('encodes zero amount', () => {
|
|
37
|
+
const data = encodeERC20Transfer(TO, 0n);
|
|
38
|
+
expect(data).toBeDefined();
|
|
39
|
+
expect(data.startsWith('0xa9059cbb')).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it('encodes large amounts (18 decimals, 1 WETH)', () => {
|
|
42
|
+
const oneWeth = toRaw('1.0', 18);
|
|
43
|
+
const data = encodeERC20Transfer(TO, oneWeth);
|
|
44
|
+
expect(data.startsWith('0xa9059cbb')).toBe(true);
|
|
45
|
+
// 1e18 = 0xde0b6b3a7640000
|
|
46
|
+
expect(data.toLowerCase()).toContain('de0b6b3a7640000');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
// ─── Transfer function smoke tests (mocked clients) ──────────────────────────
|
|
50
|
+
describe('sendToken (mocked)', () => {
|
|
51
|
+
it('calls walletClient.sendTransaction with transfer calldata', async () => {
|
|
52
|
+
const { sendToken } = await import('../transfers.js');
|
|
53
|
+
const sendTransaction = vi.fn().mockResolvedValue(FAKE_HASH);
|
|
54
|
+
const readContract = vi.fn().mockResolvedValue(6); // decimals
|
|
55
|
+
const ctx = {
|
|
56
|
+
publicClient: { readContract },
|
|
57
|
+
walletClient: { sendTransaction },
|
|
58
|
+
account: ACCOUNT,
|
|
59
|
+
chainId: 1,
|
|
60
|
+
};
|
|
61
|
+
const hash = await sendToken(ctx, TO, '1.5', USDC_ETH);
|
|
62
|
+
expect(hash).toBe(FAKE_HASH);
|
|
63
|
+
expect(sendTransaction).toHaveBeenCalledOnce();
|
|
64
|
+
const callArgs = sendTransaction.mock.calls[0][0];
|
|
65
|
+
// Should send to the token contract address
|
|
66
|
+
expect(callArgs.to).toBe(USDC_ETH);
|
|
67
|
+
// Data should start with transfer() selector
|
|
68
|
+
expect(callArgs.data.toLowerCase().startsWith('0xa9059cbb')).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('sendNative (mocked)', () => {
|
|
72
|
+
it('calls walletClient.sendTransaction with value and no data', async () => {
|
|
73
|
+
const { sendNative } = await import('../transfers.js');
|
|
74
|
+
const sendTransaction = vi.fn().mockResolvedValue(('0x' + 'b'.repeat(64)));
|
|
75
|
+
const ctx = {
|
|
76
|
+
publicClient: {},
|
|
77
|
+
walletClient: { sendTransaction },
|
|
78
|
+
account: ACCOUNT,
|
|
79
|
+
};
|
|
80
|
+
const _hash = await sendNative(ctx, TO, '0.5'); // 0.5 ETH
|
|
81
|
+
expect(sendTransaction).toHaveBeenCalledOnce();
|
|
82
|
+
const callArgs = sendTransaction.mock.calls[0][0];
|
|
83
|
+
expect(callArgs.to).toBe(TO);
|
|
84
|
+
expect(callArgs.value).toBe(500000000000000000n); // 0.5 * 10^18
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('getNativeBalance (mocked)', () => {
|
|
88
|
+
it('returns correct balance info', async () => {
|
|
89
|
+
const { getNativeBalance } = await import('../transfers.js');
|
|
90
|
+
const getBalance = vi.fn().mockResolvedValue(1000000000000000000n); // 1 ETH
|
|
91
|
+
const ctx = {
|
|
92
|
+
publicClient: { getBalance },
|
|
93
|
+
walletClient: {},
|
|
94
|
+
account: ACCOUNT,
|
|
95
|
+
chainId: 8453,
|
|
96
|
+
};
|
|
97
|
+
const result = await getNativeBalance(ctx);
|
|
98
|
+
expect(result.rawBalance).toBe(1000000000000000000n);
|
|
99
|
+
expect(result.humanBalance).toBe('1.0');
|
|
100
|
+
expect(result.decimals).toBe(18);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=transfers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfers.test.js","sourceRoot":"","sources":["../../../src/tokens/__tests__/transfers.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,8DAA8D;AAC9D,qDAAqD;AACrD,MAAM,EAAE,GAAiB,4CAA4C,CAAC,CAAC,sBAAsB;AAC7F,MAAM,OAAO,GAAY,4CAA4C,CAAC,CAAC,sBAAsB;AAC7F,MAAM,QAAQ,GAAY,4CAA4C,CAAC;AACvE,MAAM,SAAS,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAkB,CAAC;AAE3D,iFAAiF;AAEjF,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,EAAE,QAAU,CAAC,CAAC;QACjD,kDAAkD;QAClD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,EAAE,QAAU,CAAC,CAAC;QACjD,wEAAwE;QACxE,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW;QACtD,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,QAAU,CAAC,CAAC,WAAW;QACtC,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC7C,4BAA4B;QAC5B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,mBAAmB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,2BAA2B;QAC3B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,gFAAgF;AAEhF,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAEtD,MAAM,eAAe,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW;QAE9D,MAAM,GAAG,GAAG;YACV,YAAY,EAAE,EAAE,YAAY,EAAS;YACrC,YAAY,EAAE,EAAE,eAAe,EAAS;YACxC,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE,CAAC;SACX,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEvD,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAE/C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,4CAA4C;QAC5C,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,6CAA6C;QAC7C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAEvD,MAAM,eAAe,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAkB,CAAC,CAAC;QAE5F,MAAM,GAAG,GAAG;YACV,YAAY,EAAE,EAAS;YACvB,YAAY,EAAE,EAAE,eAAe,EAAS;YACxC,OAAO,EAAE,OAAO;SACjB,CAAC;QAEF,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU;QAE1D,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAE/C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAwB,CAAC,CAAC,CAAC,cAAc;IACvE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAE7D,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,oBAA0B,CAAC,CAAC,CAAC,QAAQ;QAElF,MAAM,GAAG,GAAG;YACV,YAAY,EAAE,EAAE,UAAU,EAAS;YACnC,YAAY,EAAE,EAAS;YACvB,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE,IAAI;SACd,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,oBAA0B,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module tokens/decimals
|
|
3
|
+
* Token decimal normalization utilities for multi-token agent wallets.
|
|
4
|
+
*
|
|
5
|
+
* Handles safe conversion between human-readable amounts ("1.5") and raw
|
|
6
|
+
* on-chain bigint amounts (1500000n for USDC with 6 decimals). All arithmetic
|
|
7
|
+
* is done in integer domain to avoid floating point precision errors.
|
|
8
|
+
*/
|
|
9
|
+
import type { Address } from 'viem';
|
|
10
|
+
/** Minimal token info required for formatting */
|
|
11
|
+
export interface TokenInfo {
|
|
12
|
+
symbol: string;
|
|
13
|
+
decimals: number;
|
|
14
|
+
address: Address;
|
|
15
|
+
name?: string;
|
|
16
|
+
chainId?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Convert a human-readable amount string to raw bigint (on-chain units).
|
|
20
|
+
*
|
|
21
|
+
* @param amount - Human-readable amount, e.g. "1.5" or "1000"
|
|
22
|
+
* @param decimals - Token decimal places (e.g. 6 for USDC, 18 for WETH)
|
|
23
|
+
* @returns Raw on-chain amount as bigint
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* toRaw("1.5", 6) // → 1500000n (1.5 USDC)
|
|
27
|
+
* toRaw("1.0", 18) // → 1000000000000000000n (1 WETH)
|
|
28
|
+
* toRaw("0.001", 8) // → 100000n (0.001 WBTC)
|
|
29
|
+
*/
|
|
30
|
+
export declare function toRaw(amount: string | bigint, decimals: number): bigint;
|
|
31
|
+
/**
|
|
32
|
+
* Convert a raw bigint on-chain amount to a human-readable string.
|
|
33
|
+
*
|
|
34
|
+
* @param amount - Raw on-chain amount
|
|
35
|
+
* @param decimals - Token decimal places
|
|
36
|
+
* @returns Human-readable string, trimmed trailing zeros
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* toHuman(1500000n, 6) // → "1.5"
|
|
40
|
+
* toHuman(1000000000000000000n, 18) // → "1.0"
|
|
41
|
+
* toHuman(0n, 6) // → "0.0"
|
|
42
|
+
*/
|
|
43
|
+
export declare function toHuman(amount: bigint, decimals: number): string;
|
|
44
|
+
/**
|
|
45
|
+
* Format a raw bigint amount with token symbol for display.
|
|
46
|
+
*
|
|
47
|
+
* @param amount - Raw on-chain amount
|
|
48
|
+
* @param token - Token info (symbol + decimals required)
|
|
49
|
+
* @param displayDecimals - Max decimal places to show (default: 4 for high-precision, 2 for stablecoins)
|
|
50
|
+
* @returns Formatted string e.g. "1.50 USDC" or "0.0023 WETH"
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* formatBalance(1500000n, { symbol: 'USDC', decimals: 6, address: '0x...' })
|
|
54
|
+
* // → "1.50 USDC"
|
|
55
|
+
*/
|
|
56
|
+
export declare function formatBalance(amount: bigint, token: Pick<TokenInfo, 'symbol' | 'decimals'>, displayDecimals?: number): string;
|
|
57
|
+
/**
|
|
58
|
+
* Parse amount that may be either a string (human-readable) or bigint (raw).
|
|
59
|
+
* Returns raw bigint. Used in transfer functions to accept flexible input.
|
|
60
|
+
*
|
|
61
|
+
* @param amount - Either a human-readable string "1.5" or a raw bigint
|
|
62
|
+
* @param decimals - Required only when amount is a string
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseAmount(amount: string | bigint, decimals: number): bigint;
|
|
65
|
+
//# sourceMappingURL=decimals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimals.d.ts","sourceRoot":"","sources":["../../src/tokens/decimals.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoCvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkBhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,UAAU,CAAC,EAC7C,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,CAUR;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG7E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module tokens/decimals
|
|
3
|
+
* Token decimal normalization utilities for multi-token agent wallets.
|
|
4
|
+
*
|
|
5
|
+
* Handles safe conversion between human-readable amounts ("1.5") and raw
|
|
6
|
+
* on-chain bigint amounts (1500000n for USDC with 6 decimals). All arithmetic
|
|
7
|
+
* is done in integer domain to avoid floating point precision errors.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Convert a human-readable amount string to raw bigint (on-chain units).
|
|
11
|
+
*
|
|
12
|
+
* @param amount - Human-readable amount, e.g. "1.5" or "1000"
|
|
13
|
+
* @param decimals - Token decimal places (e.g. 6 for USDC, 18 for WETH)
|
|
14
|
+
* @returns Raw on-chain amount as bigint
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* toRaw("1.5", 6) // → 1500000n (1.5 USDC)
|
|
18
|
+
* toRaw("1.0", 18) // → 1000000000000000000n (1 WETH)
|
|
19
|
+
* toRaw("0.001", 8) // → 100000n (0.001 WBTC)
|
|
20
|
+
*/
|
|
21
|
+
export function toRaw(amount, decimals) {
|
|
22
|
+
if (typeof amount === 'bigint')
|
|
23
|
+
return amount;
|
|
24
|
+
const str = amount.trim();
|
|
25
|
+
if (!str || str === '0')
|
|
26
|
+
return 0n;
|
|
27
|
+
// Validate: only digits and one optional decimal point, optional leading minus
|
|
28
|
+
if (!/^-?\d+(\.\d+)?$/.test(str)) {
|
|
29
|
+
throw new Error(`toRaw: invalid amount string "${amount}"`);
|
|
30
|
+
}
|
|
31
|
+
const negative = str.startsWith('-');
|
|
32
|
+
const abs = negative ? str.slice(1) : str;
|
|
33
|
+
const dotIndex = abs.indexOf('.');
|
|
34
|
+
if (dotIndex === -1) {
|
|
35
|
+
// Integer amount
|
|
36
|
+
const result = BigInt(abs) * (10n ** BigInt(decimals));
|
|
37
|
+
return negative ? -result : result;
|
|
38
|
+
}
|
|
39
|
+
const intPart = abs.slice(0, dotIndex);
|
|
40
|
+
let fracPart = abs.slice(dotIndex + 1);
|
|
41
|
+
// Truncate or pad fractional part to `decimals` digits
|
|
42
|
+
if (fracPart.length > decimals) {
|
|
43
|
+
fracPart = fracPart.slice(0, decimals); // truncate (floor for positive amounts)
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
fracPart = fracPart.padEnd(decimals, '0');
|
|
47
|
+
}
|
|
48
|
+
const raw = BigInt(intPart || '0') * (10n ** BigInt(decimals)) +
|
|
49
|
+
BigInt(fracPart);
|
|
50
|
+
return negative ? -raw : raw;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Convert a raw bigint on-chain amount to a human-readable string.
|
|
54
|
+
*
|
|
55
|
+
* @param amount - Raw on-chain amount
|
|
56
|
+
* @param decimals - Token decimal places
|
|
57
|
+
* @returns Human-readable string, trimmed trailing zeros
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* toHuman(1500000n, 6) // → "1.5"
|
|
61
|
+
* toHuman(1000000000000000000n, 18) // → "1.0"
|
|
62
|
+
* toHuman(0n, 6) // → "0.0"
|
|
63
|
+
*/
|
|
64
|
+
export function toHuman(amount, decimals) {
|
|
65
|
+
if (decimals === 0)
|
|
66
|
+
return amount.toString();
|
|
67
|
+
const negative = amount < 0n;
|
|
68
|
+
const abs = negative ? -amount : amount;
|
|
69
|
+
const divisor = 10n ** BigInt(decimals);
|
|
70
|
+
const intPart = abs / divisor;
|
|
71
|
+
const fracRaw = abs % divisor;
|
|
72
|
+
// Pad fractional part to `decimals` digits
|
|
73
|
+
const fracStr = fracRaw.toString().padStart(decimals, '0');
|
|
74
|
+
// Trim trailing zeros but keep at least one decimal digit
|
|
75
|
+
const trimmed = fracStr.replace(/0+$/, '') || '0';
|
|
76
|
+
const result = `${intPart}.${trimmed}`;
|
|
77
|
+
return negative ? `-${result}` : result;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Format a raw bigint amount with token symbol for display.
|
|
81
|
+
*
|
|
82
|
+
* @param amount - Raw on-chain amount
|
|
83
|
+
* @param token - Token info (symbol + decimals required)
|
|
84
|
+
* @param displayDecimals - Max decimal places to show (default: 4 for high-precision, 2 for stablecoins)
|
|
85
|
+
* @returns Formatted string e.g. "1.50 USDC" or "0.0023 WETH"
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* formatBalance(1500000n, { symbol: 'USDC', decimals: 6, address: '0x...' })
|
|
89
|
+
* // → "1.50 USDC"
|
|
90
|
+
*/
|
|
91
|
+
export function formatBalance(amount, token, displayDecimals) {
|
|
92
|
+
const human = toHuman(amount, token.decimals);
|
|
93
|
+
const maxDisplay = displayDecimals ?? (token.decimals <= 6 ? 2 : 4);
|
|
94
|
+
// Parse the human string and reformat to maxDisplay decimal places
|
|
95
|
+
const [intPart, fracPart = ''] = human.split('.');
|
|
96
|
+
const padded = fracPart.padEnd(maxDisplay, '0').slice(0, maxDisplay);
|
|
97
|
+
// If all fraction digits are zero, still show them for consistent formatting
|
|
98
|
+
return `${intPart}.${padded} ${token.symbol}`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parse amount that may be either a string (human-readable) or bigint (raw).
|
|
102
|
+
* Returns raw bigint. Used in transfer functions to accept flexible input.
|
|
103
|
+
*
|
|
104
|
+
* @param amount - Either a human-readable string "1.5" or a raw bigint
|
|
105
|
+
* @param decimals - Required only when amount is a string
|
|
106
|
+
*/
|
|
107
|
+
export function parseAmount(amount, decimals) {
|
|
108
|
+
if (typeof amount === 'bigint')
|
|
109
|
+
return amount;
|
|
110
|
+
return toRaw(amount, decimals);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=decimals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decimals.js","sourceRoot":"","sources":["../../src/tokens/decimals.ts"],"names":[],"mappings":"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"}
|