@provex/utils 1.0.16 → 1.2.4
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/chain.d.ts +446 -0
- package/dist/chain.js +98 -0
- package/dist/chain.test.js +112 -0
- package/dist/contracts.d.ts +206 -0
- package/dist/contracts.js +292 -0
- package/dist/contracts.test.js +243 -0
- package/dist/conversionRates.d.ts +215 -0
- package/dist/{src/conversionRates.js → conversionRates.js} +74 -4
- package/dist/conversionRates.test.js +473 -0
- package/dist/currencies.d.ts +248 -0
- package/dist/{src/currencies.js → currencies.js} +119 -38
- package/dist/currencies.test.js +343 -0
- package/dist/data/countries.json +1099 -0
- package/dist/deposit.d.ts +69 -0
- package/dist/deposit.js +52 -0
- package/dist/depositKeys.d.ts +154 -0
- package/dist/depositKeys.js +104 -0
- package/dist/depositKeys.test.d.ts +1 -0
- package/dist/depositKeys.test.js +231 -0
- package/dist/events.d.ts +41 -0
- package/dist/events.js +92 -0
- package/dist/events.test.d.ts +1 -0
- package/dist/events.test.js +111 -0
- package/dist/fees.d.ts +136 -0
- package/dist/fees.js +178 -0
- package/dist/fees.test.d.ts +1 -0
- package/dist/fees.test.js +165 -0
- package/dist/ids.d.ts +175 -0
- package/dist/ids.js +231 -0
- package/dist/ids.test.d.ts +1 -0
- package/dist/ids.test.js +607 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +45 -0
- package/dist/input.d.ts +26 -0
- package/dist/{src/input.js → input.js} +23 -4
- package/dist/intent.d.ts +50 -0
- package/dist/intent.js +28 -0
- package/dist/intent.test.d.ts +1 -0
- package/dist/intent.test.js +119 -0
- package/dist/json.d.ts +55 -0
- package/dist/json.js +80 -0
- package/dist/participants.d.ts +22 -0
- package/dist/participants.js +28 -0
- package/dist/payment.d.ts +481 -0
- package/dist/payment.js +1149 -0
- package/dist/payment.test.d.ts +1 -0
- package/dist/payment.test.js +272 -0
- package/dist/peer-types.d.ts +327 -0
- package/dist/peer-types.js +169 -0
- package/dist/profit.d.ts +49 -0
- package/dist/profit.js +57 -0
- package/dist/profit.test.d.ts +1 -0
- package/dist/profit.test.js +315 -0
- package/dist/reputation.d.ts +125 -0
- package/dist/reputation.js +188 -0
- package/dist/reputation.test.d.ts +1 -0
- package/dist/reputation.test.js +156 -0
- package/dist/sort.d.ts +75 -0
- package/dist/sort.js +70 -0
- package/dist/sort.test.d.ts +1 -0
- package/dist/sort.test.js +216 -0
- package/dist/stateKey.d.ts +35 -0
- package/dist/stateKey.js +36 -0
- package/dist/stats.d.ts +61 -0
- package/dist/stats.js +53 -0
- package/dist/stats.test.d.ts +1 -0
- package/dist/stats.test.js +104 -0
- package/dist/time.d.ts +104 -0
- package/dist/time.js +162 -0
- package/dist/time.test.d.ts +1 -0
- package/dist/time.test.js +231 -0
- package/dist/tokens.d.ts +15502 -0
- package/dist/{src/tokens.js → tokens.js} +98 -17
- package/dist/tokens.test.d.ts +1 -0
- package/dist/tokens.test.js +193 -0
- package/dist/units.d.ts +200 -0
- package/dist/units.js +279 -0
- package/dist/units.test.d.ts +1 -0
- package/dist/units.test.js +327 -0
- package/package.json +119 -29
- package/dist/scripts/convert-svg.js +0 -17
- package/dist/src/chain.d.ts +0 -14
- package/dist/src/chain.js +0 -18
- package/dist/src/contracts.d.ts +0 -30
- package/dist/src/contracts.js +0 -64
- package/dist/src/conversionRates.d.ts +0 -124
- package/dist/src/currencies.d.ts +0 -144
- package/dist/src/data/countries.json +0 -1099
- package/dist/src/deposit.d.ts +0 -1
- package/dist/src/events.d.ts +0 -3
- package/dist/src/events.js +0 -16
- package/dist/src/ids.d.ts +0 -72
- package/dist/src/ids.js +0 -81
- package/dist/src/index.d.ts +0 -16
- package/dist/src/index.js +0 -16
- package/dist/src/input.d.ts +0 -7
- package/dist/src/intent.d.ts +0 -14
- package/dist/src/json.d.ts +0 -18
- package/dist/src/json.js +0 -44
- package/dist/src/participants.d.ts +0 -7
- package/dist/src/participants.js +0 -13
- package/dist/src/payment.d.ts +0 -164
- package/dist/src/payment.js +0 -439
- package/dist/src/profit.d.ts +0 -28
- package/dist/src/profit.js +0 -34
- package/dist/src/sort.d.ts +0 -36
- package/dist/src/sort.js +0 -39
- package/dist/src/stats.d.ts +0 -7
- package/dist/src/stats.js +0 -8
- package/dist/src/time.d.ts +0 -54
- package/dist/src/time.js +0 -106
- package/dist/src/tokens.d.ts +0 -3675
- package/dist/src/units.d.ts +0 -17
- package/dist/src/units.js +0 -79
- package/dist/src/zkp2p-types.d.ts +0 -48
- package/dist/tsconfig.tsbuildinfo +0 -1
- 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/{scripts/convert-svg.d.ts → chain.test.d.ts} +0 -0
- /package/dist/{src/deposit.js → contracts.test.d.ts} +0 -0
- /package/dist/{src/intent.js → conversionRates.test.d.ts} +0 -0
- /package/dist/{src/zkp2p-types.js → currencies.test.d.ts} +0 -0
- /package/dist/{src/flags.d.ts → flags.d.ts} +0 -0
- /package/dist/{src/flags.js → flags.js} +0 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { base, pulsechain } from 'viem/chains';
|
|
4
|
+
import { getContracts, getLatestContract, getAllEscrowContracts, shortenEscrowAddress, getEscrowVersion, isV3Escrow, v2BaseContracts, v3BaseContracts, v2PulsechainContracts, v3PulsechainContracts, V3_PULSECHAIN_DEPLOYMENT_REFERENCE, contracts, } from './contracts.js';
|
|
5
|
+
describe('contracts', () => {
|
|
6
|
+
describe('getDefaultVersion', () => {
|
|
7
|
+
it('returns v3 for Base', async () => {
|
|
8
|
+
// getDefaultVersion is not exported, but we can test via getContracts behavior
|
|
9
|
+
// When no version is specified to getLatestContract, it uses the default version
|
|
10
|
+
const escrow = getLatestContract(base.id, 'escrow');
|
|
11
|
+
assert.strictEqual(escrow, v3BaseContracts.escrow.at(-1));
|
|
12
|
+
});
|
|
13
|
+
it('returns v3 for Pulsechain', async () => {
|
|
14
|
+
// Pulsechain now uses v3 as default (deployed 2026-01-12)
|
|
15
|
+
const escrow = getLatestContract(pulsechain.id, 'escrow');
|
|
16
|
+
assert.strictEqual(escrow, v3PulsechainContracts.escrow.at(-1));
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('getContracts', () => {
|
|
20
|
+
it('returns v2 Base contracts', () => {
|
|
21
|
+
const result = getContracts('v2', base.id);
|
|
22
|
+
assert.deepStrictEqual(result, v2BaseContracts);
|
|
23
|
+
});
|
|
24
|
+
it('returns v3 Base contracts', () => {
|
|
25
|
+
const result = getContracts('v3', base.id);
|
|
26
|
+
assert.deepStrictEqual(result, v3BaseContracts);
|
|
27
|
+
});
|
|
28
|
+
it('returns v2 Pulsechain contracts', () => {
|
|
29
|
+
const result = getContracts('v2', pulsechain.id);
|
|
30
|
+
assert.deepStrictEqual(result, v2PulsechainContracts);
|
|
31
|
+
});
|
|
32
|
+
it('returns v3 Pulsechain contracts', () => {
|
|
33
|
+
const result = getContracts('v3', pulsechain.id);
|
|
34
|
+
assert.deepStrictEqual(result, v3PulsechainContracts);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('getLatestContract', () => {
|
|
38
|
+
it('returns last escrow in v3 Base array', () => {
|
|
39
|
+
const escrow = getLatestContract(base.id, 'escrow', 'v3');
|
|
40
|
+
assert.strictEqual(escrow, v3BaseContracts.escrow.at(-1));
|
|
41
|
+
});
|
|
42
|
+
it('returns last escrow in v2 Base array', () => {
|
|
43
|
+
const escrow = getLatestContract(base.id, 'escrow', 'v2');
|
|
44
|
+
assert.strictEqual(escrow, v2BaseContracts.escrow.at(-1));
|
|
45
|
+
});
|
|
46
|
+
it('returns last escrow in v3 Pulsechain array', () => {
|
|
47
|
+
const escrow = getLatestContract(pulsechain.id, 'escrow', 'v3');
|
|
48
|
+
assert.strictEqual(escrow, v3PulsechainContracts.escrow.at(-1));
|
|
49
|
+
});
|
|
50
|
+
it('returns last escrow in v2 Pulsechain array', () => {
|
|
51
|
+
const escrow = getLatestContract(pulsechain.id, 'escrow', 'v2');
|
|
52
|
+
assert.strictEqual(escrow, v2PulsechainContracts.escrow.at(-1));
|
|
53
|
+
});
|
|
54
|
+
it('returns usdc address (non-array)', () => {
|
|
55
|
+
const usdc = getLatestContract(base.id, 'usdc', 'v3');
|
|
56
|
+
assert.strictEqual(usdc, v3BaseContracts.usdc);
|
|
57
|
+
});
|
|
58
|
+
it('returns gatingService address (non-array)', () => {
|
|
59
|
+
const gating = getLatestContract(base.id, 'gatingService', 'v3');
|
|
60
|
+
assert.strictEqual(gating, v3BaseContracts.gatingService);
|
|
61
|
+
});
|
|
62
|
+
it('returns unifiedPaymentVerifier for v3', () => {
|
|
63
|
+
const verifier = getLatestContract(base.id, 'unifiedPaymentVerifier', 'v3');
|
|
64
|
+
assert.strictEqual(verifier, v3BaseContracts.unifiedPaymentVerifier.at(-1));
|
|
65
|
+
});
|
|
66
|
+
it('uses default version when not specified', () => {
|
|
67
|
+
// Both Base and Pulsechain default to v3
|
|
68
|
+
const baseEscrow = getLatestContract(base.id, 'escrow');
|
|
69
|
+
assert.strictEqual(baseEscrow, v3BaseContracts.escrow.at(-1));
|
|
70
|
+
const pulseEscrow = getLatestContract(pulsechain.id, 'escrow');
|
|
71
|
+
assert.strictEqual(pulseEscrow, v3PulsechainContracts.escrow.at(-1));
|
|
72
|
+
});
|
|
73
|
+
it('returns v2 verifiers when explicitly requesting v2', () => {
|
|
74
|
+
const venmoVerifier = getLatestContract(base.id, 'venmoReclaimVerifier', 'v2');
|
|
75
|
+
assert.strictEqual(venmoVerifier, v2BaseContracts.venmoReclaimVerifier.at(-1));
|
|
76
|
+
});
|
|
77
|
+
it('returns null for v2-only key when requesting v3', () => {
|
|
78
|
+
// venmoReclaimVerifier exists in v2 but not v3
|
|
79
|
+
const verifier = getLatestContract(base.id, 'venmoReclaimVerifier', 'v3');
|
|
80
|
+
assert.strictEqual(verifier, null);
|
|
81
|
+
});
|
|
82
|
+
it('returns null for v3-only key when requesting v2', () => {
|
|
83
|
+
// unifiedPaymentVerifier exists in v3 but not v2
|
|
84
|
+
const verifier = getLatestContract(base.id, 'unifiedPaymentVerifier', 'v2');
|
|
85
|
+
assert.strictEqual(verifier, null);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('getAllEscrowContracts', () => {
|
|
89
|
+
it('returns array of escrow locations', () => {
|
|
90
|
+
const escrows = getAllEscrowContracts();
|
|
91
|
+
assert.ok(Array.isArray(escrows));
|
|
92
|
+
assert.ok(escrows.length >= 4); // v2 Base, v2 Pulse, v3 Base, v3 Pulse
|
|
93
|
+
});
|
|
94
|
+
it('each escrow has required fields', () => {
|
|
95
|
+
const escrows = getAllEscrowContracts();
|
|
96
|
+
for (const escrow of escrows) {
|
|
97
|
+
assert.ok(escrow.version, 'escrow should have version');
|
|
98
|
+
assert.ok(escrow.chainId, 'escrow should have chainId');
|
|
99
|
+
assert.ok(escrow.escrow, 'escrow should have escrow address');
|
|
100
|
+
assert.ok(['v2', 'v3'].includes(escrow.version), 'version should be v2 or v3');
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
it('includes v2 Base escrow', () => {
|
|
104
|
+
const escrows = getAllEscrowContracts();
|
|
105
|
+
const v2BaseEscrow = escrows.find((e) => e.version === 'v2' && e.chainId === base.id);
|
|
106
|
+
assert.ok(v2BaseEscrow);
|
|
107
|
+
assert.strictEqual(v2BaseEscrow.escrow, v2BaseContracts.escrow[0]);
|
|
108
|
+
});
|
|
109
|
+
it('includes v2 Pulsechain escrow', () => {
|
|
110
|
+
const escrows = getAllEscrowContracts();
|
|
111
|
+
const v2PulseEscrow = escrows.find((e) => e.version === 'v2' && e.chainId === pulsechain.id);
|
|
112
|
+
assert.ok(v2PulseEscrow);
|
|
113
|
+
assert.strictEqual(v2PulseEscrow.escrow, v2PulsechainContracts.escrow[0]);
|
|
114
|
+
});
|
|
115
|
+
it('includes v3 Base escrow', () => {
|
|
116
|
+
const escrows = getAllEscrowContracts();
|
|
117
|
+
const v3BaseEscrow = escrows.find((e) => e.version === 'v3' && e.chainId === base.id);
|
|
118
|
+
assert.ok(v3BaseEscrow);
|
|
119
|
+
assert.strictEqual(v3BaseEscrow.escrow, v3BaseContracts.escrow[0]);
|
|
120
|
+
});
|
|
121
|
+
it('includes v3 Pulsechain escrow', () => {
|
|
122
|
+
const escrows = getAllEscrowContracts();
|
|
123
|
+
const v3PulseEscrow = escrows.find((e) => e.version === 'v3' && e.chainId === pulsechain.id);
|
|
124
|
+
assert.ok(v3PulseEscrow);
|
|
125
|
+
assert.strictEqual(v3PulseEscrow.escrow, v3PulsechainContracts.escrow[0]);
|
|
126
|
+
});
|
|
127
|
+
it('escrow addresses are valid hex', () => {
|
|
128
|
+
const escrows = getAllEscrowContracts();
|
|
129
|
+
for (const escrow of escrows) {
|
|
130
|
+
assert.ok(escrow.escrow.startsWith('0x'), 'escrow should start with 0x');
|
|
131
|
+
assert.strictEqual(escrow.escrow.length, 42, 'escrow should be 42 chars');
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('contract structure', () => {
|
|
136
|
+
it('v2 contracts have required verifiers', () => {
|
|
137
|
+
assert.ok(v2BaseContracts.venmoReclaimVerifier);
|
|
138
|
+
assert.ok(v2BaseContracts.revolutReclaimVerifier);
|
|
139
|
+
assert.ok(v2BaseContracts.cashappReclaimVerifier);
|
|
140
|
+
assert.ok(v2BaseContracts.zelleBaseVerifier);
|
|
141
|
+
});
|
|
142
|
+
it('v3 contracts have unifiedPaymentVerifier', () => {
|
|
143
|
+
assert.ok(v3BaseContracts.unifiedPaymentVerifier);
|
|
144
|
+
assert.ok(v3PulsechainContracts.unifiedPaymentVerifier);
|
|
145
|
+
});
|
|
146
|
+
it('contracts registry has both versions', () => {
|
|
147
|
+
assert.ok(contracts.v2);
|
|
148
|
+
assert.ok(contracts.v3);
|
|
149
|
+
});
|
|
150
|
+
it('contracts registry has both chains for v2', () => {
|
|
151
|
+
assert.ok(contracts.v2[base.id]);
|
|
152
|
+
assert.ok(contracts.v2[pulsechain.id]);
|
|
153
|
+
});
|
|
154
|
+
it('contracts registry has both chains for v3', () => {
|
|
155
|
+
assert.ok(contracts.v3[base.id]);
|
|
156
|
+
assert.ok(contracts.v3[pulsechain.id]);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe('V3_PULSECHAIN_DEPLOYMENT_REFERENCE', () => {
|
|
160
|
+
it('should have all reference addresses', () => {
|
|
161
|
+
assert.ok(V3_PULSECHAIN_DEPLOYMENT_REFERENCE.orchestrator);
|
|
162
|
+
assert.ok(V3_PULSECHAIN_DEPLOYMENT_REFERENCE.paymentVerifierRegistry);
|
|
163
|
+
assert.ok(V3_PULSECHAIN_DEPLOYMENT_REFERENCE.protocolViewer);
|
|
164
|
+
assert.ok(V3_PULSECHAIN_DEPLOYMENT_REFERENCE.escrowRegistry);
|
|
165
|
+
});
|
|
166
|
+
it('should have valid address formats', () => {
|
|
167
|
+
assert.ok(V3_PULSECHAIN_DEPLOYMENT_REFERENCE.orchestrator.startsWith('0x'));
|
|
168
|
+
assert.strictEqual(V3_PULSECHAIN_DEPLOYMENT_REFERENCE.orchestrator.length, 42);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('shortenEscrowAddress', () => {
|
|
172
|
+
it('should shorten address to first 6 + last 4 chars', () => {
|
|
173
|
+
const address = '0x1234567890abcdef1234567890abcdef12345678';
|
|
174
|
+
const shortened = shortenEscrowAddress(address);
|
|
175
|
+
assert.equal(shortened, '0x1234...5678');
|
|
176
|
+
});
|
|
177
|
+
it('should handle real escrow addresses', () => {
|
|
178
|
+
const escrow = v3BaseContracts.escrow[0];
|
|
179
|
+
const shortened = shortenEscrowAddress(escrow);
|
|
180
|
+
assert.ok(shortened.startsWith('0x'));
|
|
181
|
+
assert.ok(shortened.includes('...'));
|
|
182
|
+
assert.equal(shortened.length, 13); // 0x + 4 chars + ... + 4 chars
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('getEscrowVersion', () => {
|
|
186
|
+
it('returns v2 for v2 Base escrow', () => {
|
|
187
|
+
const version = getEscrowVersion(v2BaseContracts.escrow[0], base.id);
|
|
188
|
+
assert.strictEqual(version, 'v2');
|
|
189
|
+
});
|
|
190
|
+
it('returns v3 for v3 Base escrow', () => {
|
|
191
|
+
const version = getEscrowVersion(v3BaseContracts.escrow[0], base.id);
|
|
192
|
+
assert.strictEqual(version, 'v3');
|
|
193
|
+
});
|
|
194
|
+
it('returns v2 for v2 Pulsechain escrow', () => {
|
|
195
|
+
const version = getEscrowVersion(v2PulsechainContracts.escrow[0], pulsechain.id);
|
|
196
|
+
assert.strictEqual(version, 'v2');
|
|
197
|
+
});
|
|
198
|
+
it('returns v3 for v3 Pulsechain escrow', () => {
|
|
199
|
+
const version = getEscrowVersion(v3PulsechainContracts.escrow[0], pulsechain.id);
|
|
200
|
+
assert.strictEqual(version, 'v3');
|
|
201
|
+
});
|
|
202
|
+
it('returns null for unknown escrow address', () => {
|
|
203
|
+
const version = getEscrowVersion('0x0000000000000000000000000000000000000000', base.id);
|
|
204
|
+
assert.strictEqual(version, null);
|
|
205
|
+
});
|
|
206
|
+
it('handles case-insensitive address matching', () => {
|
|
207
|
+
const lowerCase = v3BaseContracts.escrow[0].toLowerCase();
|
|
208
|
+
const version = getEscrowVersion(lowerCase, base.id);
|
|
209
|
+
assert.strictEqual(version, 'v3');
|
|
210
|
+
});
|
|
211
|
+
it('finds escrow without chainId by searching all chains', () => {
|
|
212
|
+
const version = getEscrowVersion(v3BaseContracts.escrow[0]);
|
|
213
|
+
assert.strictEqual(version, 'v3');
|
|
214
|
+
});
|
|
215
|
+
it('returns null when chainId doesnt match', () => {
|
|
216
|
+
// v3 Base escrow should not be found if we specify Pulsechain chainId
|
|
217
|
+
const version = getEscrowVersion(v3BaseContracts.escrow[0], pulsechain.id);
|
|
218
|
+
assert.strictEqual(version, null);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
describe('isV3Escrow', () => {
|
|
222
|
+
it('returns true for v3 Base escrow', () => {
|
|
223
|
+
const result = isV3Escrow(v3BaseContracts.escrow[0], base.id);
|
|
224
|
+
assert.strictEqual(result, true);
|
|
225
|
+
});
|
|
226
|
+
it('returns false for v2 Base escrow', () => {
|
|
227
|
+
const result = isV3Escrow(v2BaseContracts.escrow[0], base.id);
|
|
228
|
+
assert.strictEqual(result, false);
|
|
229
|
+
});
|
|
230
|
+
it('returns true for v3 Pulsechain escrow', () => {
|
|
231
|
+
const result = isV3Escrow(v3PulsechainContracts.escrow[0], pulsechain.id);
|
|
232
|
+
assert.strictEqual(result, true);
|
|
233
|
+
});
|
|
234
|
+
it('returns false for v2 Pulsechain escrow', () => {
|
|
235
|
+
const result = isV3Escrow(v2PulsechainContracts.escrow[0], pulsechain.id);
|
|
236
|
+
assert.strictEqual(result, false);
|
|
237
|
+
});
|
|
238
|
+
it('returns false for unknown escrow', () => {
|
|
239
|
+
const result = isV3Escrow('0x0000000000000000000000000000000000000000', base.id);
|
|
240
|
+
assert.strictEqual(result, false);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Conversion rate utilities for fiat-to-crypto exchange calculations.
|
|
3
|
+
*
|
|
4
|
+
* This module processes conversion rate events from deposits and provides utilities
|
|
5
|
+
* for calculating token amounts from fiat amounts and vice versa.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Conversion rates are stored with 18 decimal precision (like ETH).
|
|
9
|
+
* A rate of 1.0 (1:1 exchange) = 1e18 in the contract.
|
|
10
|
+
*
|
|
11
|
+
* Rates are organized by:
|
|
12
|
+
* - Payment provider (Venmo, Zelle, etc.)
|
|
13
|
+
* - Fiat currency (USD, EUR, etc.)
|
|
14
|
+
*
|
|
15
|
+
* @see {@link currencies} for currency definitions
|
|
16
|
+
* @see {@link payment} for provider definitions
|
|
17
|
+
*/
|
|
18
|
+
import type { Hex } from 'viem';
|
|
19
|
+
import { Currency } from './currencies.js';
|
|
20
|
+
import { type ProviderKey } from './payment.js';
|
|
21
|
+
import type { SortDirection } from './sort.js';
|
|
22
|
+
import type { TokenInfo } from './tokens.js';
|
|
23
|
+
import type { ChainId } from './chain.js';
|
|
24
|
+
/**
|
|
25
|
+
* Information about a single conversion rate configuration.
|
|
26
|
+
* Represents a rate set by a depositor for a specific payment method and currency.
|
|
27
|
+
*/
|
|
28
|
+
export interface ConversionRateInfo {
|
|
29
|
+
/** Unique ID of the rate update event */
|
|
30
|
+
depositConversionRateUpdatedId: string;
|
|
31
|
+
/** Currency contract ID (keccak256 hash) */
|
|
32
|
+
currency: string;
|
|
33
|
+
/** Payment verifier address or method ID */
|
|
34
|
+
verifier: string;
|
|
35
|
+
/** Conversion rate as string (18 decimals, e.g., "1000000000000000000" = 1.0) */
|
|
36
|
+
value: string;
|
|
37
|
+
/** Event order ID for chronological sorting */
|
|
38
|
+
orderId: string;
|
|
39
|
+
/** Associated deposit ID */
|
|
40
|
+
depositId: string;
|
|
41
|
+
/** Transaction metadata */
|
|
42
|
+
transaction: {
|
|
43
|
+
hash: string;
|
|
44
|
+
block: {
|
|
45
|
+
timestamp: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extended conversion rate info including the current (latest) rate.
|
|
51
|
+
* Used when processing historical rate changes to track the active rate.
|
|
52
|
+
*/
|
|
53
|
+
export interface ConversionRateInfoWithCurrent extends ConversionRateInfo {
|
|
54
|
+
currentDepositConversionRateUpdatedId: string;
|
|
55
|
+
currentDepositConversionRateUpdated: {
|
|
56
|
+
value: string;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Nested map structure for organizing rates by provider and currency.
|
|
61
|
+
* Outer map: provider key -> currency map
|
|
62
|
+
* Inner map: currency contract ID -> rate info
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* const rates: ProviderRates<ConversionRateInfo> = new Map([
|
|
67
|
+
* ['venmo', new Map([
|
|
68
|
+
* ['0x...usd', { value: '1000000000000000000', ... }]
|
|
69
|
+
* ])]
|
|
70
|
+
* ])
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export type ProviderRates<RateInfo> = Map<ProviderKey, Map<Hex, RateInfo>>;
|
|
74
|
+
/**
|
|
75
|
+
* Options for processing conversion rate events into organized maps.
|
|
76
|
+
*/
|
|
77
|
+
interface ProcessConversionRatesOptions {
|
|
78
|
+
/** Chain ID for verifier lookup */
|
|
79
|
+
chainId: ChainId;
|
|
80
|
+
events: ConversionRateInfoWithCurrent[];
|
|
81
|
+
sortOrder?: SortDirection;
|
|
82
|
+
includeHistorical?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get conversion rate options
|
|
86
|
+
*/
|
|
87
|
+
interface GetConversionRateOptions {
|
|
88
|
+
events: ConversionRateInfoWithCurrent[];
|
|
89
|
+
currency: Hex;
|
|
90
|
+
verifier: string;
|
|
91
|
+
chainId: ChainId;
|
|
92
|
+
includeHistory?: boolean;
|
|
93
|
+
fallbackRate?: {
|
|
94
|
+
currency: string;
|
|
95
|
+
value: string;
|
|
96
|
+
verifier: string;
|
|
97
|
+
} | null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extract currencies options
|
|
101
|
+
*/
|
|
102
|
+
interface ExtractCurrenciesOptions {
|
|
103
|
+
providerRates: ProviderRates<ConversionRateInfo[]>;
|
|
104
|
+
providersOnly?: ProviderKey[];
|
|
105
|
+
currenciesOnly?: string[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Process conversion rate events into an organized map by provider and currency.
|
|
109
|
+
*
|
|
110
|
+
* @param options - Processing options including events and sorting preferences
|
|
111
|
+
* @returns Nested map of provider -> currency -> rate info array
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* const rates = processConversionRates({
|
|
116
|
+
* chainId: 8453,
|
|
117
|
+
* events: depositCurrencyEvents,
|
|
118
|
+
* sortOrder: 'desc',
|
|
119
|
+
* includeHistorical: false
|
|
120
|
+
* })
|
|
121
|
+
*
|
|
122
|
+
* // Get Venmo USD rate
|
|
123
|
+
* const venmoUsd = rates.get('venmo')?.get(USD_CONTRACT_ID)?.[0]
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export declare function processConversionRates(options: ProcessConversionRatesOptions): ProviderRates<ConversionRateInfo[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Get conversion rate for a specific currency and verifier combination
|
|
129
|
+
*/
|
|
130
|
+
export declare function getConversionRate(options: GetConversionRateOptions): ConversionRateInfo | ConversionRateInfo[] | null;
|
|
131
|
+
/**
|
|
132
|
+
* Extract unique currencies from processed provider rates
|
|
133
|
+
*/
|
|
134
|
+
export declare function extractCurrencies(options: ExtractCurrenciesOptions): string[];
|
|
135
|
+
/**
|
|
136
|
+
* Get the latest conversion rate across all providers for a currency
|
|
137
|
+
*/
|
|
138
|
+
export declare function getLatestRateForCurrency(options: {
|
|
139
|
+
providerRates: ProviderRates<ConversionRateInfo>;
|
|
140
|
+
currency: Hex;
|
|
141
|
+
preferredProvider?: ProviderKey;
|
|
142
|
+
}): ConversionRateInfo | null;
|
|
143
|
+
/**
|
|
144
|
+
* Get the primary conversion rate from processed provider rates
|
|
145
|
+
* Returns the first available rate, prioritizing by provider order
|
|
146
|
+
*/
|
|
147
|
+
export declare function getPrimaryConversionRate(providerRates: ProviderRates<ConversionRateInfo>): ConversionRateInfo | null;
|
|
148
|
+
/**
|
|
149
|
+
* Get primary conversion rate for a specific currency across all providers
|
|
150
|
+
*/
|
|
151
|
+
export declare function getPrimaryRateForCurrency(providerRates: ProviderRates<ConversionRateInfo>, currency: Hex): ConversionRateInfo | null;
|
|
152
|
+
/**
|
|
153
|
+
* Get the primary verifier (payment provider) from conversion rates
|
|
154
|
+
*/
|
|
155
|
+
export declare function getPrimaryVerifier(providerRates: ProviderRates<ConversionRateInfo>): string | null;
|
|
156
|
+
/**
|
|
157
|
+
* Get the primary currency from conversion rates
|
|
158
|
+
*/
|
|
159
|
+
export declare function getPrimaryCurrency(providerRates: ProviderRates<ConversionRateInfo>): string | null;
|
|
160
|
+
/**
|
|
161
|
+
* Convert a token amount to a fiat currency amount using the conversion rate.
|
|
162
|
+
* Rounds up to the nearest cent (token decimals - 2) for user-friendly display.
|
|
163
|
+
*
|
|
164
|
+
* @param params - Conversion parameters
|
|
165
|
+
* @param params.token - Token info with decimals
|
|
166
|
+
* @param params.amountOutInt - Token amount as bigint (e.g., 100_000000n for 100 USDC)
|
|
167
|
+
* @param params.rate - Conversion rate with 18 decimals (1e18 = 1:1)
|
|
168
|
+
* @returns Fiat amount as bigint with cent-rounding applied
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* // Convert 100 USDC at 1.05 rate to fiat
|
|
173
|
+
* const fiat = convertTokenInputToCurrency({
|
|
174
|
+
* token: { decimals: 6, ... },
|
|
175
|
+
* amountOutInt: 100_000000n,
|
|
176
|
+
* rate: 1_050000000000000000n // 1.05
|
|
177
|
+
* })
|
|
178
|
+
* // Returns: 105_000000n (rounded to nearest cent)
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export declare const convertTokenInputToCurrency: ({ token, amountOutInt, rate }: {
|
|
182
|
+
token: TokenInfo;
|
|
183
|
+
amountOutInt: bigint;
|
|
184
|
+
rate: bigint;
|
|
185
|
+
}) => bigint;
|
|
186
|
+
/**
|
|
187
|
+
* Convert a fiat currency amount back to token amount (inverse of convertTokenInputToCurrency).
|
|
188
|
+
* Accounts for the cent-rounding that was applied during the forward conversion.
|
|
189
|
+
*
|
|
190
|
+
* @param params - Conversion parameters
|
|
191
|
+
* @param params.token - Token info with decimals
|
|
192
|
+
* @param params.currency - Currency info with decimals
|
|
193
|
+
* @param params.currencyAmountInt - Fiat amount as bigint
|
|
194
|
+
* @param params.rate - Conversion rate with 18 decimals (1e18 = 1:1)
|
|
195
|
+
* @returns Token amount as bigint, floored to smallest token unit
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* // Convert $105 fiat back to USDC at 1.05 rate
|
|
200
|
+
* const tokens = convertCurrencyToTokenOutput({
|
|
201
|
+
* token: { decimals: 6, ... },
|
|
202
|
+
* currency: SUPPORTED_CURRENCIES.USD,
|
|
203
|
+
* currencyAmountInt: 105_00n, // $105.00
|
|
204
|
+
* rate: 1_050000000000000000n // 1.05
|
|
205
|
+
* })
|
|
206
|
+
* // Returns: 100_000000n (100 USDC)
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
export declare const convertCurrencyToTokenOutput: ({ token, currency, currencyAmountInt, rate, }: {
|
|
210
|
+
token: TokenInfo;
|
|
211
|
+
currency: Currency;
|
|
212
|
+
currencyAmountInt: bigint;
|
|
213
|
+
rate: bigint;
|
|
214
|
+
}) => bigint;
|
|
215
|
+
export {};
|
|
@@ -1,7 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Conversion rate utilities for fiat-to-crypto exchange calculations.
|
|
3
|
+
*
|
|
4
|
+
* This module processes conversion rate events from deposits and provides utilities
|
|
5
|
+
* for calculating token amounts from fiat amounts and vice versa.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Conversion rates are stored with 18 decimal precision (like ETH).
|
|
9
|
+
* A rate of 1.0 (1:1 exchange) = 1e18 in the contract.
|
|
10
|
+
*
|
|
11
|
+
* Rates are organized by:
|
|
12
|
+
* - Payment provider (Venmo, Zelle, etc.)
|
|
13
|
+
* - Fiat currency (USD, EUR, etc.)
|
|
14
|
+
*
|
|
15
|
+
* @see {@link currencies} for currency definitions
|
|
16
|
+
* @see {@link payment} for provider definitions
|
|
17
|
+
*/
|
|
1
18
|
import { SUPPORTED_CURRENCIES } from './currencies.js';
|
|
2
19
|
import { verifierGetsKey } from './payment.js';
|
|
3
20
|
/**
|
|
4
|
-
* Process
|
|
21
|
+
* Process conversion rate events into an organized map by provider and currency.
|
|
22
|
+
*
|
|
23
|
+
* @param options - Processing options including events and sorting preferences
|
|
24
|
+
* @returns Nested map of provider -> currency -> rate info array
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const rates = processConversionRates({
|
|
29
|
+
* chainId: 8453,
|
|
30
|
+
* events: depositCurrencyEvents,
|
|
31
|
+
* sortOrder: 'desc',
|
|
32
|
+
* includeHistorical: false
|
|
33
|
+
* })
|
|
34
|
+
*
|
|
35
|
+
* // Get Venmo USD rate
|
|
36
|
+
* const venmoUsd = rates.get('venmo')?.get(USD_CONTRACT_ID)?.[0]
|
|
37
|
+
* ```
|
|
5
38
|
*/
|
|
6
39
|
export function processConversionRates(options) {
|
|
7
40
|
const { events, sortOrder = 'asc', includeHistorical = false, chainId, } = options;
|
|
@@ -189,7 +222,25 @@ export function getPrimaryCurrency(providerRates) {
|
|
|
189
222
|
return primaryRate?.currency || null;
|
|
190
223
|
}
|
|
191
224
|
/**
|
|
192
|
-
* Convert token
|
|
225
|
+
* Convert a token amount to a fiat currency amount using the conversion rate.
|
|
226
|
+
* Rounds up to the nearest cent (token decimals - 2) for user-friendly display.
|
|
227
|
+
*
|
|
228
|
+
* @param params - Conversion parameters
|
|
229
|
+
* @param params.token - Token info with decimals
|
|
230
|
+
* @param params.amountOutInt - Token amount as bigint (e.g., 100_000000n for 100 USDC)
|
|
231
|
+
* @param params.rate - Conversion rate with 18 decimals (1e18 = 1:1)
|
|
232
|
+
* @returns Fiat amount as bigint with cent-rounding applied
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* // Convert 100 USDC at 1.05 rate to fiat
|
|
237
|
+
* const fiat = convertTokenInputToCurrency({
|
|
238
|
+
* token: { decimals: 6, ... },
|
|
239
|
+
* amountOutInt: 100_000000n,
|
|
240
|
+
* rate: 1_050000000000000000n // 1.05
|
|
241
|
+
* })
|
|
242
|
+
* // Returns: 105_000000n (rounded to nearest cent)
|
|
243
|
+
* ```
|
|
193
244
|
*/
|
|
194
245
|
export const convertTokenInputToCurrency = ({ token, amountOutInt, rate }) => {
|
|
195
246
|
const oneCent = 10n ** BigInt(token.decimals - 2);
|
|
@@ -201,8 +252,27 @@ export const convertTokenInputToCurrency = ({ token, amountOutInt, rate }) => {
|
|
|
201
252
|
return finalAmountInInt;
|
|
202
253
|
};
|
|
203
254
|
/**
|
|
204
|
-
* Convert currency amount to token amount
|
|
205
|
-
*
|
|
255
|
+
* Convert a fiat currency amount back to token amount (inverse of convertTokenInputToCurrency).
|
|
256
|
+
* Accounts for the cent-rounding that was applied during the forward conversion.
|
|
257
|
+
*
|
|
258
|
+
* @param params - Conversion parameters
|
|
259
|
+
* @param params.token - Token info with decimals
|
|
260
|
+
* @param params.currency - Currency info with decimals
|
|
261
|
+
* @param params.currencyAmountInt - Fiat amount as bigint
|
|
262
|
+
* @param params.rate - Conversion rate with 18 decimals (1e18 = 1:1)
|
|
263
|
+
* @returns Token amount as bigint, floored to smallest token unit
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* // Convert $105 fiat back to USDC at 1.05 rate
|
|
268
|
+
* const tokens = convertCurrencyToTokenOutput({
|
|
269
|
+
* token: { decimals: 6, ... },
|
|
270
|
+
* currency: SUPPORTED_CURRENCIES.USD,
|
|
271
|
+
* currencyAmountInt: 105_00n, // $105.00
|
|
272
|
+
* rate: 1_050000000000000000n // 1.05
|
|
273
|
+
* })
|
|
274
|
+
* // Returns: 100_000000n (100 USDC)
|
|
275
|
+
* ```
|
|
206
276
|
*/
|
|
207
277
|
export const convertCurrencyToTokenOutput = ({ token, currency, currencyAmountInt, rate, }) => {
|
|
208
278
|
const smallestUnit = 10n ** BigInt(token.decimals - currency.decimals);
|