@fiatsend/core 0.1.0
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/index.d.mts +4719 -0
- package/dist/index.d.ts +4719 -0
- package/dist/index.js +4387 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4366 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +44 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4387 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var viem = require('viem');
|
|
4
|
+
var types = require('@fiatsend/types');
|
|
5
|
+
var utils = require('@fiatsend/utils');
|
|
6
|
+
|
|
7
|
+
// src/client.ts
|
|
8
|
+
|
|
9
|
+
// src/config.ts
|
|
10
|
+
var ZERO = "0x0000000000000000000000000000000000000000";
|
|
11
|
+
var CHAINS = {
|
|
12
|
+
bsc: {
|
|
13
|
+
chainId: 56,
|
|
14
|
+
name: "BNB Smart Chain",
|
|
15
|
+
rpcUrl: "https://bsc-dataseed.binance.org",
|
|
16
|
+
contracts: {
|
|
17
|
+
mobileNumberNFT: ZERO,
|
|
18
|
+
gateway: ZERO,
|
|
19
|
+
paymentRouter: ZERO,
|
|
20
|
+
withdrawals: ZERO,
|
|
21
|
+
liquidityPool: ZERO,
|
|
22
|
+
vaultController: ZERO,
|
|
23
|
+
ghsFiat: ZERO,
|
|
24
|
+
payoutEscrow: ZERO,
|
|
25
|
+
p2pExchange: ZERO
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
polygon: {
|
|
29
|
+
chainId: 137,
|
|
30
|
+
name: "Polygon",
|
|
31
|
+
rpcUrl: "https://polygon-rpc.com",
|
|
32
|
+
contracts: {
|
|
33
|
+
mobileNumberNFT: ZERO,
|
|
34
|
+
gateway: ZERO,
|
|
35
|
+
paymentRouter: ZERO,
|
|
36
|
+
withdrawals: ZERO,
|
|
37
|
+
liquidityPool: ZERO,
|
|
38
|
+
vaultController: ZERO,
|
|
39
|
+
ghsFiat: ZERO,
|
|
40
|
+
payoutEscrow: ZERO,
|
|
41
|
+
p2pExchange: ZERO
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
bscTestnet: {
|
|
45
|
+
chainId: 97,
|
|
46
|
+
name: "BNB Smart Chain Testnet",
|
|
47
|
+
rpcUrl: "https://bnb-testnet.g.alchemy.com/v2/f-aLkrbDR0Yn9cafkJrazWwWCh8DrbVF",
|
|
48
|
+
contracts: {
|
|
49
|
+
mobileNumberNFT: "0x9f9914d4F528268CE070C52605852BB5207f0767",
|
|
50
|
+
gateway: "0x284f2D3f65aCAdD30B06F963c316161385728B88",
|
|
51
|
+
paymentRouter: "0x701ECdb6823fc3e258c7E291D2D8C16BC52Fbe94",
|
|
52
|
+
withdrawals: "0x008864a6937cF16acbb0D08cBFE0a1b59FbDA2aB",
|
|
53
|
+
liquidityPool: "0x915Be609c7aA429322447951c8905220D82a4e20",
|
|
54
|
+
vaultController: "0x6c15230473422471ae0653B3530C840836092dd5",
|
|
55
|
+
ghsFiat: "0x4D0FB402146204636f663f179828D409d4B578bf",
|
|
56
|
+
payoutEscrow: "0xE3d86823f533a400D24AB3F01f9c907Ea07012AB",
|
|
57
|
+
p2pExchange: "0x3364A46C779B60A6aCe8825C1e5A52dDB40cF256"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
polygonMumbai: {
|
|
61
|
+
chainId: 80001,
|
|
62
|
+
name: "Polygon Mumbai Testnet",
|
|
63
|
+
rpcUrl: "https://rpc-mumbai.maticvigil.com",
|
|
64
|
+
contracts: {
|
|
65
|
+
mobileNumberNFT: ZERO,
|
|
66
|
+
gateway: ZERO,
|
|
67
|
+
paymentRouter: ZERO,
|
|
68
|
+
withdrawals: ZERO,
|
|
69
|
+
liquidityPool: ZERO,
|
|
70
|
+
vaultController: ZERO,
|
|
71
|
+
ghsFiat: ZERO,
|
|
72
|
+
payoutEscrow: ZERO,
|
|
73
|
+
p2pExchange: ZERO
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
function getChainConfig(chainIdOrName) {
|
|
78
|
+
if (typeof chainIdOrName === "string") {
|
|
79
|
+
const config2 = CHAINS[chainIdOrName];
|
|
80
|
+
if (!config2) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Chain "${chainIdOrName}" is not configured. Available chains: ${Object.keys(CHAINS).join(", ")}`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return config2;
|
|
86
|
+
}
|
|
87
|
+
const config = Object.values(CHAINS).find((c) => c.chainId === chainIdOrName);
|
|
88
|
+
if (!config) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Chain ID ${chainIdOrName} is not configured. Available chain IDs: ${Object.values(CHAINS).map((c) => c.chainId).join(", ")}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
return config;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/abis/MobileNumberNFT.ts
|
|
97
|
+
var MobileNumberNFTABI = [
|
|
98
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
99
|
+
{
|
|
100
|
+
type: "error",
|
|
101
|
+
name: "AlreadyRegistered",
|
|
102
|
+
inputs: []
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: "error",
|
|
106
|
+
name: "PhoneAlreadyRegistered",
|
|
107
|
+
inputs: []
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: "error",
|
|
111
|
+
name: "NotAuthorized",
|
|
112
|
+
inputs: []
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: "error",
|
|
116
|
+
name: "InvalidKYCLevel",
|
|
117
|
+
inputs: []
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: "error",
|
|
121
|
+
name: "TransferNotAllowed",
|
|
122
|
+
inputs: []
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
type: "error",
|
|
126
|
+
name: "SignatureExpired",
|
|
127
|
+
inputs: []
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
type: "error",
|
|
131
|
+
name: "InvalidSignature",
|
|
132
|
+
inputs: []
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: "error",
|
|
136
|
+
name: "ZeroAddress",
|
|
137
|
+
inputs: []
|
|
138
|
+
},
|
|
139
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
140
|
+
{
|
|
141
|
+
type: "event",
|
|
142
|
+
name: "MobileNumberRegistered",
|
|
143
|
+
inputs: [
|
|
144
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
145
|
+
{ name: "tokenId", type: "uint256", indexed: true, internalType: "uint256" },
|
|
146
|
+
{ name: "countryCode", type: "string", indexed: false, internalType: "string" }
|
|
147
|
+
],
|
|
148
|
+
anonymous: false
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: "event",
|
|
152
|
+
name: "KYCLevelUpdated",
|
|
153
|
+
inputs: [
|
|
154
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
155
|
+
{ name: "tokenId", type: "uint256", indexed: true, internalType: "uint256" },
|
|
156
|
+
{ name: "newLevel", type: "uint8", indexed: false, internalType: "uint8" }
|
|
157
|
+
],
|
|
158
|
+
anonymous: false
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: "event",
|
|
162
|
+
name: "Transfer",
|
|
163
|
+
inputs: [
|
|
164
|
+
{ name: "from", type: "address", indexed: true, internalType: "address" },
|
|
165
|
+
{ name: "to", type: "address", indexed: true, internalType: "address" },
|
|
166
|
+
{ name: "tokenId", type: "uint256", indexed: true, internalType: "uint256" }
|
|
167
|
+
],
|
|
168
|
+
anonymous: false
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: "event",
|
|
172
|
+
name: "Approval",
|
|
173
|
+
inputs: [
|
|
174
|
+
{ name: "owner", type: "address", indexed: true, internalType: "address" },
|
|
175
|
+
{ name: "approved", type: "address", indexed: true, internalType: "address" },
|
|
176
|
+
{ name: "tokenId", type: "uint256", indexed: true, internalType: "uint256" }
|
|
177
|
+
],
|
|
178
|
+
anonymous: false
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: "event",
|
|
182
|
+
name: "ApprovalForAll",
|
|
183
|
+
inputs: [
|
|
184
|
+
{ name: "owner", type: "address", indexed: true, internalType: "address" },
|
|
185
|
+
{ name: "operator", type: "address", indexed: true, internalType: "address" },
|
|
186
|
+
{ name: "approved", type: "bool", indexed: false, internalType: "bool" }
|
|
187
|
+
],
|
|
188
|
+
anonymous: false
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
type: "event",
|
|
192
|
+
name: "OwnershipTransferred",
|
|
193
|
+
inputs: [
|
|
194
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
195
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
196
|
+
],
|
|
197
|
+
anonymous: false
|
|
198
|
+
},
|
|
199
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
200
|
+
{
|
|
201
|
+
type: "constructor",
|
|
202
|
+
inputs: [{ name: "baseURI", type: "string", internalType: "string" }],
|
|
203
|
+
stateMutability: "nonpayable"
|
|
204
|
+
},
|
|
205
|
+
// ─── Functions: Registration ──────────────────────────────────────────────
|
|
206
|
+
{
|
|
207
|
+
type: "function",
|
|
208
|
+
name: "registerMobile",
|
|
209
|
+
inputs: [
|
|
210
|
+
{ name: "encryptedPhone", type: "bytes", internalType: "bytes" },
|
|
211
|
+
{ name: "countryCode", type: "string", internalType: "string" }
|
|
212
|
+
],
|
|
213
|
+
outputs: [],
|
|
214
|
+
stateMutability: "nonpayable"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
type: "function",
|
|
218
|
+
name: "registerMobileWithSignature",
|
|
219
|
+
inputs: [
|
|
220
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
221
|
+
{ name: "encryptedPhone", type: "bytes", internalType: "bytes" },
|
|
222
|
+
{ name: "countryCode", type: "string", internalType: "string" },
|
|
223
|
+
{ name: "deadline", type: "uint256", internalType: "uint256" },
|
|
224
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
225
|
+
],
|
|
226
|
+
outputs: [],
|
|
227
|
+
stateMutability: "nonpayable"
|
|
228
|
+
},
|
|
229
|
+
// ─── Functions: KYC ───────────────────────────────────────────────────────
|
|
230
|
+
{
|
|
231
|
+
type: "function",
|
|
232
|
+
name: "updateKYCLevel",
|
|
233
|
+
inputs: [
|
|
234
|
+
{ name: "tokenId", type: "uint256", internalType: "uint256" },
|
|
235
|
+
{ name: "newLevel", type: "uint8", internalType: "uint8" }
|
|
236
|
+
],
|
|
237
|
+
outputs: [],
|
|
238
|
+
stateMutability: "nonpayable"
|
|
239
|
+
},
|
|
240
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
241
|
+
{
|
|
242
|
+
type: "function",
|
|
243
|
+
name: "setAuthorizedMinter",
|
|
244
|
+
inputs: [
|
|
245
|
+
{ name: "minter", type: "address", internalType: "address" },
|
|
246
|
+
{ name: "authorized", type: "bool", internalType: "bool" }
|
|
247
|
+
],
|
|
248
|
+
outputs: [],
|
|
249
|
+
stateMutability: "nonpayable"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
type: "function",
|
|
253
|
+
name: "setBaseURI",
|
|
254
|
+
inputs: [{ name: "baseURI", type: "string", internalType: "string" }],
|
|
255
|
+
outputs: [],
|
|
256
|
+
stateMutability: "nonpayable"
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
type: "function",
|
|
260
|
+
name: "transferOwnership",
|
|
261
|
+
inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
|
|
262
|
+
outputs: [],
|
|
263
|
+
stateMutability: "nonpayable"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
type: "function",
|
|
267
|
+
name: "renounceOwnership",
|
|
268
|
+
inputs: [],
|
|
269
|
+
outputs: [],
|
|
270
|
+
stateMutability: "nonpayable"
|
|
271
|
+
},
|
|
272
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
273
|
+
{
|
|
274
|
+
type: "function",
|
|
275
|
+
name: "getTokenId",
|
|
276
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
277
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
278
|
+
stateMutability: "view"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
type: "function",
|
|
282
|
+
name: "getTokenIdByPhone",
|
|
283
|
+
inputs: [{ name: "encryptedPhone", type: "bytes", internalType: "bytes" }],
|
|
284
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
285
|
+
stateMutability: "view"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
type: "function",
|
|
289
|
+
name: "getKYCLevel",
|
|
290
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
291
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
292
|
+
stateMutability: "view"
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
type: "function",
|
|
296
|
+
name: "getKYCLevelByAddress",
|
|
297
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
298
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
299
|
+
stateMutability: "view"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
type: "function",
|
|
303
|
+
name: "getCountryCode",
|
|
304
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
305
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
306
|
+
stateMutability: "view"
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
type: "function",
|
|
310
|
+
name: "getEncryptedPhone",
|
|
311
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
312
|
+
outputs: [{ name: "", type: "bytes", internalType: "bytes" }],
|
|
313
|
+
stateMutability: "view"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
type: "function",
|
|
317
|
+
name: "nonces",
|
|
318
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
319
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
320
|
+
stateMutability: "view"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
type: "function",
|
|
324
|
+
name: "owner",
|
|
325
|
+
inputs: [],
|
|
326
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
327
|
+
stateMutability: "view"
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
type: "function",
|
|
331
|
+
name: "ownerOf",
|
|
332
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
333
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
334
|
+
stateMutability: "view"
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
type: "function",
|
|
338
|
+
name: "balanceOf",
|
|
339
|
+
inputs: [{ name: "owner", type: "address", internalType: "address" }],
|
|
340
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
341
|
+
stateMutability: "view"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
type: "function",
|
|
345
|
+
name: "tokenURI",
|
|
346
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
347
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
348
|
+
stateMutability: "view"
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
type: "function",
|
|
352
|
+
name: "totalSupply",
|
|
353
|
+
inputs: [],
|
|
354
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
355
|
+
stateMutability: "view"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
type: "function",
|
|
359
|
+
name: "tokenByIndex",
|
|
360
|
+
inputs: [{ name: "index", type: "uint256", internalType: "uint256" }],
|
|
361
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
362
|
+
stateMutability: "view"
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
type: "function",
|
|
366
|
+
name: "tokenOfOwnerByIndex",
|
|
367
|
+
inputs: [
|
|
368
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
369
|
+
{ name: "index", type: "uint256", internalType: "uint256" }
|
|
370
|
+
],
|
|
371
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
372
|
+
stateMutability: "view"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
type: "function",
|
|
376
|
+
name: "supportsInterface",
|
|
377
|
+
inputs: [{ name: "interfaceId", type: "bytes4", internalType: "bytes4" }],
|
|
378
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
379
|
+
stateMutability: "view"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
type: "function",
|
|
383
|
+
name: "name",
|
|
384
|
+
inputs: [],
|
|
385
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
386
|
+
stateMutability: "view"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
type: "function",
|
|
390
|
+
name: "symbol",
|
|
391
|
+
inputs: [],
|
|
392
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
393
|
+
stateMutability: "view"
|
|
394
|
+
}
|
|
395
|
+
];
|
|
396
|
+
|
|
397
|
+
// src/abis/FiatsendGateway.ts
|
|
398
|
+
var FiatsendGatewayABI = [
|
|
399
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
400
|
+
{ type: "error", name: "TokenNotSupported", inputs: [] },
|
|
401
|
+
{ type: "error", name: "NoMobileNFT", inputs: [] },
|
|
402
|
+
{ type: "error", name: "KYCRequired", inputs: [] },
|
|
403
|
+
{ type: "error", name: "BelowMinimum", inputs: [] },
|
|
404
|
+
{ type: "error", name: "DailyLimitExceeded", inputs: [] },
|
|
405
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
406
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
407
|
+
{ type: "error", name: "InvalidFeeRate", inputs: [] },
|
|
408
|
+
{ type: "error", name: "NotAuthorizedOnramp", inputs: [] },
|
|
409
|
+
{ type: "error", name: "NotAuthorizedContract", inputs: [] },
|
|
410
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
411
|
+
{
|
|
412
|
+
type: "event",
|
|
413
|
+
name: "OfframpInitiated",
|
|
414
|
+
inputs: [
|
|
415
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
416
|
+
{ name: "token", type: "address", indexed: true, internalType: "address" },
|
|
417
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" },
|
|
418
|
+
{ name: "fee", type: "uint256", indexed: false, internalType: "uint256" },
|
|
419
|
+
{ name: "phoneNumber", type: "string", indexed: false, internalType: "string" }
|
|
420
|
+
],
|
|
421
|
+
anonymous: false
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
type: "event",
|
|
425
|
+
name: "OnrampCompleted",
|
|
426
|
+
inputs: [
|
|
427
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
428
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
429
|
+
],
|
|
430
|
+
anonymous: false
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
type: "event",
|
|
434
|
+
name: "ConversionRateUpdated",
|
|
435
|
+
inputs: [
|
|
436
|
+
{ name: "token", type: "address", indexed: true, internalType: "address" },
|
|
437
|
+
{ name: "rate", type: "uint256", indexed: false, internalType: "uint256" }
|
|
438
|
+
],
|
|
439
|
+
anonymous: false
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
type: "event",
|
|
443
|
+
name: "TokenAdded",
|
|
444
|
+
inputs: [{ name: "token", type: "address", indexed: true, internalType: "address" }],
|
|
445
|
+
anonymous: false
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
type: "event",
|
|
449
|
+
name: "TokenRemoved",
|
|
450
|
+
inputs: [{ name: "token", type: "address", indexed: true, internalType: "address" }],
|
|
451
|
+
anonymous: false
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
type: "event",
|
|
455
|
+
name: "FeeCollected",
|
|
456
|
+
inputs: [
|
|
457
|
+
{ name: "token", type: "address", indexed: true, internalType: "address" },
|
|
458
|
+
{ name: "feeAmount", type: "uint256", indexed: false, internalType: "uint256" },
|
|
459
|
+
{ name: "treasury", type: "address", indexed: false, internalType: "address" }
|
|
460
|
+
],
|
|
461
|
+
anonymous: false
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
type: "event",
|
|
465
|
+
name: "Paused",
|
|
466
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
467
|
+
anonymous: false
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
type: "event",
|
|
471
|
+
name: "Unpaused",
|
|
472
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
473
|
+
anonymous: false
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
type: "event",
|
|
477
|
+
name: "OwnershipTransferred",
|
|
478
|
+
inputs: [
|
|
479
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
480
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
481
|
+
],
|
|
482
|
+
anonymous: false
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
type: "event",
|
|
486
|
+
name: "Upgraded",
|
|
487
|
+
inputs: [{ name: "implementation", type: "address", indexed: true, internalType: "address" }],
|
|
488
|
+
anonymous: false
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
type: "event",
|
|
492
|
+
name: "Initialized",
|
|
493
|
+
inputs: [{ name: "version", type: "uint64", indexed: false, internalType: "uint64" }],
|
|
494
|
+
anonymous: false
|
|
495
|
+
},
|
|
496
|
+
// ─── Functions: Initializer ───────────────────────────────────────────────
|
|
497
|
+
{
|
|
498
|
+
type: "function",
|
|
499
|
+
name: "initialize",
|
|
500
|
+
inputs: [
|
|
501
|
+
{ name: "_ghsFiatToken", type: "address", internalType: "address" },
|
|
502
|
+
{ name: "_mobileNumberNFT", type: "address", internalType: "address" },
|
|
503
|
+
{ name: "_treasury", type: "address", internalType: "address" },
|
|
504
|
+
{ name: "_feeRate", type: "uint256", internalType: "uint256" }
|
|
505
|
+
],
|
|
506
|
+
outputs: [],
|
|
507
|
+
stateMutability: "nonpayable"
|
|
508
|
+
},
|
|
509
|
+
// ─── Functions: Core operations ───────────────────────────────────────────
|
|
510
|
+
{
|
|
511
|
+
type: "function",
|
|
512
|
+
name: "offrampFor",
|
|
513
|
+
inputs: [
|
|
514
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
515
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
516
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
517
|
+
{ name: "phoneNumber", type: "string", internalType: "string" }
|
|
518
|
+
],
|
|
519
|
+
outputs: [],
|
|
520
|
+
stateMutability: "nonpayable"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
type: "function",
|
|
524
|
+
name: "offramp",
|
|
525
|
+
inputs: [
|
|
526
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
527
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
528
|
+
{ name: "phoneNumber", type: "string", internalType: "string" }
|
|
529
|
+
],
|
|
530
|
+
outputs: [],
|
|
531
|
+
stateMutability: "nonpayable"
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
type: "function",
|
|
535
|
+
name: "onramp",
|
|
536
|
+
inputs: [
|
|
537
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
538
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
539
|
+
],
|
|
540
|
+
outputs: [],
|
|
541
|
+
stateMutability: "nonpayable"
|
|
542
|
+
},
|
|
543
|
+
// ─── Functions: Admin — Configuration ────────────────────────────────────
|
|
544
|
+
{
|
|
545
|
+
type: "function",
|
|
546
|
+
name: "setConversionRate",
|
|
547
|
+
inputs: [
|
|
548
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
549
|
+
{ name: "rate", type: "uint256", internalType: "uint256" }
|
|
550
|
+
],
|
|
551
|
+
outputs: [],
|
|
552
|
+
stateMutability: "nonpayable"
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
type: "function",
|
|
556
|
+
name: "addSupportedToken",
|
|
557
|
+
inputs: [{ name: "token", type: "address", internalType: "address" }],
|
|
558
|
+
outputs: [],
|
|
559
|
+
stateMutability: "nonpayable"
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
type: "function",
|
|
563
|
+
name: "removeSupportedToken",
|
|
564
|
+
inputs: [{ name: "token", type: "address", internalType: "address" }],
|
|
565
|
+
outputs: [],
|
|
566
|
+
stateMutability: "nonpayable"
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
type: "function",
|
|
570
|
+
name: "setKYC",
|
|
571
|
+
inputs: [
|
|
572
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
573
|
+
{ name: "status", type: "bool", internalType: "bool" }
|
|
574
|
+
],
|
|
575
|
+
outputs: [],
|
|
576
|
+
stateMutability: "nonpayable"
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
type: "function",
|
|
580
|
+
name: "setProtocolFee",
|
|
581
|
+
inputs: [{ name: "newFeeRate", type: "uint256", internalType: "uint256" }],
|
|
582
|
+
outputs: [],
|
|
583
|
+
stateMutability: "nonpayable"
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
type: "function",
|
|
587
|
+
name: "setMinWithdrawAmount",
|
|
588
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
589
|
+
outputs: [],
|
|
590
|
+
stateMutability: "nonpayable"
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
type: "function",
|
|
594
|
+
name: "setDailyLimit",
|
|
595
|
+
inputs: [{ name: "limit", type: "uint256", internalType: "uint256" }],
|
|
596
|
+
outputs: [],
|
|
597
|
+
stateMutability: "nonpayable"
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
type: "function",
|
|
601
|
+
name: "setWithdrawalsContract",
|
|
602
|
+
inputs: [{ name: "_withdrawals", type: "address", internalType: "address" }],
|
|
603
|
+
outputs: [],
|
|
604
|
+
stateMutability: "nonpayable"
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
type: "function",
|
|
608
|
+
name: "setAuthorizedOnramper",
|
|
609
|
+
inputs: [
|
|
610
|
+
{ name: "onramper", type: "address", internalType: "address" },
|
|
611
|
+
{ name: "authorized", type: "bool", internalType: "bool" }
|
|
612
|
+
],
|
|
613
|
+
outputs: [],
|
|
614
|
+
stateMutability: "nonpayable"
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
type: "function",
|
|
618
|
+
name: "setAuthorizedContract",
|
|
619
|
+
inputs: [
|
|
620
|
+
{ name: "contractAddr", type: "address", internalType: "address" },
|
|
621
|
+
{ name: "authorized", type: "bool", internalType: "bool" }
|
|
622
|
+
],
|
|
623
|
+
outputs: [],
|
|
624
|
+
stateMutability: "nonpayable"
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
type: "function",
|
|
628
|
+
name: "setProtocolTreasury",
|
|
629
|
+
inputs: [{ name: "treasury", type: "address", internalType: "address" }],
|
|
630
|
+
outputs: [],
|
|
631
|
+
stateMutability: "nonpayable"
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
type: "function",
|
|
635
|
+
name: "emergencyWithdraw",
|
|
636
|
+
inputs: [
|
|
637
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
638
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
639
|
+
],
|
|
640
|
+
outputs: [],
|
|
641
|
+
stateMutability: "nonpayable"
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
type: "function",
|
|
645
|
+
name: "pause",
|
|
646
|
+
inputs: [],
|
|
647
|
+
outputs: [],
|
|
648
|
+
stateMutability: "nonpayable"
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
type: "function",
|
|
652
|
+
name: "unpause",
|
|
653
|
+
inputs: [],
|
|
654
|
+
outputs: [],
|
|
655
|
+
stateMutability: "nonpayable"
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
type: "function",
|
|
659
|
+
name: "transferOwnership",
|
|
660
|
+
inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
|
|
661
|
+
outputs: [],
|
|
662
|
+
stateMutability: "nonpayable"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
type: "function",
|
|
666
|
+
name: "renounceOwnership",
|
|
667
|
+
inputs: [],
|
|
668
|
+
outputs: [],
|
|
669
|
+
stateMutability: "nonpayable"
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
type: "function",
|
|
673
|
+
name: "upgradeTo",
|
|
674
|
+
inputs: [{ name: "newImplementation", type: "address", internalType: "address" }],
|
|
675
|
+
outputs: [],
|
|
676
|
+
stateMutability: "nonpayable"
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
type: "function",
|
|
680
|
+
name: "upgradeToAndCall",
|
|
681
|
+
inputs: [
|
|
682
|
+
{ name: "newImplementation", type: "address", internalType: "address" },
|
|
683
|
+
{ name: "data", type: "bytes", internalType: "bytes" }
|
|
684
|
+
],
|
|
685
|
+
outputs: [],
|
|
686
|
+
stateMutability: "payable"
|
|
687
|
+
},
|
|
688
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
689
|
+
{
|
|
690
|
+
type: "function",
|
|
691
|
+
name: "isTokenSupported",
|
|
692
|
+
inputs: [{ name: "token", type: "address", internalType: "address" }],
|
|
693
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
694
|
+
stateMutability: "view"
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
type: "function",
|
|
698
|
+
name: "getConversionRate",
|
|
699
|
+
inputs: [{ name: "token", type: "address", internalType: "address" }],
|
|
700
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
701
|
+
stateMutability: "view"
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
type: "function",
|
|
705
|
+
name: "isKYCPassed",
|
|
706
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
707
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
708
|
+
stateMutability: "view"
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
type: "function",
|
|
712
|
+
name: "getDailyVolume",
|
|
713
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
714
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
715
|
+
stateMutability: "view"
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
type: "function",
|
|
719
|
+
name: "isAuthorizedContract",
|
|
720
|
+
inputs: [{ name: "contractAddr", type: "address", internalType: "address" }],
|
|
721
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
722
|
+
stateMutability: "view"
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
type: "function",
|
|
726
|
+
name: "protocolFeeRate",
|
|
727
|
+
inputs: [],
|
|
728
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
729
|
+
stateMutability: "view"
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
type: "function",
|
|
733
|
+
name: "protocolTreasury",
|
|
734
|
+
inputs: [],
|
|
735
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
736
|
+
stateMutability: "view"
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
type: "function",
|
|
740
|
+
name: "minWithdrawAmount",
|
|
741
|
+
inputs: [],
|
|
742
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
743
|
+
stateMutability: "view"
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
type: "function",
|
|
747
|
+
name: "dailyLimit",
|
|
748
|
+
inputs: [],
|
|
749
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
750
|
+
stateMutability: "view"
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
type: "function",
|
|
754
|
+
name: "paused",
|
|
755
|
+
inputs: [],
|
|
756
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
757
|
+
stateMutability: "view"
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
type: "function",
|
|
761
|
+
name: "owner",
|
|
762
|
+
inputs: [],
|
|
763
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
764
|
+
stateMutability: "view"
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
type: "function",
|
|
768
|
+
name: "MAX_FEE_RATE",
|
|
769
|
+
inputs: [],
|
|
770
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
771
|
+
stateMutability: "view"
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
type: "function",
|
|
775
|
+
name: "KYC_THRESHOLD",
|
|
776
|
+
inputs: [],
|
|
777
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
778
|
+
stateMutability: "view"
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
type: "function",
|
|
782
|
+
name: "ghsFiatToken",
|
|
783
|
+
inputs: [],
|
|
784
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
785
|
+
stateMutability: "view"
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
type: "function",
|
|
789
|
+
name: "mobileNumberNFT",
|
|
790
|
+
inputs: [],
|
|
791
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
792
|
+
stateMutability: "view"
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
type: "function",
|
|
796
|
+
name: "withdrawalsContract",
|
|
797
|
+
inputs: [],
|
|
798
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
799
|
+
stateMutability: "view"
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
type: "function",
|
|
803
|
+
name: "proxiableUUID",
|
|
804
|
+
inputs: [],
|
|
805
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
806
|
+
stateMutability: "view"
|
|
807
|
+
}
|
|
808
|
+
];
|
|
809
|
+
|
|
810
|
+
// src/abis/PaymentRouter.ts
|
|
811
|
+
var PaymentRouterABI = [
|
|
812
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
813
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
814
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
815
|
+
{ type: "error", name: "PhoneNotRegistered", inputs: [] },
|
|
816
|
+
{ type: "error", name: "RequestNotFound", inputs: [] },
|
|
817
|
+
{ type: "error", name: "RequestNotPending", inputs: [] },
|
|
818
|
+
{ type: "error", name: "NotRequestOwner", inputs: [] },
|
|
819
|
+
{ type: "error", name: "NotRequestRecipient", inputs: [] },
|
|
820
|
+
{ type: "error", name: "SelfPayment", inputs: [] },
|
|
821
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
822
|
+
{
|
|
823
|
+
type: "event",
|
|
824
|
+
name: "PaymentSent",
|
|
825
|
+
inputs: [
|
|
826
|
+
{ name: "from", type: "address", indexed: true, internalType: "address" },
|
|
827
|
+
{ name: "to", type: "address", indexed: true, internalType: "address" },
|
|
828
|
+
{ name: "token", type: "address", indexed: false, internalType: "address" },
|
|
829
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" },
|
|
830
|
+
{ name: "memo", type: "string", indexed: false, internalType: "string" }
|
|
831
|
+
],
|
|
832
|
+
anonymous: false
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
type: "event",
|
|
836
|
+
name: "PaymentRequestCreated",
|
|
837
|
+
inputs: [
|
|
838
|
+
{ name: "requestId", type: "uint256", indexed: true, internalType: "uint256" },
|
|
839
|
+
{ name: "from", type: "address", indexed: true, internalType: "address" },
|
|
840
|
+
{ name: "to", type: "address", indexed: true, internalType: "address" },
|
|
841
|
+
{ name: "token", type: "address", indexed: false, internalType: "address" },
|
|
842
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
843
|
+
],
|
|
844
|
+
anonymous: false
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
type: "event",
|
|
848
|
+
name: "PaymentRequestPaid",
|
|
849
|
+
inputs: [
|
|
850
|
+
{ name: "requestId", type: "uint256", indexed: true, internalType: "uint256" },
|
|
851
|
+
{ name: "paidBy", type: "address", indexed: true, internalType: "address" }
|
|
852
|
+
],
|
|
853
|
+
anonymous: false
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
type: "event",
|
|
857
|
+
name: "PaymentRequestCancelled",
|
|
858
|
+
inputs: [{ name: "requestId", type: "uint256", indexed: true, internalType: "uint256" }],
|
|
859
|
+
anonymous: false
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
type: "event",
|
|
863
|
+
name: "OwnershipTransferred",
|
|
864
|
+
inputs: [
|
|
865
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
866
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
867
|
+
],
|
|
868
|
+
anonymous: false
|
|
869
|
+
},
|
|
870
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
871
|
+
{
|
|
872
|
+
type: "constructor",
|
|
873
|
+
inputs: [
|
|
874
|
+
{ name: "_mobileNumberNFT", type: "address", internalType: "address" },
|
|
875
|
+
{ name: "_feeTreasury", type: "address", internalType: "address" }
|
|
876
|
+
],
|
|
877
|
+
stateMutability: "nonpayable"
|
|
878
|
+
},
|
|
879
|
+
// ─── Functions: Payments ──────────────────────────────────────────────────
|
|
880
|
+
{
|
|
881
|
+
type: "function",
|
|
882
|
+
name: "send",
|
|
883
|
+
inputs: [
|
|
884
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
885
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
886
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
887
|
+
{ name: "memo", type: "string", internalType: "string" }
|
|
888
|
+
],
|
|
889
|
+
outputs: [],
|
|
890
|
+
stateMutability: "nonpayable"
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
type: "function",
|
|
894
|
+
name: "sendToPhone",
|
|
895
|
+
inputs: [
|
|
896
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
897
|
+
{ name: "encryptedPhone", type: "bytes", internalType: "bytes" },
|
|
898
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
899
|
+
{ name: "memo", type: "string", internalType: "string" }
|
|
900
|
+
],
|
|
901
|
+
outputs: [],
|
|
902
|
+
stateMutability: "nonpayable"
|
|
903
|
+
},
|
|
904
|
+
// ─── Functions: Payment Requests ─────────────────────────────────────────
|
|
905
|
+
{
|
|
906
|
+
type: "function",
|
|
907
|
+
name: "createPaymentRequest",
|
|
908
|
+
inputs: [
|
|
909
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
910
|
+
{ name: "from", type: "address", internalType: "address" },
|
|
911
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
912
|
+
{ name: "memo", type: "string", internalType: "string" }
|
|
913
|
+
],
|
|
914
|
+
outputs: [{ name: "requestId", type: "uint256", internalType: "uint256" }],
|
|
915
|
+
stateMutability: "nonpayable"
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
type: "function",
|
|
919
|
+
name: "payRequest",
|
|
920
|
+
inputs: [{ name: "requestId", type: "uint256", internalType: "uint256" }],
|
|
921
|
+
outputs: [],
|
|
922
|
+
stateMutability: "nonpayable"
|
|
923
|
+
},
|
|
924
|
+
{
|
|
925
|
+
type: "function",
|
|
926
|
+
name: "cancelRequest",
|
|
927
|
+
inputs: [{ name: "requestId", type: "uint256", internalType: "uint256" }],
|
|
928
|
+
outputs: [],
|
|
929
|
+
stateMutability: "nonpayable"
|
|
930
|
+
},
|
|
931
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
932
|
+
{
|
|
933
|
+
type: "function",
|
|
934
|
+
name: "setP2PFeeRate",
|
|
935
|
+
inputs: [{ name: "rate", type: "uint256", internalType: "uint256" }],
|
|
936
|
+
outputs: [],
|
|
937
|
+
stateMutability: "nonpayable"
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
type: "function",
|
|
941
|
+
name: "setFeeTreasury",
|
|
942
|
+
inputs: [{ name: "treasury", type: "address", internalType: "address" }],
|
|
943
|
+
outputs: [],
|
|
944
|
+
stateMutability: "nonpayable"
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
type: "function",
|
|
948
|
+
name: "transferOwnership",
|
|
949
|
+
inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
|
|
950
|
+
outputs: [],
|
|
951
|
+
stateMutability: "nonpayable"
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
type: "function",
|
|
955
|
+
name: "renounceOwnership",
|
|
956
|
+
inputs: [],
|
|
957
|
+
outputs: [],
|
|
958
|
+
stateMutability: "nonpayable"
|
|
959
|
+
},
|
|
960
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
961
|
+
{
|
|
962
|
+
type: "function",
|
|
963
|
+
name: "getPaymentRequest",
|
|
964
|
+
inputs: [{ name: "requestId", type: "uint256", internalType: "uint256" }],
|
|
965
|
+
outputs: [
|
|
966
|
+
{
|
|
967
|
+
name: "",
|
|
968
|
+
type: "tuple",
|
|
969
|
+
internalType: "struct IPaymentRouter.PaymentRequest",
|
|
970
|
+
components: [
|
|
971
|
+
{ name: "id", type: "uint256", internalType: "uint256" },
|
|
972
|
+
{ name: "from", type: "address", internalType: "address" },
|
|
973
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
974
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
975
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
976
|
+
{ name: "memo", type: "string", internalType: "string" },
|
|
977
|
+
{ name: "status", type: "uint8", internalType: "enum IPaymentRouter.RequestStatus" },
|
|
978
|
+
{ name: "createdAt", type: "uint256", internalType: "uint256" }
|
|
979
|
+
]
|
|
980
|
+
}
|
|
981
|
+
],
|
|
982
|
+
stateMutability: "view"
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
type: "function",
|
|
986
|
+
name: "paymentRequestCounter",
|
|
987
|
+
inputs: [],
|
|
988
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
989
|
+
stateMutability: "view"
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
type: "function",
|
|
993
|
+
name: "p2pFeeRate",
|
|
994
|
+
inputs: [],
|
|
995
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
996
|
+
stateMutability: "view"
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
type: "function",
|
|
1000
|
+
name: "feeTreasury",
|
|
1001
|
+
inputs: [],
|
|
1002
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1003
|
+
stateMutability: "view"
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
type: "function",
|
|
1007
|
+
name: "mobileNumberNFT",
|
|
1008
|
+
inputs: [],
|
|
1009
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1010
|
+
stateMutability: "view"
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
type: "function",
|
|
1014
|
+
name: "owner",
|
|
1015
|
+
inputs: [],
|
|
1016
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1017
|
+
stateMutability: "view"
|
|
1018
|
+
}
|
|
1019
|
+
];
|
|
1020
|
+
|
|
1021
|
+
// src/abis/Withdrawals.ts
|
|
1022
|
+
var WithdrawalsABI = [
|
|
1023
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
1024
|
+
{ type: "error", name: "OnlyGateway", inputs: [] },
|
|
1025
|
+
{ type: "error", name: "WithdrawalNotFound", inputs: [] },
|
|
1026
|
+
{ type: "error", name: "InvalidStatus", inputs: [] },
|
|
1027
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
1028
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
1029
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
1030
|
+
{
|
|
1031
|
+
type: "event",
|
|
1032
|
+
name: "WithdrawalCreated",
|
|
1033
|
+
inputs: [
|
|
1034
|
+
{ name: "id", type: "uint256", indexed: true, internalType: "uint256" },
|
|
1035
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1036
|
+
{ name: "token", type: "address", indexed: false, internalType: "address" },
|
|
1037
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" },
|
|
1038
|
+
{ name: "fee", type: "uint256", indexed: false, internalType: "uint256" },
|
|
1039
|
+
{ name: "phoneNumber", type: "string", indexed: false, internalType: "string" }
|
|
1040
|
+
],
|
|
1041
|
+
anonymous: false
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
type: "event",
|
|
1045
|
+
name: "WithdrawalProcessing",
|
|
1046
|
+
inputs: [{ name: "id", type: "uint256", indexed: true, internalType: "uint256" }],
|
|
1047
|
+
anonymous: false
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
type: "event",
|
|
1051
|
+
name: "WithdrawalCompleted",
|
|
1052
|
+
inputs: [
|
|
1053
|
+
{ name: "id", type: "uint256", indexed: true, internalType: "uint256" },
|
|
1054
|
+
{ name: "completedAt", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1055
|
+
],
|
|
1056
|
+
anonymous: false
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
type: "event",
|
|
1060
|
+
name: "WithdrawalFailed",
|
|
1061
|
+
inputs: [
|
|
1062
|
+
{ name: "id", type: "uint256", indexed: true, internalType: "uint256" },
|
|
1063
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1064
|
+
{ name: "refundAmount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1065
|
+
],
|
|
1066
|
+
anonymous: false
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
type: "event",
|
|
1070
|
+
name: "GatewayUpdated",
|
|
1071
|
+
inputs: [{ name: "gateway", type: "address", indexed: true, internalType: "address" }],
|
|
1072
|
+
anonymous: false
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
type: "event",
|
|
1076
|
+
name: "OwnershipTransferred",
|
|
1077
|
+
inputs: [
|
|
1078
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
1079
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
1080
|
+
],
|
|
1081
|
+
anonymous: false
|
|
1082
|
+
},
|
|
1083
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
1084
|
+
{
|
|
1085
|
+
type: "constructor",
|
|
1086
|
+
inputs: [],
|
|
1087
|
+
stateMutability: "nonpayable"
|
|
1088
|
+
},
|
|
1089
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
1090
|
+
{
|
|
1091
|
+
type: "function",
|
|
1092
|
+
name: "setGateway",
|
|
1093
|
+
inputs: [{ name: "_gateway", type: "address", internalType: "address" }],
|
|
1094
|
+
outputs: [],
|
|
1095
|
+
stateMutability: "nonpayable"
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
type: "function",
|
|
1099
|
+
name: "processWithdrawal",
|
|
1100
|
+
inputs: [{ name: "id", type: "uint256", internalType: "uint256" }],
|
|
1101
|
+
outputs: [],
|
|
1102
|
+
stateMutability: "nonpayable"
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
type: "function",
|
|
1106
|
+
name: "completeWithdrawal",
|
|
1107
|
+
inputs: [{ name: "id", type: "uint256", internalType: "uint256" }],
|
|
1108
|
+
outputs: [],
|
|
1109
|
+
stateMutability: "nonpayable"
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
type: "function",
|
|
1113
|
+
name: "failWithdrawal",
|
|
1114
|
+
inputs: [{ name: "id", type: "uint256", internalType: "uint256" }],
|
|
1115
|
+
outputs: [],
|
|
1116
|
+
stateMutability: "nonpayable"
|
|
1117
|
+
},
|
|
1118
|
+
// ─── Functions: Gateway-only ──────────────────────────────────────────────
|
|
1119
|
+
{
|
|
1120
|
+
type: "function",
|
|
1121
|
+
name: "createWithdrawal",
|
|
1122
|
+
inputs: [
|
|
1123
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
1124
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
1125
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
1126
|
+
{ name: "fee", type: "uint256", internalType: "uint256" },
|
|
1127
|
+
{ name: "paymentMethod", type: "uint8", internalType: "uint8" },
|
|
1128
|
+
{ name: "phoneNumber", type: "string", internalType: "string" }
|
|
1129
|
+
],
|
|
1130
|
+
outputs: [{ name: "id", type: "uint256", internalType: "uint256" }],
|
|
1131
|
+
stateMutability: "nonpayable"
|
|
1132
|
+
},
|
|
1133
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
1134
|
+
{
|
|
1135
|
+
type: "function",
|
|
1136
|
+
name: "getWithdrawal",
|
|
1137
|
+
inputs: [{ name: "id", type: "uint256", internalType: "uint256" }],
|
|
1138
|
+
outputs: [
|
|
1139
|
+
{
|
|
1140
|
+
name: "",
|
|
1141
|
+
type: "tuple",
|
|
1142
|
+
internalType: "struct Withdrawals.Withdrawal",
|
|
1143
|
+
components: [
|
|
1144
|
+
{ name: "id", type: "uint256", internalType: "uint256" },
|
|
1145
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
1146
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
1147
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
1148
|
+
{ name: "fee", type: "uint256", internalType: "uint256" },
|
|
1149
|
+
{ name: "status", type: "uint8", internalType: "uint8" },
|
|
1150
|
+
{ name: "paymentMethod", type: "uint8", internalType: "uint8" },
|
|
1151
|
+
{ name: "phoneNumber", type: "string", internalType: "string" },
|
|
1152
|
+
{ name: "createdAt", type: "uint256", internalType: "uint256" },
|
|
1153
|
+
{ name: "completedAt", type: "uint256", internalType: "uint256" }
|
|
1154
|
+
]
|
|
1155
|
+
}
|
|
1156
|
+
],
|
|
1157
|
+
stateMutability: "view"
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
type: "function",
|
|
1161
|
+
name: "getUserWithdrawals",
|
|
1162
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
1163
|
+
outputs: [{ name: "", type: "uint256[]", internalType: "uint256[]" }],
|
|
1164
|
+
stateMutability: "view"
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
type: "function",
|
|
1168
|
+
name: "withdrawalCounter",
|
|
1169
|
+
inputs: [],
|
|
1170
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1171
|
+
stateMutability: "view"
|
|
1172
|
+
},
|
|
1173
|
+
{
|
|
1174
|
+
type: "function",
|
|
1175
|
+
name: "gateway",
|
|
1176
|
+
inputs: [],
|
|
1177
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1178
|
+
stateMutability: "view"
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
type: "function",
|
|
1182
|
+
name: "STATUS_PENDING",
|
|
1183
|
+
inputs: [],
|
|
1184
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
1185
|
+
stateMutability: "view"
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
type: "function",
|
|
1189
|
+
name: "STATUS_PROCESSING",
|
|
1190
|
+
inputs: [],
|
|
1191
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
1192
|
+
stateMutability: "view"
|
|
1193
|
+
},
|
|
1194
|
+
{
|
|
1195
|
+
type: "function",
|
|
1196
|
+
name: "STATUS_COMPLETED",
|
|
1197
|
+
inputs: [],
|
|
1198
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
1199
|
+
stateMutability: "view"
|
|
1200
|
+
},
|
|
1201
|
+
{
|
|
1202
|
+
type: "function",
|
|
1203
|
+
name: "STATUS_FAILED",
|
|
1204
|
+
inputs: [],
|
|
1205
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
1206
|
+
stateMutability: "view"
|
|
1207
|
+
},
|
|
1208
|
+
{
|
|
1209
|
+
type: "function",
|
|
1210
|
+
name: "owner",
|
|
1211
|
+
inputs: [],
|
|
1212
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1213
|
+
stateMutability: "view"
|
|
1214
|
+
}
|
|
1215
|
+
];
|
|
1216
|
+
|
|
1217
|
+
// src/abis/LiquidityPool.ts
|
|
1218
|
+
var LiquidityPoolABI = [
|
|
1219
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
1220
|
+
{ type: "error", name: "BelowMinDeposit", inputs: [] },
|
|
1221
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
1222
|
+
{ type: "error", name: "LockPeriodActive", inputs: [] },
|
|
1223
|
+
{ type: "error", name: "InsufficientBalance", inputs: [] },
|
|
1224
|
+
{ type: "error", name: "OnlyGateway", inputs: [] },
|
|
1225
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
1226
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
1227
|
+
{
|
|
1228
|
+
type: "event",
|
|
1229
|
+
name: "Deposited",
|
|
1230
|
+
inputs: [
|
|
1231
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1232
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1233
|
+
],
|
|
1234
|
+
anonymous: false
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
type: "event",
|
|
1238
|
+
name: "Withdrawn",
|
|
1239
|
+
inputs: [
|
|
1240
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1241
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1242
|
+
],
|
|
1243
|
+
anonymous: false
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
type: "event",
|
|
1247
|
+
name: "RewardsClaimed",
|
|
1248
|
+
inputs: [
|
|
1249
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1250
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1251
|
+
],
|
|
1252
|
+
anonymous: false
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
type: "event",
|
|
1256
|
+
name: "RewardsDistributed",
|
|
1257
|
+
inputs: [{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }],
|
|
1258
|
+
anonymous: false
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
type: "event",
|
|
1262
|
+
name: "OwnershipTransferred",
|
|
1263
|
+
inputs: [
|
|
1264
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
1265
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
1266
|
+
],
|
|
1267
|
+
anonymous: false
|
|
1268
|
+
},
|
|
1269
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
1270
|
+
{
|
|
1271
|
+
type: "constructor",
|
|
1272
|
+
inputs: [
|
|
1273
|
+
{ name: "_supportedToken", type: "address", internalType: "address" },
|
|
1274
|
+
{ name: "_gateway", type: "address", internalType: "address" },
|
|
1275
|
+
{ name: "_minDeposit", type: "uint256", internalType: "uint256" },
|
|
1276
|
+
{ name: "_lockPeriod", type: "uint256", internalType: "uint256" }
|
|
1277
|
+
],
|
|
1278
|
+
stateMutability: "nonpayable"
|
|
1279
|
+
},
|
|
1280
|
+
// ─── Functions: LP actions ────────────────────────────────────────────────
|
|
1281
|
+
{
|
|
1282
|
+
type: "function",
|
|
1283
|
+
name: "deposit",
|
|
1284
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1285
|
+
outputs: [],
|
|
1286
|
+
stateMutability: "nonpayable"
|
|
1287
|
+
},
|
|
1288
|
+
{
|
|
1289
|
+
type: "function",
|
|
1290
|
+
name: "withdraw",
|
|
1291
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1292
|
+
outputs: [],
|
|
1293
|
+
stateMutability: "nonpayable"
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
type: "function",
|
|
1297
|
+
name: "claimRewards",
|
|
1298
|
+
inputs: [],
|
|
1299
|
+
outputs: [],
|
|
1300
|
+
stateMutability: "nonpayable"
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
type: "function",
|
|
1304
|
+
name: "distributeRewards",
|
|
1305
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1306
|
+
outputs: [],
|
|
1307
|
+
stateMutability: "nonpayable"
|
|
1308
|
+
},
|
|
1309
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
1310
|
+
{
|
|
1311
|
+
type: "function",
|
|
1312
|
+
name: "setGateway",
|
|
1313
|
+
inputs: [{ name: "_gateway", type: "address", internalType: "address" }],
|
|
1314
|
+
outputs: [],
|
|
1315
|
+
stateMutability: "nonpayable"
|
|
1316
|
+
},
|
|
1317
|
+
{
|
|
1318
|
+
type: "function",
|
|
1319
|
+
name: "setMinDeposit",
|
|
1320
|
+
inputs: [{ name: "_minDeposit", type: "uint256", internalType: "uint256" }],
|
|
1321
|
+
outputs: [],
|
|
1322
|
+
stateMutability: "nonpayable"
|
|
1323
|
+
},
|
|
1324
|
+
{
|
|
1325
|
+
type: "function",
|
|
1326
|
+
name: "setLockPeriod",
|
|
1327
|
+
inputs: [{ name: "_lockPeriod", type: "uint256", internalType: "uint256" }],
|
|
1328
|
+
outputs: [],
|
|
1329
|
+
stateMutability: "nonpayable"
|
|
1330
|
+
},
|
|
1331
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
1332
|
+
{
|
|
1333
|
+
type: "function",
|
|
1334
|
+
name: "getRewards",
|
|
1335
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
1336
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1337
|
+
stateMutability: "view"
|
|
1338
|
+
},
|
|
1339
|
+
{
|
|
1340
|
+
type: "function",
|
|
1341
|
+
name: "getDeposit",
|
|
1342
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
1343
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1344
|
+
stateMutability: "view"
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
type: "function",
|
|
1348
|
+
name: "getPoolInfo",
|
|
1349
|
+
inputs: [],
|
|
1350
|
+
outputs: [
|
|
1351
|
+
{
|
|
1352
|
+
name: "",
|
|
1353
|
+
type: "tuple",
|
|
1354
|
+
internalType: "struct ILiquidityPool.PoolInfo",
|
|
1355
|
+
components: [
|
|
1356
|
+
{ name: "totalDeposits", type: "uint256", internalType: "uint256" },
|
|
1357
|
+
{ name: "rewardPerToken", type: "uint256", internalType: "uint256" },
|
|
1358
|
+
{ name: "supportedToken", type: "address", internalType: "address" },
|
|
1359
|
+
{ name: "minDeposit", type: "uint256", internalType: "uint256" },
|
|
1360
|
+
{ name: "lockPeriod", type: "uint256", internalType: "uint256" }
|
|
1361
|
+
]
|
|
1362
|
+
}
|
|
1363
|
+
],
|
|
1364
|
+
stateMutability: "view"
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
type: "function",
|
|
1368
|
+
name: "supportedToken",
|
|
1369
|
+
inputs: [],
|
|
1370
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1371
|
+
stateMutability: "view"
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
type: "function",
|
|
1375
|
+
name: "totalDeposits",
|
|
1376
|
+
inputs: [],
|
|
1377
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1378
|
+
stateMutability: "view"
|
|
1379
|
+
},
|
|
1380
|
+
{
|
|
1381
|
+
type: "function",
|
|
1382
|
+
name: "minDeposit",
|
|
1383
|
+
inputs: [],
|
|
1384
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1385
|
+
stateMutability: "view"
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
type: "function",
|
|
1389
|
+
name: "lockPeriod",
|
|
1390
|
+
inputs: [],
|
|
1391
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1392
|
+
stateMutability: "view"
|
|
1393
|
+
},
|
|
1394
|
+
{
|
|
1395
|
+
type: "function",
|
|
1396
|
+
name: "accRewardPerShare",
|
|
1397
|
+
inputs: [],
|
|
1398
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1399
|
+
stateMutability: "view"
|
|
1400
|
+
},
|
|
1401
|
+
{
|
|
1402
|
+
type: "function",
|
|
1403
|
+
name: "gateway",
|
|
1404
|
+
inputs: [],
|
|
1405
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1406
|
+
stateMutability: "view"
|
|
1407
|
+
},
|
|
1408
|
+
{
|
|
1409
|
+
type: "function",
|
|
1410
|
+
name: "owner",
|
|
1411
|
+
inputs: [],
|
|
1412
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1413
|
+
stateMutability: "view"
|
|
1414
|
+
}
|
|
1415
|
+
];
|
|
1416
|
+
|
|
1417
|
+
// src/abis/VaultController.ts
|
|
1418
|
+
var VaultControllerABI = [
|
|
1419
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
1420
|
+
{ type: "error", name: "BelowMinDeposit", inputs: [] },
|
|
1421
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
1422
|
+
{ type: "error", name: "InsufficientBalance", inputs: [] },
|
|
1423
|
+
{ type: "error", name: "NoYieldAvailable", inputs: [] },
|
|
1424
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
1425
|
+
{ type: "error", name: "InvalidYieldRate", inputs: [] },
|
|
1426
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
1427
|
+
{
|
|
1428
|
+
type: "event",
|
|
1429
|
+
name: "VaultDeposited",
|
|
1430
|
+
inputs: [
|
|
1431
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1432
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1433
|
+
],
|
|
1434
|
+
anonymous: false
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
type: "event",
|
|
1438
|
+
name: "VaultWithdrawn",
|
|
1439
|
+
inputs: [
|
|
1440
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1441
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1442
|
+
],
|
|
1443
|
+
anonymous: false
|
|
1444
|
+
},
|
|
1445
|
+
{
|
|
1446
|
+
type: "event",
|
|
1447
|
+
name: "YieldClaimed",
|
|
1448
|
+
inputs: [
|
|
1449
|
+
{ name: "user", type: "address", indexed: true, internalType: "address" },
|
|
1450
|
+
{ name: "yieldAmount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1451
|
+
],
|
|
1452
|
+
anonymous: false
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
type: "event",
|
|
1456
|
+
name: "YieldRateUpdated",
|
|
1457
|
+
inputs: [{ name: "newRate", type: "uint256", indexed: false, internalType: "uint256" }],
|
|
1458
|
+
anonymous: false
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
type: "event",
|
|
1462
|
+
name: "OwnershipTransferred",
|
|
1463
|
+
inputs: [
|
|
1464
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
1465
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
1466
|
+
],
|
|
1467
|
+
anonymous: false
|
|
1468
|
+
},
|
|
1469
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
1470
|
+
{
|
|
1471
|
+
type: "constructor",
|
|
1472
|
+
inputs: [
|
|
1473
|
+
{ name: "_supportedToken", type: "address", internalType: "address" },
|
|
1474
|
+
{ name: "_annualYieldRate", type: "uint256", internalType: "uint256" },
|
|
1475
|
+
{ name: "_minDeposit", type: "uint256", internalType: "uint256" }
|
|
1476
|
+
],
|
|
1477
|
+
stateMutability: "nonpayable"
|
|
1478
|
+
},
|
|
1479
|
+
// ─── Functions: Vault actions ─────────────────────────────────────────────
|
|
1480
|
+
{
|
|
1481
|
+
type: "function",
|
|
1482
|
+
name: "deposit",
|
|
1483
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1484
|
+
outputs: [],
|
|
1485
|
+
stateMutability: "nonpayable"
|
|
1486
|
+
},
|
|
1487
|
+
{
|
|
1488
|
+
type: "function",
|
|
1489
|
+
name: "withdraw",
|
|
1490
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1491
|
+
outputs: [],
|
|
1492
|
+
stateMutability: "nonpayable"
|
|
1493
|
+
},
|
|
1494
|
+
{
|
|
1495
|
+
type: "function",
|
|
1496
|
+
name: "claimYield",
|
|
1497
|
+
inputs: [],
|
|
1498
|
+
outputs: [],
|
|
1499
|
+
stateMutability: "nonpayable"
|
|
1500
|
+
},
|
|
1501
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
1502
|
+
{
|
|
1503
|
+
type: "function",
|
|
1504
|
+
name: "setAnnualYieldRate",
|
|
1505
|
+
inputs: [{ name: "rate", type: "uint256", internalType: "uint256" }],
|
|
1506
|
+
outputs: [],
|
|
1507
|
+
stateMutability: "nonpayable"
|
|
1508
|
+
},
|
|
1509
|
+
{
|
|
1510
|
+
type: "function",
|
|
1511
|
+
name: "setMinDeposit",
|
|
1512
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1513
|
+
outputs: [],
|
|
1514
|
+
stateMutability: "nonpayable"
|
|
1515
|
+
},
|
|
1516
|
+
{
|
|
1517
|
+
type: "function",
|
|
1518
|
+
name: "transferOwnership",
|
|
1519
|
+
inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
|
|
1520
|
+
outputs: [],
|
|
1521
|
+
stateMutability: "nonpayable"
|
|
1522
|
+
},
|
|
1523
|
+
{
|
|
1524
|
+
type: "function",
|
|
1525
|
+
name: "renounceOwnership",
|
|
1526
|
+
inputs: [],
|
|
1527
|
+
outputs: [],
|
|
1528
|
+
stateMutability: "nonpayable"
|
|
1529
|
+
},
|
|
1530
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
1531
|
+
{
|
|
1532
|
+
type: "function",
|
|
1533
|
+
name: "getVault",
|
|
1534
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
1535
|
+
outputs: [
|
|
1536
|
+
{
|
|
1537
|
+
name: "",
|
|
1538
|
+
type: "tuple",
|
|
1539
|
+
internalType: "struct IVault.VaultInfo",
|
|
1540
|
+
components: [
|
|
1541
|
+
{ name: "balance", type: "uint256", internalType: "uint256" },
|
|
1542
|
+
{ name: "depositedAt", type: "uint256", internalType: "uint256" },
|
|
1543
|
+
{ name: "lastYieldClaim", type: "uint256", internalType: "uint256" }
|
|
1544
|
+
]
|
|
1545
|
+
}
|
|
1546
|
+
],
|
|
1547
|
+
stateMutability: "view"
|
|
1548
|
+
},
|
|
1549
|
+
{
|
|
1550
|
+
type: "function",
|
|
1551
|
+
name: "calculateYield",
|
|
1552
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
1553
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1554
|
+
stateMutability: "view"
|
|
1555
|
+
},
|
|
1556
|
+
{
|
|
1557
|
+
type: "function",
|
|
1558
|
+
name: "annualYieldRate",
|
|
1559
|
+
inputs: [],
|
|
1560
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1561
|
+
stateMutability: "view"
|
|
1562
|
+
},
|
|
1563
|
+
{
|
|
1564
|
+
type: "function",
|
|
1565
|
+
name: "minDeposit",
|
|
1566
|
+
inputs: [],
|
|
1567
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1568
|
+
stateMutability: "view"
|
|
1569
|
+
},
|
|
1570
|
+
{
|
|
1571
|
+
type: "function",
|
|
1572
|
+
name: "totalDeposited",
|
|
1573
|
+
inputs: [],
|
|
1574
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1575
|
+
stateMutability: "view"
|
|
1576
|
+
},
|
|
1577
|
+
{
|
|
1578
|
+
type: "function",
|
|
1579
|
+
name: "supportedToken",
|
|
1580
|
+
inputs: [],
|
|
1581
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1582
|
+
stateMutability: "view"
|
|
1583
|
+
},
|
|
1584
|
+
{
|
|
1585
|
+
type: "function",
|
|
1586
|
+
name: "MAX_YIELD_RATE",
|
|
1587
|
+
inputs: [],
|
|
1588
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1589
|
+
stateMutability: "view"
|
|
1590
|
+
},
|
|
1591
|
+
{
|
|
1592
|
+
type: "function",
|
|
1593
|
+
name: "owner",
|
|
1594
|
+
inputs: [],
|
|
1595
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
1596
|
+
stateMutability: "view"
|
|
1597
|
+
}
|
|
1598
|
+
];
|
|
1599
|
+
|
|
1600
|
+
// src/abis/GHSFIAT.ts
|
|
1601
|
+
var GHSFIATABI = [
|
|
1602
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
1603
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
1604
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
1605
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
1606
|
+
{
|
|
1607
|
+
type: "event",
|
|
1608
|
+
name: "Transfer",
|
|
1609
|
+
inputs: [
|
|
1610
|
+
{ name: "from", type: "address", indexed: true, internalType: "address" },
|
|
1611
|
+
{ name: "to", type: "address", indexed: true, internalType: "address" },
|
|
1612
|
+
{ name: "value", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1613
|
+
],
|
|
1614
|
+
anonymous: false
|
|
1615
|
+
},
|
|
1616
|
+
{
|
|
1617
|
+
type: "event",
|
|
1618
|
+
name: "Approval",
|
|
1619
|
+
inputs: [
|
|
1620
|
+
{ name: "owner", type: "address", indexed: true, internalType: "address" },
|
|
1621
|
+
{ name: "spender", type: "address", indexed: true, internalType: "address" },
|
|
1622
|
+
{ name: "value", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1623
|
+
],
|
|
1624
|
+
anonymous: false
|
|
1625
|
+
},
|
|
1626
|
+
{
|
|
1627
|
+
type: "event",
|
|
1628
|
+
name: "Paused",
|
|
1629
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
1630
|
+
anonymous: false
|
|
1631
|
+
},
|
|
1632
|
+
{
|
|
1633
|
+
type: "event",
|
|
1634
|
+
name: "Unpaused",
|
|
1635
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
1636
|
+
anonymous: false
|
|
1637
|
+
},
|
|
1638
|
+
{
|
|
1639
|
+
type: "event",
|
|
1640
|
+
name: "RoleGranted",
|
|
1641
|
+
inputs: [
|
|
1642
|
+
{ name: "role", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
1643
|
+
{ name: "account", type: "address", indexed: true, internalType: "address" },
|
|
1644
|
+
{ name: "sender", type: "address", indexed: true, internalType: "address" }
|
|
1645
|
+
],
|
|
1646
|
+
anonymous: false
|
|
1647
|
+
},
|
|
1648
|
+
{
|
|
1649
|
+
type: "event",
|
|
1650
|
+
name: "RoleRevoked",
|
|
1651
|
+
inputs: [
|
|
1652
|
+
{ name: "role", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
1653
|
+
{ name: "account", type: "address", indexed: true, internalType: "address" },
|
|
1654
|
+
{ name: "sender", type: "address", indexed: true, internalType: "address" }
|
|
1655
|
+
],
|
|
1656
|
+
anonymous: false
|
|
1657
|
+
},
|
|
1658
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
1659
|
+
{
|
|
1660
|
+
type: "constructor",
|
|
1661
|
+
inputs: [{ name: "admin", type: "address", internalType: "address" }],
|
|
1662
|
+
stateMutability: "nonpayable"
|
|
1663
|
+
},
|
|
1664
|
+
// ─── Functions: Mint / Burn ───────────────────────────────────────────────
|
|
1665
|
+
{
|
|
1666
|
+
type: "function",
|
|
1667
|
+
name: "mint",
|
|
1668
|
+
inputs: [
|
|
1669
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
1670
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
1671
|
+
],
|
|
1672
|
+
outputs: [],
|
|
1673
|
+
stateMutability: "nonpayable"
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
type: "function",
|
|
1677
|
+
name: "burn",
|
|
1678
|
+
inputs: [{ name: "amount", type: "uint256", internalType: "uint256" }],
|
|
1679
|
+
outputs: [],
|
|
1680
|
+
stateMutability: "nonpayable"
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
type: "function",
|
|
1684
|
+
name: "burnFrom",
|
|
1685
|
+
inputs: [
|
|
1686
|
+
{ name: "account", type: "address", internalType: "address" },
|
|
1687
|
+
{ name: "amount", type: "uint256", internalType: "uint256" }
|
|
1688
|
+
],
|
|
1689
|
+
outputs: [],
|
|
1690
|
+
stateMutability: "nonpayable"
|
|
1691
|
+
},
|
|
1692
|
+
// ─── Functions: Pause / Unpause ───────────────────────────────────────────
|
|
1693
|
+
{
|
|
1694
|
+
type: "function",
|
|
1695
|
+
name: "pause",
|
|
1696
|
+
inputs: [],
|
|
1697
|
+
outputs: [],
|
|
1698
|
+
stateMutability: "nonpayable"
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
type: "function",
|
|
1702
|
+
name: "unpause",
|
|
1703
|
+
inputs: [],
|
|
1704
|
+
outputs: [],
|
|
1705
|
+
stateMutability: "nonpayable"
|
|
1706
|
+
},
|
|
1707
|
+
// ─── Functions: ERC20 ─────────────────────────────────────────────────────
|
|
1708
|
+
{
|
|
1709
|
+
type: "function",
|
|
1710
|
+
name: "transfer",
|
|
1711
|
+
inputs: [
|
|
1712
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
1713
|
+
{ name: "value", type: "uint256", internalType: "uint256" }
|
|
1714
|
+
],
|
|
1715
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1716
|
+
stateMutability: "nonpayable"
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
type: "function",
|
|
1720
|
+
name: "transferFrom",
|
|
1721
|
+
inputs: [
|
|
1722
|
+
{ name: "from", type: "address", internalType: "address" },
|
|
1723
|
+
{ name: "to", type: "address", internalType: "address" },
|
|
1724
|
+
{ name: "value", type: "uint256", internalType: "uint256" }
|
|
1725
|
+
],
|
|
1726
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1727
|
+
stateMutability: "nonpayable"
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
type: "function",
|
|
1731
|
+
name: "approve",
|
|
1732
|
+
inputs: [
|
|
1733
|
+
{ name: "spender", type: "address", internalType: "address" },
|
|
1734
|
+
{ name: "value", type: "uint256", internalType: "uint256" }
|
|
1735
|
+
],
|
|
1736
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1737
|
+
stateMutability: "nonpayable"
|
|
1738
|
+
},
|
|
1739
|
+
// ─── Functions: AccessControl ─────────────────────────────────────────────
|
|
1740
|
+
{
|
|
1741
|
+
type: "function",
|
|
1742
|
+
name: "grantRole",
|
|
1743
|
+
inputs: [
|
|
1744
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
1745
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
1746
|
+
],
|
|
1747
|
+
outputs: [],
|
|
1748
|
+
stateMutability: "nonpayable"
|
|
1749
|
+
},
|
|
1750
|
+
{
|
|
1751
|
+
type: "function",
|
|
1752
|
+
name: "revokeRole",
|
|
1753
|
+
inputs: [
|
|
1754
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
1755
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
1756
|
+
],
|
|
1757
|
+
outputs: [],
|
|
1758
|
+
stateMutability: "nonpayable"
|
|
1759
|
+
},
|
|
1760
|
+
{
|
|
1761
|
+
type: "function",
|
|
1762
|
+
name: "renounceRole",
|
|
1763
|
+
inputs: [
|
|
1764
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
1765
|
+
{ name: "callerConfirmation", type: "address", internalType: "address" }
|
|
1766
|
+
],
|
|
1767
|
+
outputs: [],
|
|
1768
|
+
stateMutability: "nonpayable"
|
|
1769
|
+
},
|
|
1770
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
1771
|
+
{
|
|
1772
|
+
type: "function",
|
|
1773
|
+
name: "balanceOf",
|
|
1774
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
1775
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1776
|
+
stateMutability: "view"
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
type: "function",
|
|
1780
|
+
name: "allowance",
|
|
1781
|
+
inputs: [
|
|
1782
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
1783
|
+
{ name: "spender", type: "address", internalType: "address" }
|
|
1784
|
+
],
|
|
1785
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1786
|
+
stateMutability: "view"
|
|
1787
|
+
},
|
|
1788
|
+
{
|
|
1789
|
+
type: "function",
|
|
1790
|
+
name: "totalSupply",
|
|
1791
|
+
inputs: [],
|
|
1792
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1793
|
+
stateMutability: "view"
|
|
1794
|
+
},
|
|
1795
|
+
{
|
|
1796
|
+
type: "function",
|
|
1797
|
+
name: "name",
|
|
1798
|
+
inputs: [],
|
|
1799
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
1800
|
+
stateMutability: "view"
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
type: "function",
|
|
1804
|
+
name: "symbol",
|
|
1805
|
+
inputs: [],
|
|
1806
|
+
outputs: [{ name: "", type: "string", internalType: "string" }],
|
|
1807
|
+
stateMutability: "view"
|
|
1808
|
+
},
|
|
1809
|
+
{
|
|
1810
|
+
type: "function",
|
|
1811
|
+
name: "decimals",
|
|
1812
|
+
inputs: [],
|
|
1813
|
+
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
|
|
1814
|
+
stateMutability: "view"
|
|
1815
|
+
},
|
|
1816
|
+
{
|
|
1817
|
+
type: "function",
|
|
1818
|
+
name: "paused",
|
|
1819
|
+
inputs: [],
|
|
1820
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1821
|
+
stateMutability: "view"
|
|
1822
|
+
},
|
|
1823
|
+
{
|
|
1824
|
+
type: "function",
|
|
1825
|
+
name: "MINTER_ROLE",
|
|
1826
|
+
inputs: [],
|
|
1827
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
1828
|
+
stateMutability: "view"
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
type: "function",
|
|
1832
|
+
name: "PAUSER_ROLE",
|
|
1833
|
+
inputs: [],
|
|
1834
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
1835
|
+
stateMutability: "view"
|
|
1836
|
+
},
|
|
1837
|
+
{
|
|
1838
|
+
type: "function",
|
|
1839
|
+
name: "DEFAULT_ADMIN_ROLE",
|
|
1840
|
+
inputs: [],
|
|
1841
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
1842
|
+
stateMutability: "view"
|
|
1843
|
+
},
|
|
1844
|
+
{
|
|
1845
|
+
type: "function",
|
|
1846
|
+
name: "hasRole",
|
|
1847
|
+
inputs: [
|
|
1848
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
1849
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
1850
|
+
],
|
|
1851
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1852
|
+
stateMutability: "view"
|
|
1853
|
+
},
|
|
1854
|
+
{
|
|
1855
|
+
type: "function",
|
|
1856
|
+
name: "getRoleAdmin",
|
|
1857
|
+
inputs: [{ name: "role", type: "bytes32", internalType: "bytes32" }],
|
|
1858
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
1859
|
+
stateMutability: "view"
|
|
1860
|
+
},
|
|
1861
|
+
{
|
|
1862
|
+
type: "function",
|
|
1863
|
+
name: "supportsInterface",
|
|
1864
|
+
inputs: [{ name: "interfaceId", type: "bytes4", internalType: "bytes4" }],
|
|
1865
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1866
|
+
stateMutability: "view"
|
|
1867
|
+
}
|
|
1868
|
+
];
|
|
1869
|
+
|
|
1870
|
+
// src/abis/PayoutEscrow.ts
|
|
1871
|
+
var PayoutEscrowABI = [
|
|
1872
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
1873
|
+
{ type: "error", name: "PayoutAlreadyExists", inputs: [] },
|
|
1874
|
+
{ type: "error", name: "PayoutNotFound", inputs: [] },
|
|
1875
|
+
{ type: "error", name: "NotAuthorizedSender", inputs: [] },
|
|
1876
|
+
{ type: "error", name: "NotPending", inputs: [] },
|
|
1877
|
+
{ type: "error", name: "NotExpiredYet", inputs: [] },
|
|
1878
|
+
{ type: "error", name: "NotRefundEligible", inputs: [] },
|
|
1879
|
+
{ type: "error", name: "PhoneHashMismatch", inputs: [] },
|
|
1880
|
+
{ type: "error", name: "NoMobileNFT", inputs: [] },
|
|
1881
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
1882
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
1883
|
+
{ type: "error", name: "ArrayLengthMismatch", inputs: [] },
|
|
1884
|
+
{ type: "error", name: "InvalidExpiry", inputs: [] },
|
|
1885
|
+
{ type: "error", name: "GatewayNotSet", inputs: [] },
|
|
1886
|
+
{ type: "error", name: "TokenNotSupportedByGateway", inputs: [] },
|
|
1887
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
1888
|
+
{
|
|
1889
|
+
type: "event",
|
|
1890
|
+
name: "PayoutCreated",
|
|
1891
|
+
inputs: [
|
|
1892
|
+
{ name: "payoutId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
1893
|
+
{ name: "sender", type: "address", indexed: true, internalType: "address" },
|
|
1894
|
+
{ name: "token", type: "address", indexed: false, internalType: "address" },
|
|
1895
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" },
|
|
1896
|
+
{ name: "phoneHash", type: "bytes32", indexed: true, internalType: "bytes32" }
|
|
1897
|
+
],
|
|
1898
|
+
anonymous: false
|
|
1899
|
+
},
|
|
1900
|
+
{
|
|
1901
|
+
type: "event",
|
|
1902
|
+
name: "PayoutClaimed",
|
|
1903
|
+
inputs: [
|
|
1904
|
+
{ name: "payoutId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
1905
|
+
{ name: "recipient", type: "address", indexed: true, internalType: "address" },
|
|
1906
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1907
|
+
],
|
|
1908
|
+
anonymous: false
|
|
1909
|
+
},
|
|
1910
|
+
{
|
|
1911
|
+
type: "event",
|
|
1912
|
+
name: "PayoutRefunded",
|
|
1913
|
+
inputs: [
|
|
1914
|
+
{ name: "payoutId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
1915
|
+
{ name: "sender", type: "address", indexed: true, internalType: "address" },
|
|
1916
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1917
|
+
],
|
|
1918
|
+
anonymous: false
|
|
1919
|
+
},
|
|
1920
|
+
{
|
|
1921
|
+
type: "event",
|
|
1922
|
+
name: "PayoutExpired",
|
|
1923
|
+
inputs: [
|
|
1924
|
+
{ name: "payoutId", type: "bytes32", indexed: true, internalType: "bytes32" }
|
|
1925
|
+
],
|
|
1926
|
+
anonymous: false
|
|
1927
|
+
},
|
|
1928
|
+
{
|
|
1929
|
+
type: "event",
|
|
1930
|
+
name: "AuthorizedSenderSet",
|
|
1931
|
+
inputs: [
|
|
1932
|
+
{ name: "sender", type: "address", indexed: true, internalType: "address" },
|
|
1933
|
+
{ name: "authorized", type: "bool", indexed: false, internalType: "bool" }
|
|
1934
|
+
],
|
|
1935
|
+
anonymous: false
|
|
1936
|
+
},
|
|
1937
|
+
{
|
|
1938
|
+
type: "event",
|
|
1939
|
+
name: "GatewaySet",
|
|
1940
|
+
inputs: [
|
|
1941
|
+
{ name: "gateway", type: "address", indexed: true, internalType: "address" }
|
|
1942
|
+
],
|
|
1943
|
+
anonymous: false
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
type: "event",
|
|
1947
|
+
name: "DefaultExpiryDurationSet",
|
|
1948
|
+
inputs: [
|
|
1949
|
+
{ name: "duration", type: "uint256", indexed: false, internalType: "uint256" }
|
|
1950
|
+
],
|
|
1951
|
+
anonymous: false
|
|
1952
|
+
},
|
|
1953
|
+
{
|
|
1954
|
+
type: "event",
|
|
1955
|
+
name: "OwnershipTransferred",
|
|
1956
|
+
inputs: [
|
|
1957
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
1958
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
1959
|
+
],
|
|
1960
|
+
anonymous: false
|
|
1961
|
+
},
|
|
1962
|
+
{
|
|
1963
|
+
type: "event",
|
|
1964
|
+
name: "Paused",
|
|
1965
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
1966
|
+
anonymous: false
|
|
1967
|
+
},
|
|
1968
|
+
{
|
|
1969
|
+
type: "event",
|
|
1970
|
+
name: "Unpaused",
|
|
1971
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
1972
|
+
anonymous: false
|
|
1973
|
+
},
|
|
1974
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
1975
|
+
{
|
|
1976
|
+
type: "constructor",
|
|
1977
|
+
inputs: [
|
|
1978
|
+
{ name: "_mobileNumberNFT", type: "address", internalType: "address" },
|
|
1979
|
+
{ name: "_gateway", type: "address", internalType: "address" },
|
|
1980
|
+
{ name: "_expiryDuration", type: "uint256", internalType: "uint256" }
|
|
1981
|
+
],
|
|
1982
|
+
stateMutability: "nonpayable"
|
|
1983
|
+
},
|
|
1984
|
+
// ─── Functions: Payout creation ───────────────────────────────────────────
|
|
1985
|
+
{
|
|
1986
|
+
type: "function",
|
|
1987
|
+
name: "createPayout",
|
|
1988
|
+
inputs: [
|
|
1989
|
+
{ name: "payoutId", type: "bytes32", internalType: "bytes32" },
|
|
1990
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
1991
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
1992
|
+
{ name: "phoneHash", type: "bytes32", internalType: "bytes32" },
|
|
1993
|
+
{ name: "expiresAt", type: "uint256", internalType: "uint256" }
|
|
1994
|
+
],
|
|
1995
|
+
outputs: [],
|
|
1996
|
+
stateMutability: "nonpayable"
|
|
1997
|
+
},
|
|
1998
|
+
{
|
|
1999
|
+
type: "function",
|
|
2000
|
+
name: "createBatchPayout",
|
|
2001
|
+
inputs: [
|
|
2002
|
+
{ name: "payoutIds", type: "bytes32[]", internalType: "bytes32[]" },
|
|
2003
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
2004
|
+
{ name: "amounts", type: "uint256[]", internalType: "uint256[]" },
|
|
2005
|
+
{ name: "phoneHashes", type: "bytes32[]", internalType: "bytes32[]" },
|
|
2006
|
+
{ name: "expiresAt", type: "uint256", internalType: "uint256" }
|
|
2007
|
+
],
|
|
2008
|
+
outputs: [],
|
|
2009
|
+
stateMutability: "nonpayable"
|
|
2010
|
+
},
|
|
2011
|
+
// ─── Functions: Claim ─────────────────────────────────────────────────────
|
|
2012
|
+
{
|
|
2013
|
+
type: "function",
|
|
2014
|
+
name: "claim",
|
|
2015
|
+
inputs: [
|
|
2016
|
+
{ name: "payoutId", type: "bytes32", internalType: "bytes32" }
|
|
2017
|
+
],
|
|
2018
|
+
outputs: [],
|
|
2019
|
+
stateMutability: "nonpayable"
|
|
2020
|
+
},
|
|
2021
|
+
{
|
|
2022
|
+
type: "function",
|
|
2023
|
+
name: "claimToMoMo",
|
|
2024
|
+
inputs: [
|
|
2025
|
+
{ name: "payoutId", type: "bytes32", internalType: "bytes32" },
|
|
2026
|
+
{ name: "phoneNumber", type: "string", internalType: "string" }
|
|
2027
|
+
],
|
|
2028
|
+
outputs: [],
|
|
2029
|
+
stateMutability: "nonpayable"
|
|
2030
|
+
},
|
|
2031
|
+
// ─── Functions: Refund ────────────────────────────────────────────────────
|
|
2032
|
+
{
|
|
2033
|
+
type: "function",
|
|
2034
|
+
name: "refund",
|
|
2035
|
+
inputs: [
|
|
2036
|
+
{ name: "payoutId", type: "bytes32", internalType: "bytes32" }
|
|
2037
|
+
],
|
|
2038
|
+
outputs: [],
|
|
2039
|
+
stateMutability: "nonpayable"
|
|
2040
|
+
},
|
|
2041
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
2042
|
+
{
|
|
2043
|
+
type: "function",
|
|
2044
|
+
name: "getPayout",
|
|
2045
|
+
inputs: [
|
|
2046
|
+
{ name: "payoutId", type: "bytes32", internalType: "bytes32" }
|
|
2047
|
+
],
|
|
2048
|
+
outputs: [
|
|
2049
|
+
{
|
|
2050
|
+
name: "",
|
|
2051
|
+
type: "tuple",
|
|
2052
|
+
internalType: "struct IPayoutEscrow.Payout",
|
|
2053
|
+
components: [
|
|
2054
|
+
{ name: "id", type: "bytes32", internalType: "bytes32" },
|
|
2055
|
+
{ name: "sender", type: "address", internalType: "address" },
|
|
2056
|
+
{ name: "recipient", type: "address", internalType: "address" },
|
|
2057
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
2058
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
2059
|
+
{ name: "phoneHash", type: "bytes32", internalType: "bytes32" },
|
|
2060
|
+
{ name: "status", type: "uint8", internalType: "enum IPayoutEscrow.PayoutStatus" },
|
|
2061
|
+
{ name: "expiresAt", type: "uint256", internalType: "uint256" },
|
|
2062
|
+
{ name: "createdAt", type: "uint256", internalType: "uint256" },
|
|
2063
|
+
{ name: "claimedAt", type: "uint256", internalType: "uint256" }
|
|
2064
|
+
]
|
|
2065
|
+
}
|
|
2066
|
+
],
|
|
2067
|
+
stateMutability: "view"
|
|
2068
|
+
},
|
|
2069
|
+
{
|
|
2070
|
+
type: "function",
|
|
2071
|
+
name: "getPayoutsForPhone",
|
|
2072
|
+
inputs: [
|
|
2073
|
+
{ name: "phoneHash", type: "bytes32", internalType: "bytes32" }
|
|
2074
|
+
],
|
|
2075
|
+
outputs: [
|
|
2076
|
+
{ name: "", type: "bytes32[]", internalType: "bytes32[]" }
|
|
2077
|
+
],
|
|
2078
|
+
stateMutability: "view"
|
|
2079
|
+
},
|
|
2080
|
+
{
|
|
2081
|
+
type: "function",
|
|
2082
|
+
name: "getPayoutsByStatus",
|
|
2083
|
+
inputs: [
|
|
2084
|
+
{ name: "phoneHash", type: "bytes32", internalType: "bytes32" },
|
|
2085
|
+
{ name: "status", type: "uint8", internalType: "enum IPayoutEscrow.PayoutStatus" }
|
|
2086
|
+
],
|
|
2087
|
+
outputs: [
|
|
2088
|
+
{ name: "", type: "bytes32[]", internalType: "bytes32[]" }
|
|
2089
|
+
],
|
|
2090
|
+
stateMutability: "view"
|
|
2091
|
+
},
|
|
2092
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
2093
|
+
{
|
|
2094
|
+
type: "function",
|
|
2095
|
+
name: "setAuthorizedSender",
|
|
2096
|
+
inputs: [
|
|
2097
|
+
{ name: "sender", type: "address", internalType: "address" },
|
|
2098
|
+
{ name: "authorized", type: "bool", internalType: "bool" }
|
|
2099
|
+
],
|
|
2100
|
+
outputs: [],
|
|
2101
|
+
stateMutability: "nonpayable"
|
|
2102
|
+
},
|
|
2103
|
+
{
|
|
2104
|
+
type: "function",
|
|
2105
|
+
name: "setDefaultExpiryDuration",
|
|
2106
|
+
inputs: [
|
|
2107
|
+
{ name: "duration", type: "uint256", internalType: "uint256" }
|
|
2108
|
+
],
|
|
2109
|
+
outputs: [],
|
|
2110
|
+
stateMutability: "nonpayable"
|
|
2111
|
+
},
|
|
2112
|
+
{
|
|
2113
|
+
type: "function",
|
|
2114
|
+
name: "setGateway",
|
|
2115
|
+
inputs: [
|
|
2116
|
+
{ name: "_gateway", type: "address", internalType: "address" }
|
|
2117
|
+
],
|
|
2118
|
+
outputs: [],
|
|
2119
|
+
stateMutability: "nonpayable"
|
|
2120
|
+
},
|
|
2121
|
+
{
|
|
2122
|
+
type: "function",
|
|
2123
|
+
name: "pause",
|
|
2124
|
+
inputs: [],
|
|
2125
|
+
outputs: [],
|
|
2126
|
+
stateMutability: "nonpayable"
|
|
2127
|
+
},
|
|
2128
|
+
{
|
|
2129
|
+
type: "function",
|
|
2130
|
+
name: "unpause",
|
|
2131
|
+
inputs: [],
|
|
2132
|
+
outputs: [],
|
|
2133
|
+
stateMutability: "nonpayable"
|
|
2134
|
+
},
|
|
2135
|
+
{
|
|
2136
|
+
type: "function",
|
|
2137
|
+
name: "transferOwnership",
|
|
2138
|
+
inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
|
|
2139
|
+
outputs: [],
|
|
2140
|
+
stateMutability: "nonpayable"
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
type: "function",
|
|
2144
|
+
name: "renounceOwnership",
|
|
2145
|
+
inputs: [],
|
|
2146
|
+
outputs: [],
|
|
2147
|
+
stateMutability: "nonpayable"
|
|
2148
|
+
},
|
|
2149
|
+
// ─── Functions: State vars ────────────────────────────────────────────────
|
|
2150
|
+
{
|
|
2151
|
+
type: "function",
|
|
2152
|
+
name: "mobileNumberNFT",
|
|
2153
|
+
inputs: [],
|
|
2154
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
2155
|
+
stateMutability: "view"
|
|
2156
|
+
},
|
|
2157
|
+
{
|
|
2158
|
+
type: "function",
|
|
2159
|
+
name: "gateway",
|
|
2160
|
+
inputs: [],
|
|
2161
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
2162
|
+
stateMutability: "view"
|
|
2163
|
+
},
|
|
2164
|
+
{
|
|
2165
|
+
type: "function",
|
|
2166
|
+
name: "defaultExpiryDuration",
|
|
2167
|
+
inputs: [],
|
|
2168
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
2169
|
+
stateMutability: "view"
|
|
2170
|
+
},
|
|
2171
|
+
{
|
|
2172
|
+
type: "function",
|
|
2173
|
+
name: "authorizedSenders",
|
|
2174
|
+
inputs: [{ name: "sender", type: "address", internalType: "address" }],
|
|
2175
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
2176
|
+
stateMutability: "view"
|
|
2177
|
+
},
|
|
2178
|
+
{
|
|
2179
|
+
type: "function",
|
|
2180
|
+
name: "owner",
|
|
2181
|
+
inputs: [],
|
|
2182
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
2183
|
+
stateMutability: "view"
|
|
2184
|
+
},
|
|
2185
|
+
{
|
|
2186
|
+
type: "function",
|
|
2187
|
+
name: "paused",
|
|
2188
|
+
inputs: [],
|
|
2189
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
2190
|
+
stateMutability: "view"
|
|
2191
|
+
}
|
|
2192
|
+
];
|
|
2193
|
+
|
|
2194
|
+
// src/abis/P2PExchange.ts
|
|
2195
|
+
var P2PExchangeABI = [
|
|
2196
|
+
// ─── Custom Errors ────────────────────────────────────────────────────────
|
|
2197
|
+
{ type: "error", name: "OrderAlreadyExists", inputs: [] },
|
|
2198
|
+
{ type: "error", name: "OrderNotFound", inputs: [] },
|
|
2199
|
+
{ type: "error", name: "NotMaker", inputs: [] },
|
|
2200
|
+
{ type: "error", name: "NotParty", inputs: [] },
|
|
2201
|
+
{ type: "error", name: "NotDisputeResolver", inputs: [] },
|
|
2202
|
+
{ type: "error", name: "OrderNotOpen", inputs: [] },
|
|
2203
|
+
{ type: "error", name: "OrderNotLocked", inputs: [] },
|
|
2204
|
+
{ type: "error", name: "OrderNotDisputed", inputs: [] },
|
|
2205
|
+
{ type: "error", name: "AlreadyTaken", inputs: [] },
|
|
2206
|
+
{ type: "error", name: "SelfTake", inputs: [] },
|
|
2207
|
+
{ type: "error", name: "ZeroAddress", inputs: [] },
|
|
2208
|
+
{ type: "error", name: "ZeroAmount", inputs: [] },
|
|
2209
|
+
{ type: "error", name: "ZeroExpiryDuration", inputs: [] },
|
|
2210
|
+
{ type: "error", name: "InvalidWinner", inputs: [] },
|
|
2211
|
+
// ─── Events ───────────────────────────────────────────────────────────────
|
|
2212
|
+
{
|
|
2213
|
+
type: "event",
|
|
2214
|
+
name: "OrderCreated",
|
|
2215
|
+
inputs: [
|
|
2216
|
+
{ name: "orderId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
2217
|
+
{ name: "maker", type: "address", indexed: true, internalType: "address" },
|
|
2218
|
+
{ name: "token", type: "address", indexed: false, internalType: "address" },
|
|
2219
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" },
|
|
2220
|
+
{ name: "paymentReference", type: "string", indexed: false, internalType: "string" },
|
|
2221
|
+
{ name: "exchangePlatform", type: "string", indexed: false, internalType: "string" }
|
|
2222
|
+
],
|
|
2223
|
+
anonymous: false
|
|
2224
|
+
},
|
|
2225
|
+
{
|
|
2226
|
+
type: "event",
|
|
2227
|
+
name: "OrderTaken",
|
|
2228
|
+
inputs: [
|
|
2229
|
+
{ name: "orderId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
2230
|
+
{ name: "taker", type: "address", indexed: true, internalType: "address" }
|
|
2231
|
+
],
|
|
2232
|
+
anonymous: false
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
type: "event",
|
|
2236
|
+
name: "OrderCompleted",
|
|
2237
|
+
inputs: [
|
|
2238
|
+
{ name: "orderId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
2239
|
+
{ name: "taker", type: "address", indexed: true, internalType: "address" },
|
|
2240
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
2241
|
+
],
|
|
2242
|
+
anonymous: false
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
type: "event",
|
|
2246
|
+
name: "OrderCancelled",
|
|
2247
|
+
inputs: [
|
|
2248
|
+
{ name: "orderId", type: "bytes32", indexed: true, internalType: "bytes32" }
|
|
2249
|
+
],
|
|
2250
|
+
anonymous: false
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
type: "event",
|
|
2254
|
+
name: "OrderDisputed",
|
|
2255
|
+
inputs: [
|
|
2256
|
+
{ name: "orderId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
2257
|
+
{ name: "disputedBy", type: "address", indexed: true, internalType: "address" }
|
|
2258
|
+
],
|
|
2259
|
+
anonymous: false
|
|
2260
|
+
},
|
|
2261
|
+
{
|
|
2262
|
+
type: "event",
|
|
2263
|
+
name: "DisputeResolved",
|
|
2264
|
+
inputs: [
|
|
2265
|
+
{ name: "orderId", type: "bytes32", indexed: true, internalType: "bytes32" },
|
|
2266
|
+
{ name: "winner", type: "address", indexed: true, internalType: "address" },
|
|
2267
|
+
{ name: "amount", type: "uint256", indexed: false, internalType: "uint256" }
|
|
2268
|
+
],
|
|
2269
|
+
anonymous: false
|
|
2270
|
+
},
|
|
2271
|
+
{
|
|
2272
|
+
type: "event",
|
|
2273
|
+
name: "DisputeResolverSet",
|
|
2274
|
+
inputs: [
|
|
2275
|
+
{ name: "resolver", type: "address", indexed: true, internalType: "address" }
|
|
2276
|
+
],
|
|
2277
|
+
anonymous: false
|
|
2278
|
+
},
|
|
2279
|
+
{
|
|
2280
|
+
type: "event",
|
|
2281
|
+
name: "OwnershipTransferred",
|
|
2282
|
+
inputs: [
|
|
2283
|
+
{ name: "previousOwner", type: "address", indexed: true, internalType: "address" },
|
|
2284
|
+
{ name: "newOwner", type: "address", indexed: true, internalType: "address" }
|
|
2285
|
+
],
|
|
2286
|
+
anonymous: false
|
|
2287
|
+
},
|
|
2288
|
+
{
|
|
2289
|
+
type: "event",
|
|
2290
|
+
name: "Paused",
|
|
2291
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
2292
|
+
anonymous: false
|
|
2293
|
+
},
|
|
2294
|
+
{
|
|
2295
|
+
type: "event",
|
|
2296
|
+
name: "Unpaused",
|
|
2297
|
+
inputs: [{ name: "account", type: "address", indexed: false, internalType: "address" }],
|
|
2298
|
+
anonymous: false
|
|
2299
|
+
},
|
|
2300
|
+
// ─── Constructor ──────────────────────────────────────────────────────────
|
|
2301
|
+
{
|
|
2302
|
+
type: "constructor",
|
|
2303
|
+
inputs: [
|
|
2304
|
+
{ name: "_disputeResolver", type: "address", internalType: "address" }
|
|
2305
|
+
],
|
|
2306
|
+
stateMutability: "nonpayable"
|
|
2307
|
+
},
|
|
2308
|
+
// ─── Functions: Order lifecycle ───────────────────────────────────────────
|
|
2309
|
+
{
|
|
2310
|
+
type: "function",
|
|
2311
|
+
name: "createOrder",
|
|
2312
|
+
inputs: [
|
|
2313
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" },
|
|
2314
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
2315
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
2316
|
+
{ name: "paymentReference", type: "string", internalType: "string" },
|
|
2317
|
+
{ name: "exchangePlatform", type: "string", internalType: "string" },
|
|
2318
|
+
{ name: "expiryDuration", type: "uint256", internalType: "uint256" }
|
|
2319
|
+
],
|
|
2320
|
+
outputs: [],
|
|
2321
|
+
stateMutability: "nonpayable"
|
|
2322
|
+
},
|
|
2323
|
+
{
|
|
2324
|
+
type: "function",
|
|
2325
|
+
name: "takeOrder",
|
|
2326
|
+
inputs: [
|
|
2327
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" }
|
|
2328
|
+
],
|
|
2329
|
+
outputs: [],
|
|
2330
|
+
stateMutability: "nonpayable"
|
|
2331
|
+
},
|
|
2332
|
+
{
|
|
2333
|
+
type: "function",
|
|
2334
|
+
name: "confirmPayment",
|
|
2335
|
+
inputs: [
|
|
2336
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" }
|
|
2337
|
+
],
|
|
2338
|
+
outputs: [],
|
|
2339
|
+
stateMutability: "nonpayable"
|
|
2340
|
+
},
|
|
2341
|
+
{
|
|
2342
|
+
type: "function",
|
|
2343
|
+
name: "cancelOrder",
|
|
2344
|
+
inputs: [
|
|
2345
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" }
|
|
2346
|
+
],
|
|
2347
|
+
outputs: [],
|
|
2348
|
+
stateMutability: "nonpayable"
|
|
2349
|
+
},
|
|
2350
|
+
{
|
|
2351
|
+
type: "function",
|
|
2352
|
+
name: "disputeOrder",
|
|
2353
|
+
inputs: [
|
|
2354
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" }
|
|
2355
|
+
],
|
|
2356
|
+
outputs: [],
|
|
2357
|
+
stateMutability: "nonpayable"
|
|
2358
|
+
},
|
|
2359
|
+
{
|
|
2360
|
+
type: "function",
|
|
2361
|
+
name: "resolveDispute",
|
|
2362
|
+
inputs: [
|
|
2363
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" },
|
|
2364
|
+
{ name: "winner", type: "address", internalType: "address" }
|
|
2365
|
+
],
|
|
2366
|
+
outputs: [],
|
|
2367
|
+
stateMutability: "nonpayable"
|
|
2368
|
+
},
|
|
2369
|
+
// ─── Functions: View ──────────────────────────────────────────────────────
|
|
2370
|
+
{
|
|
2371
|
+
type: "function",
|
|
2372
|
+
name: "getOrder",
|
|
2373
|
+
inputs: [
|
|
2374
|
+
{ name: "orderId", type: "bytes32", internalType: "bytes32" }
|
|
2375
|
+
],
|
|
2376
|
+
outputs: [
|
|
2377
|
+
{
|
|
2378
|
+
name: "",
|
|
2379
|
+
type: "tuple",
|
|
2380
|
+
internalType: "struct IP2PExchange.P2POrder",
|
|
2381
|
+
components: [
|
|
2382
|
+
{ name: "id", type: "bytes32", internalType: "bytes32" },
|
|
2383
|
+
{ name: "maker", type: "address", internalType: "address" },
|
|
2384
|
+
{ name: "taker", type: "address", internalType: "address" },
|
|
2385
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
2386
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
2387
|
+
{ name: "paymentReference", type: "string", internalType: "string" },
|
|
2388
|
+
{ name: "exchangePlatform", type: "string", internalType: "string" },
|
|
2389
|
+
{ name: "status", type: "uint8", internalType: "enum IP2PExchange.OrderStatus" },
|
|
2390
|
+
{ name: "createdAt", type: "uint256", internalType: "uint256" },
|
|
2391
|
+
{ name: "lockedAt", type: "uint256", internalType: "uint256" },
|
|
2392
|
+
{ name: "completedAt", type: "uint256", internalType: "uint256" },
|
|
2393
|
+
{ name: "expiryDuration", type: "uint256", internalType: "uint256" }
|
|
2394
|
+
]
|
|
2395
|
+
}
|
|
2396
|
+
],
|
|
2397
|
+
stateMutability: "view"
|
|
2398
|
+
},
|
|
2399
|
+
{
|
|
2400
|
+
type: "function",
|
|
2401
|
+
name: "getUserOrders",
|
|
2402
|
+
inputs: [
|
|
2403
|
+
{ name: "user", type: "address", internalType: "address" }
|
|
2404
|
+
],
|
|
2405
|
+
outputs: [
|
|
2406
|
+
{ name: "", type: "bytes32[]", internalType: "bytes32[]" }
|
|
2407
|
+
],
|
|
2408
|
+
stateMutability: "view"
|
|
2409
|
+
},
|
|
2410
|
+
{
|
|
2411
|
+
type: "function",
|
|
2412
|
+
name: "getOpenOrders",
|
|
2413
|
+
inputs: [
|
|
2414
|
+
{ name: "limit", type: "uint256", internalType: "uint256" }
|
|
2415
|
+
],
|
|
2416
|
+
outputs: [
|
|
2417
|
+
{ name: "", type: "bytes32[]", internalType: "bytes32[]" }
|
|
2418
|
+
],
|
|
2419
|
+
stateMutability: "view"
|
|
2420
|
+
},
|
|
2421
|
+
// ─── Functions: Admin ─────────────────────────────────────────────────────
|
|
2422
|
+
{
|
|
2423
|
+
type: "function",
|
|
2424
|
+
name: "setDisputeResolver",
|
|
2425
|
+
inputs: [
|
|
2426
|
+
{ name: "resolver", type: "address", internalType: "address" }
|
|
2427
|
+
],
|
|
2428
|
+
outputs: [],
|
|
2429
|
+
stateMutability: "nonpayable"
|
|
2430
|
+
},
|
|
2431
|
+
{
|
|
2432
|
+
type: "function",
|
|
2433
|
+
name: "pause",
|
|
2434
|
+
inputs: [],
|
|
2435
|
+
outputs: [],
|
|
2436
|
+
stateMutability: "nonpayable"
|
|
2437
|
+
},
|
|
2438
|
+
{
|
|
2439
|
+
type: "function",
|
|
2440
|
+
name: "unpause",
|
|
2441
|
+
inputs: [],
|
|
2442
|
+
outputs: [],
|
|
2443
|
+
stateMutability: "nonpayable"
|
|
2444
|
+
},
|
|
2445
|
+
{
|
|
2446
|
+
type: "function",
|
|
2447
|
+
name: "transferOwnership",
|
|
2448
|
+
inputs: [{ name: "newOwner", type: "address", internalType: "address" }],
|
|
2449
|
+
outputs: [],
|
|
2450
|
+
stateMutability: "nonpayable"
|
|
2451
|
+
},
|
|
2452
|
+
{
|
|
2453
|
+
type: "function",
|
|
2454
|
+
name: "renounceOwnership",
|
|
2455
|
+
inputs: [],
|
|
2456
|
+
outputs: [],
|
|
2457
|
+
stateMutability: "nonpayable"
|
|
2458
|
+
},
|
|
2459
|
+
// ─── Functions: State vars ────────────────────────────────────────────────
|
|
2460
|
+
{
|
|
2461
|
+
type: "function",
|
|
2462
|
+
name: "disputeResolver",
|
|
2463
|
+
inputs: [],
|
|
2464
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
2465
|
+
stateMutability: "view"
|
|
2466
|
+
},
|
|
2467
|
+
{
|
|
2468
|
+
type: "function",
|
|
2469
|
+
name: "owner",
|
|
2470
|
+
inputs: [],
|
|
2471
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
2472
|
+
stateMutability: "view"
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
type: "function",
|
|
2476
|
+
name: "paused",
|
|
2477
|
+
inputs: [],
|
|
2478
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
2479
|
+
stateMutability: "view"
|
|
2480
|
+
}
|
|
2481
|
+
];
|
|
2482
|
+
|
|
2483
|
+
// src/resources/identity.ts
|
|
2484
|
+
function wrapError(err, contractAddress) {
|
|
2485
|
+
if (err instanceof types.FiatsendError) return err;
|
|
2486
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2487
|
+
if (message.includes("AlreadyRegistered")) {
|
|
2488
|
+
return new types.FiatsendError("Address already has a registered MobileNumber NFT", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2489
|
+
}
|
|
2490
|
+
if (message.includes("PhoneAlreadyRegistered")) {
|
|
2491
|
+
return new types.FiatsendError("Phone number is already registered to another address", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2492
|
+
}
|
|
2493
|
+
if (message.includes("NotAuthorized")) {
|
|
2494
|
+
return new types.FiatsendError("Caller is not an authorized minter", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2495
|
+
}
|
|
2496
|
+
if (message.includes("SignatureExpired")) {
|
|
2497
|
+
return new types.FiatsendError("Gasless registration signature has expired", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2498
|
+
}
|
|
2499
|
+
if (message.includes("InvalidSignature")) {
|
|
2500
|
+
return new types.FiatsendError("Invalid EIP-712 signature for gasless registration", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2501
|
+
}
|
|
2502
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2503
|
+
}
|
|
2504
|
+
var IdentityResource = class {
|
|
2505
|
+
publicClient;
|
|
2506
|
+
walletClient;
|
|
2507
|
+
contractAddress;
|
|
2508
|
+
constructor(params) {
|
|
2509
|
+
this.publicClient = params.publicClient;
|
|
2510
|
+
this.walletClient = params.walletClient;
|
|
2511
|
+
this.contractAddress = params.contractAddress;
|
|
2512
|
+
}
|
|
2513
|
+
get readContract() {
|
|
2514
|
+
return viem.getContract({
|
|
2515
|
+
address: this.contractAddress,
|
|
2516
|
+
abi: MobileNumberNFTABI,
|
|
2517
|
+
client: this.publicClient
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
requireWallet() {
|
|
2521
|
+
if (!this.walletClient) {
|
|
2522
|
+
throw new types.FiatsendError(
|
|
2523
|
+
"A walletClient is required for write operations. Pass one to FiatsendClient.",
|
|
2524
|
+
types.FiatsendErrorCode.UNAUTHORIZED
|
|
2525
|
+
);
|
|
2526
|
+
}
|
|
2527
|
+
return this.walletClient;
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* Mints a soulbound MobileNumber NFT for the connected wallet.
|
|
2531
|
+
*
|
|
2532
|
+
* @param params - Encrypted phone bytes and ISO country code
|
|
2533
|
+
* @returns Transaction result with hash and wait() function
|
|
2534
|
+
*/
|
|
2535
|
+
async register(params) {
|
|
2536
|
+
try {
|
|
2537
|
+
const wallet = this.requireWallet();
|
|
2538
|
+
const hash = await wallet.writeContract({
|
|
2539
|
+
address: this.contractAddress,
|
|
2540
|
+
abi: MobileNumberNFTABI,
|
|
2541
|
+
functionName: "registerMobile",
|
|
2542
|
+
args: [params.encryptedPhone, params.countryCode],
|
|
2543
|
+
account: wallet.account,
|
|
2544
|
+
chain: wallet.chain ?? null
|
|
2545
|
+
});
|
|
2546
|
+
return {
|
|
2547
|
+
hash,
|
|
2548
|
+
wait: async () => {
|
|
2549
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
2550
|
+
return {
|
|
2551
|
+
hash: receipt.transactionHash,
|
|
2552
|
+
status: receipt.status,
|
|
2553
|
+
blockNumber: receipt.blockNumber,
|
|
2554
|
+
gasUsed: receipt.gasUsed
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
} catch (err) {
|
|
2559
|
+
throw wrapError(err, this.contractAddress);
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
/**
|
|
2563
|
+
* Gasless NFT mint: the authorized minter submits the transaction on behalf
|
|
2564
|
+
* of the user. The user must have previously signed the EIP-712 typed data.
|
|
2565
|
+
*
|
|
2566
|
+
* @param params - User address, encrypted phone, country code, deadline, and signature
|
|
2567
|
+
* @returns Transaction result with hash and wait() function
|
|
2568
|
+
*/
|
|
2569
|
+
async registerWithSignature(params) {
|
|
2570
|
+
try {
|
|
2571
|
+
const wallet = this.requireWallet();
|
|
2572
|
+
const hash = await wallet.writeContract({
|
|
2573
|
+
address: this.contractAddress,
|
|
2574
|
+
abi: MobileNumberNFTABI,
|
|
2575
|
+
functionName: "registerMobileWithSignature",
|
|
2576
|
+
args: [
|
|
2577
|
+
params.user,
|
|
2578
|
+
params.encryptedPhone,
|
|
2579
|
+
params.countryCode,
|
|
2580
|
+
params.deadline,
|
|
2581
|
+
params.signature
|
|
2582
|
+
],
|
|
2583
|
+
account: wallet.account,
|
|
2584
|
+
chain: wallet.chain ?? null
|
|
2585
|
+
});
|
|
2586
|
+
return {
|
|
2587
|
+
hash,
|
|
2588
|
+
wait: async () => {
|
|
2589
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
2590
|
+
return {
|
|
2591
|
+
hash: receipt.transactionHash,
|
|
2592
|
+
status: receipt.status,
|
|
2593
|
+
blockNumber: receipt.blockNumber,
|
|
2594
|
+
gasUsed: receipt.gasUsed
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
};
|
|
2598
|
+
} catch (err) {
|
|
2599
|
+
throw wrapError(err, this.contractAddress);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
/**
|
|
2603
|
+
* Returns the MobileNumber NFT data for an address, or null if not registered.
|
|
2604
|
+
*
|
|
2605
|
+
* @param address - Wallet address to query
|
|
2606
|
+
*/
|
|
2607
|
+
async getNFT(address) {
|
|
2608
|
+
try {
|
|
2609
|
+
const contract = this.readContract;
|
|
2610
|
+
const tokenId = await contract.read.getTokenId([address]);
|
|
2611
|
+
if (tokenId === 0n) return null;
|
|
2612
|
+
const [countryCode, kycLevel, encryptedPhone] = await Promise.all([
|
|
2613
|
+
contract.read.getCountryCode([tokenId]),
|
|
2614
|
+
contract.read.getKYCLevel([tokenId]),
|
|
2615
|
+
contract.read.getEncryptedPhone([tokenId])
|
|
2616
|
+
]);
|
|
2617
|
+
return {
|
|
2618
|
+
tokenId,
|
|
2619
|
+
owner: address,
|
|
2620
|
+
encryptedPhone,
|
|
2621
|
+
countryCode,
|
|
2622
|
+
kycLevel: Math.min(kycLevel, 2)
|
|
2623
|
+
};
|
|
2624
|
+
} catch (err) {
|
|
2625
|
+
throw wrapError(err, this.contractAddress);
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
/**
|
|
2629
|
+
* Returns the KYC level for an address (0 if no NFT).
|
|
2630
|
+
*
|
|
2631
|
+
* @param address - Wallet address to query
|
|
2632
|
+
*/
|
|
2633
|
+
async getKYCLevel(address) {
|
|
2634
|
+
try {
|
|
2635
|
+
const level = await this.readContract.read.getKYCLevelByAddress([address]);
|
|
2636
|
+
return Math.min(level, 2);
|
|
2637
|
+
} catch (err) {
|
|
2638
|
+
throw wrapError(err, this.contractAddress);
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Resolves an encrypted phone hash to the owner address.
|
|
2643
|
+
*
|
|
2644
|
+
* @param encryptedPhone - Encrypted phone bytes (0x-prefixed)
|
|
2645
|
+
* @returns Owner address or null if not registered
|
|
2646
|
+
*/
|
|
2647
|
+
async getOwnerByPhone(encryptedPhone) {
|
|
2648
|
+
try {
|
|
2649
|
+
const contract = this.readContract;
|
|
2650
|
+
const tokenId = await contract.read.getTokenIdByPhone([encryptedPhone]);
|
|
2651
|
+
if (tokenId === 0n) return null;
|
|
2652
|
+
const owner = await this.publicClient.readContract({
|
|
2653
|
+
address: this.contractAddress,
|
|
2654
|
+
abi: MobileNumberNFTABI,
|
|
2655
|
+
functionName: "ownerOf",
|
|
2656
|
+
args: [tokenId]
|
|
2657
|
+
});
|
|
2658
|
+
return owner;
|
|
2659
|
+
} catch (err) {
|
|
2660
|
+
throw wrapError(err, this.contractAddress);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
/**
|
|
2664
|
+
* Returns the token ID for an address (null if not registered).
|
|
2665
|
+
*
|
|
2666
|
+
* @param address - Wallet address
|
|
2667
|
+
*/
|
|
2668
|
+
async getTokenId(address) {
|
|
2669
|
+
try {
|
|
2670
|
+
const tokenId = await this.readContract.read.getTokenId([address]);
|
|
2671
|
+
return tokenId === 0n ? null : tokenId;
|
|
2672
|
+
} catch (err) {
|
|
2673
|
+
throw wrapError(err, this.contractAddress);
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
/**
|
|
2677
|
+
* Returns the user's nonce for EIP-712 replay protection.
|
|
2678
|
+
*
|
|
2679
|
+
* @param address - Wallet address
|
|
2680
|
+
*/
|
|
2681
|
+
async getNonce(address) {
|
|
2682
|
+
try {
|
|
2683
|
+
return await this.readContract.read.nonces([address]);
|
|
2684
|
+
} catch (err) {
|
|
2685
|
+
throw wrapError(err, this.contractAddress);
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
function wrapError2(err, contractAddress) {
|
|
2690
|
+
if (err instanceof types.FiatsendError) return err;
|
|
2691
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2692
|
+
if (message.includes("TokenNotSupported")) {
|
|
2693
|
+
return new types.FiatsendError("Token is not supported by the gateway", types.FiatsendErrorCode.TOKEN_NOT_SUPPORTED, { contractAddress });
|
|
2694
|
+
}
|
|
2695
|
+
if (message.includes("NoMobileNFT")) {
|
|
2696
|
+
return new types.FiatsendError("User does not have a MobileNumber NFT \u2014 please register first", types.FiatsendErrorCode.NO_NFT, { contractAddress });
|
|
2697
|
+
}
|
|
2698
|
+
if (message.includes("KYCRequired")) {
|
|
2699
|
+
return new types.FiatsendError("KYC verification is required for amounts above the threshold", types.FiatsendErrorCode.KYC_REQUIRED, { contractAddress });
|
|
2700
|
+
}
|
|
2701
|
+
if (message.includes("BelowMinimum")) {
|
|
2702
|
+
return new types.FiatsendError("Amount is below the minimum withdrawal amount", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
2703
|
+
}
|
|
2704
|
+
if (message.includes("DailyLimitExceeded")) {
|
|
2705
|
+
return new types.FiatsendError("Daily withdrawal limit exceeded", types.FiatsendErrorCode.DAILY_LIMIT_EXCEEDED, { contractAddress });
|
|
2706
|
+
}
|
|
2707
|
+
if (message.includes("Paused") || message.includes("EnforcedPause")) {
|
|
2708
|
+
return new types.FiatsendError("Gateway is currently paused", types.FiatsendErrorCode.CONTRACT_PAUSED, { contractAddress });
|
|
2709
|
+
}
|
|
2710
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2711
|
+
}
|
|
2712
|
+
var GatewayResource = class {
|
|
2713
|
+
publicClient;
|
|
2714
|
+
walletClient;
|
|
2715
|
+
contractAddress;
|
|
2716
|
+
constructor(params) {
|
|
2717
|
+
this.publicClient = params.publicClient;
|
|
2718
|
+
this.walletClient = params.walletClient;
|
|
2719
|
+
this.contractAddress = params.contractAddress;
|
|
2720
|
+
}
|
|
2721
|
+
get readContract() {
|
|
2722
|
+
return viem.getContract({
|
|
2723
|
+
address: this.contractAddress,
|
|
2724
|
+
abi: FiatsendGatewayABI,
|
|
2725
|
+
client: this.publicClient
|
|
2726
|
+
});
|
|
2727
|
+
}
|
|
2728
|
+
requireWallet() {
|
|
2729
|
+
if (!this.walletClient) {
|
|
2730
|
+
throw new types.FiatsendError(
|
|
2731
|
+
"A walletClient is required for write operations.",
|
|
2732
|
+
types.FiatsendErrorCode.UNAUTHORIZED
|
|
2733
|
+
);
|
|
2734
|
+
}
|
|
2735
|
+
return this.walletClient;
|
|
2736
|
+
}
|
|
2737
|
+
/**
|
|
2738
|
+
* Initiates an offramp: converts a supported stablecoin to a mobile money payout.
|
|
2739
|
+
*
|
|
2740
|
+
* The user must:
|
|
2741
|
+
* 1. Have a MobileNumber NFT
|
|
2742
|
+
* 2. Pass KYC (if amount >= threshold)
|
|
2743
|
+
* 3. Have approved the gateway to spend `params.amount` of `params.token`
|
|
2744
|
+
*
|
|
2745
|
+
* @param params - Token, amount, and destination phone number
|
|
2746
|
+
* @returns Offramp result including the withdrawal ID and fees
|
|
2747
|
+
*/
|
|
2748
|
+
async offramp(params) {
|
|
2749
|
+
utils.validateOfframpParams(params);
|
|
2750
|
+
try {
|
|
2751
|
+
const [feeRate, minWithdraw] = await Promise.all([
|
|
2752
|
+
this.readContract.read.protocolFeeRate(),
|
|
2753
|
+
this.readContract.read.minWithdrawAmount()
|
|
2754
|
+
]);
|
|
2755
|
+
if (params.amount < minWithdraw) {
|
|
2756
|
+
throw new types.FiatsendError(
|
|
2757
|
+
`Amount ${params.amount} is below the minimum withdrawal amount of ${minWithdraw}`,
|
|
2758
|
+
types.FiatsendErrorCode.BELOW_MINIMUM,
|
|
2759
|
+
{ contractAddress: this.contractAddress }
|
|
2760
|
+
);
|
|
2761
|
+
}
|
|
2762
|
+
const fee = params.amount * feeRate / 10000n;
|
|
2763
|
+
const netAmount = params.amount - fee;
|
|
2764
|
+
const wallet = this.requireWallet();
|
|
2765
|
+
const hash = await wallet.writeContract({
|
|
2766
|
+
address: this.contractAddress,
|
|
2767
|
+
abi: FiatsendGatewayABI,
|
|
2768
|
+
functionName: "offramp",
|
|
2769
|
+
args: [params.token, params.amount, params.phoneNumber],
|
|
2770
|
+
account: wallet.account,
|
|
2771
|
+
chain: wallet.chain ?? null
|
|
2772
|
+
});
|
|
2773
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
2774
|
+
let withdrawalId = 0n;
|
|
2775
|
+
for (const log of receipt.logs) {
|
|
2776
|
+
if (log.topics.length >= 2) {
|
|
2777
|
+
const possibleId = BigInt(log.topics[1] ?? "0x0");
|
|
2778
|
+
if (possibleId > 0n) {
|
|
2779
|
+
withdrawalId = possibleId;
|
|
2780
|
+
break;
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
return {
|
|
2785
|
+
withdrawalId,
|
|
2786
|
+
amount: params.amount,
|
|
2787
|
+
fee,
|
|
2788
|
+
netAmount,
|
|
2789
|
+
hash
|
|
2790
|
+
};
|
|
2791
|
+
} catch (err) {
|
|
2792
|
+
if (err instanceof types.FiatsendError) throw err;
|
|
2793
|
+
throw wrapError2(err, this.contractAddress);
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* Returns the conversion rate for a supported token.
|
|
2798
|
+
*
|
|
2799
|
+
* @param token - Token address
|
|
2800
|
+
* @returns Scaled conversion rate as stored in the contract
|
|
2801
|
+
*/
|
|
2802
|
+
async getConversionRate(token) {
|
|
2803
|
+
try {
|
|
2804
|
+
return await this.readContract.read.getConversionRate([token]);
|
|
2805
|
+
} catch (err) {
|
|
2806
|
+
throw wrapError2(err, this.contractAddress);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* Checks whether a token is supported by the gateway.
|
|
2811
|
+
*
|
|
2812
|
+
* @param token - Token address
|
|
2813
|
+
*/
|
|
2814
|
+
async isTokenSupported(token) {
|
|
2815
|
+
try {
|
|
2816
|
+
return await this.readContract.read.isTokenSupported([token]);
|
|
2817
|
+
} catch (err) {
|
|
2818
|
+
throw wrapError2(err, this.contractAddress);
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
/**
|
|
2822
|
+
* Checks whether a user has passed KYC verification.
|
|
2823
|
+
*
|
|
2824
|
+
* @param user - User address
|
|
2825
|
+
*/
|
|
2826
|
+
async isKYCPassed(user) {
|
|
2827
|
+
try {
|
|
2828
|
+
return await this.readContract.read.isKYCPassed([user]);
|
|
2829
|
+
} catch (err) {
|
|
2830
|
+
throw wrapError2(err, this.contractAddress);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
/**
|
|
2834
|
+
* Returns the gateway's full configuration snapshot.
|
|
2835
|
+
*/
|
|
2836
|
+
async getConfig() {
|
|
2837
|
+
try {
|
|
2838
|
+
const contract = this.readContract;
|
|
2839
|
+
const [protocolFeeRate, minWithdrawAmount, dailyLimit, treasury] = await Promise.all([
|
|
2840
|
+
contract.read.protocolFeeRate(),
|
|
2841
|
+
contract.read.minWithdrawAmount(),
|
|
2842
|
+
contract.read.dailyLimit(),
|
|
2843
|
+
contract.read.protocolTreasury()
|
|
2844
|
+
]);
|
|
2845
|
+
return {
|
|
2846
|
+
protocolFeeRate,
|
|
2847
|
+
minWithdrawAmount,
|
|
2848
|
+
dailyLimit,
|
|
2849
|
+
treasury
|
|
2850
|
+
};
|
|
2851
|
+
} catch (err) {
|
|
2852
|
+
throw wrapError2(err, this.contractAddress);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
/**
|
|
2856
|
+
* Returns the daily volume used by a user today.
|
|
2857
|
+
*
|
|
2858
|
+
* @param user - User address
|
|
2859
|
+
*/
|
|
2860
|
+
async getDailyVolume(user) {
|
|
2861
|
+
try {
|
|
2862
|
+
return await this.readContract.read.getDailyVolume([user]);
|
|
2863
|
+
} catch (err) {
|
|
2864
|
+
throw wrapError2(err, this.contractAddress);
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
/**
|
|
2868
|
+
* Returns the remaining daily allowance for a user.
|
|
2869
|
+
*
|
|
2870
|
+
* @param user - User address
|
|
2871
|
+
*/
|
|
2872
|
+
async getDailyRemaining(user) {
|
|
2873
|
+
try {
|
|
2874
|
+
const contract = this.readContract;
|
|
2875
|
+
const [limit, used] = await Promise.all([
|
|
2876
|
+
contract.read.dailyLimit(),
|
|
2877
|
+
contract.read.getDailyVolume([user])
|
|
2878
|
+
]);
|
|
2879
|
+
return limit > used ? limit - used : 0n;
|
|
2880
|
+
} catch (err) {
|
|
2881
|
+
throw wrapError2(err, this.contractAddress);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Mints GHSFIAT for a user. Requires the caller to be an authorized onramper.
|
|
2886
|
+
*
|
|
2887
|
+
* @param user - Recipient address
|
|
2888
|
+
* @param amount - Amount to mint
|
|
2889
|
+
* @returns Transaction result
|
|
2890
|
+
*/
|
|
2891
|
+
async onramp(user, amount) {
|
|
2892
|
+
try {
|
|
2893
|
+
const wallet = this.requireWallet();
|
|
2894
|
+
const hash = await wallet.writeContract({
|
|
2895
|
+
address: this.contractAddress,
|
|
2896
|
+
abi: FiatsendGatewayABI,
|
|
2897
|
+
functionName: "onramp",
|
|
2898
|
+
args: [user, amount],
|
|
2899
|
+
account: wallet.account,
|
|
2900
|
+
chain: wallet.chain ?? null
|
|
2901
|
+
});
|
|
2902
|
+
return {
|
|
2903
|
+
hash,
|
|
2904
|
+
wait: async () => {
|
|
2905
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
2906
|
+
return {
|
|
2907
|
+
hash: receipt.transactionHash,
|
|
2908
|
+
status: receipt.status,
|
|
2909
|
+
blockNumber: receipt.blockNumber,
|
|
2910
|
+
gasUsed: receipt.gasUsed
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
};
|
|
2914
|
+
} catch (err) {
|
|
2915
|
+
throw wrapError2(err, this.contractAddress);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
};
|
|
2919
|
+
function mapStatus(status) {
|
|
2920
|
+
if (status === 0) return "pending";
|
|
2921
|
+
if (status === 1) return "paid";
|
|
2922
|
+
return "cancelled";
|
|
2923
|
+
}
|
|
2924
|
+
function wrapError3(err, contractAddress) {
|
|
2925
|
+
if (err instanceof types.FiatsendError) return err;
|
|
2926
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2927
|
+
if (message.includes("PhoneNotRegistered")) {
|
|
2928
|
+
return new types.FiatsendError("Phone number is not registered to any address", types.FiatsendErrorCode.NO_NFT, { contractAddress });
|
|
2929
|
+
}
|
|
2930
|
+
if (message.includes("SelfPayment")) {
|
|
2931
|
+
return new types.FiatsendError("Cannot send payment to yourself", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
2932
|
+
}
|
|
2933
|
+
if (message.includes("RequestNotFound")) {
|
|
2934
|
+
return new types.FiatsendError("Payment request not found", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
2935
|
+
}
|
|
2936
|
+
if (message.includes("RequestNotPending")) {
|
|
2937
|
+
return new types.FiatsendError("Payment request is no longer pending", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
2938
|
+
}
|
|
2939
|
+
if (message.includes("NotRequestOwner")) {
|
|
2940
|
+
return new types.FiatsendError("Only the request creator can cancel it", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
2941
|
+
}
|
|
2942
|
+
if (message.includes("NotRequestRecipient")) {
|
|
2943
|
+
return new types.FiatsendError("Only the intended payer can pay this request", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
2944
|
+
}
|
|
2945
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
2946
|
+
}
|
|
2947
|
+
var PaymentsResource = class {
|
|
2948
|
+
publicClient;
|
|
2949
|
+
walletClient;
|
|
2950
|
+
contractAddress;
|
|
2951
|
+
constructor(params) {
|
|
2952
|
+
this.publicClient = params.publicClient;
|
|
2953
|
+
this.walletClient = params.walletClient;
|
|
2954
|
+
this.contractAddress = params.contractAddress;
|
|
2955
|
+
}
|
|
2956
|
+
get readContract() {
|
|
2957
|
+
return viem.getContract({
|
|
2958
|
+
address: this.contractAddress,
|
|
2959
|
+
abi: PaymentRouterABI,
|
|
2960
|
+
client: this.publicClient
|
|
2961
|
+
});
|
|
2962
|
+
}
|
|
2963
|
+
requireWallet() {
|
|
2964
|
+
if (!this.walletClient) {
|
|
2965
|
+
throw new types.FiatsendError(
|
|
2966
|
+
"A walletClient is required for write operations.",
|
|
2967
|
+
types.FiatsendErrorCode.UNAUTHORIZED
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
return this.walletClient;
|
|
2971
|
+
}
|
|
2972
|
+
/**
|
|
2973
|
+
* Sends tokens directly to an address.
|
|
2974
|
+
*
|
|
2975
|
+
* The caller must have approved `params.amount` of `params.token` to the PaymentRouter.
|
|
2976
|
+
*
|
|
2977
|
+
* @param params - Token, recipient address, amount, and optional memo
|
|
2978
|
+
* @returns Transaction result
|
|
2979
|
+
*/
|
|
2980
|
+
async send(params) {
|
|
2981
|
+
try {
|
|
2982
|
+
const wallet = this.requireWallet();
|
|
2983
|
+
const hash = await wallet.writeContract({
|
|
2984
|
+
address: this.contractAddress,
|
|
2985
|
+
abi: PaymentRouterABI,
|
|
2986
|
+
functionName: "send",
|
|
2987
|
+
args: [params.token, params.to, params.amount, params.memo ?? ""],
|
|
2988
|
+
account: wallet.account,
|
|
2989
|
+
chain: wallet.chain ?? null
|
|
2990
|
+
});
|
|
2991
|
+
return {
|
|
2992
|
+
hash,
|
|
2993
|
+
wait: async () => {
|
|
2994
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
2995
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
2996
|
+
}
|
|
2997
|
+
};
|
|
2998
|
+
} catch (err) {
|
|
2999
|
+
throw wrapError3(err, this.contractAddress);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
/**
|
|
3003
|
+
* Resolves an encrypted phone hash to an address via MobileNumberNFT and sends tokens.
|
|
3004
|
+
*
|
|
3005
|
+
* @param params - Token, encrypted phone, amount, and optional memo
|
|
3006
|
+
* @returns Transaction result
|
|
3007
|
+
*/
|
|
3008
|
+
async sendToPhone(params) {
|
|
3009
|
+
try {
|
|
3010
|
+
const wallet = this.requireWallet();
|
|
3011
|
+
const hash = await wallet.writeContract({
|
|
3012
|
+
address: this.contractAddress,
|
|
3013
|
+
abi: PaymentRouterABI,
|
|
3014
|
+
functionName: "sendToPhone",
|
|
3015
|
+
args: [params.token, params.encryptedPhone, params.amount, params.memo ?? ""],
|
|
3016
|
+
account: wallet.account,
|
|
3017
|
+
chain: wallet.chain ?? null
|
|
3018
|
+
});
|
|
3019
|
+
return {
|
|
3020
|
+
hash,
|
|
3021
|
+
wait: async () => {
|
|
3022
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3023
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3024
|
+
}
|
|
3025
|
+
};
|
|
3026
|
+
} catch (err) {
|
|
3027
|
+
throw wrapError3(err, this.contractAddress);
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
/**
|
|
3031
|
+
* Creates a payment request — asks another address to pay you.
|
|
3032
|
+
*
|
|
3033
|
+
* @param params - Token, payer address, amount, and optional memo
|
|
3034
|
+
* @returns The created request ID and transaction hash
|
|
3035
|
+
*/
|
|
3036
|
+
async createRequest(params) {
|
|
3037
|
+
try {
|
|
3038
|
+
const wallet = this.requireWallet();
|
|
3039
|
+
const hash = await wallet.writeContract({
|
|
3040
|
+
address: this.contractAddress,
|
|
3041
|
+
abi: PaymentRouterABI,
|
|
3042
|
+
functionName: "createPaymentRequest",
|
|
3043
|
+
args: [params.token, params.from, params.amount, params.memo ?? ""],
|
|
3044
|
+
account: wallet.account,
|
|
3045
|
+
chain: wallet.chain ?? null
|
|
3046
|
+
});
|
|
3047
|
+
return { requestId: 0n, hash };
|
|
3048
|
+
} catch (err) {
|
|
3049
|
+
throw wrapError3(err, this.contractAddress);
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* Pays a pending payment request.
|
|
3054
|
+
*
|
|
3055
|
+
* Only the `to` address on the request can call this.
|
|
3056
|
+
* The caller must approve `request.amount` of `request.token` to the PaymentRouter.
|
|
3057
|
+
*
|
|
3058
|
+
* @param requestId - The payment request ID to pay
|
|
3059
|
+
* @returns Transaction result
|
|
3060
|
+
*/
|
|
3061
|
+
async payRequest(requestId) {
|
|
3062
|
+
try {
|
|
3063
|
+
const wallet = this.requireWallet();
|
|
3064
|
+
const hash = await wallet.writeContract({
|
|
3065
|
+
address: this.contractAddress,
|
|
3066
|
+
abi: PaymentRouterABI,
|
|
3067
|
+
functionName: "payRequest",
|
|
3068
|
+
args: [requestId],
|
|
3069
|
+
account: wallet.account,
|
|
3070
|
+
chain: wallet.chain ?? null
|
|
3071
|
+
});
|
|
3072
|
+
return {
|
|
3073
|
+
hash,
|
|
3074
|
+
wait: async () => {
|
|
3075
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3076
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3077
|
+
}
|
|
3078
|
+
};
|
|
3079
|
+
} catch (err) {
|
|
3080
|
+
throw wrapError3(err, this.contractAddress);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
/**
|
|
3084
|
+
* Cancels a pending payment request.
|
|
3085
|
+
*
|
|
3086
|
+
* Only the request creator (`from` address) can cancel.
|
|
3087
|
+
*
|
|
3088
|
+
* @param requestId - The payment request ID to cancel
|
|
3089
|
+
* @returns Transaction result
|
|
3090
|
+
*/
|
|
3091
|
+
async cancelRequest(requestId) {
|
|
3092
|
+
try {
|
|
3093
|
+
const wallet = this.requireWallet();
|
|
3094
|
+
const hash = await wallet.writeContract({
|
|
3095
|
+
address: this.contractAddress,
|
|
3096
|
+
abi: PaymentRouterABI,
|
|
3097
|
+
functionName: "cancelRequest",
|
|
3098
|
+
args: [requestId],
|
|
3099
|
+
account: wallet.account,
|
|
3100
|
+
chain: wallet.chain ?? null
|
|
3101
|
+
});
|
|
3102
|
+
return {
|
|
3103
|
+
hash,
|
|
3104
|
+
wait: async () => {
|
|
3105
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3106
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3107
|
+
}
|
|
3108
|
+
};
|
|
3109
|
+
} catch (err) {
|
|
3110
|
+
throw wrapError3(err, this.contractAddress);
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
/**
|
|
3114
|
+
* Fetches a payment request by ID.
|
|
3115
|
+
*
|
|
3116
|
+
* @param requestId - Payment request ID
|
|
3117
|
+
* @returns PaymentRequest data
|
|
3118
|
+
*/
|
|
3119
|
+
async getRequest(requestId) {
|
|
3120
|
+
try {
|
|
3121
|
+
const req = await this.readContract.read.getPaymentRequest([requestId]);
|
|
3122
|
+
return {
|
|
3123
|
+
id: req.id,
|
|
3124
|
+
from: req.from,
|
|
3125
|
+
to: req.to,
|
|
3126
|
+
token: req.token,
|
|
3127
|
+
amount: req.amount,
|
|
3128
|
+
memo: req.memo,
|
|
3129
|
+
status: mapStatus(req.status),
|
|
3130
|
+
createdAt: req.createdAt
|
|
3131
|
+
};
|
|
3132
|
+
} catch (err) {
|
|
3133
|
+
throw wrapError3(err, this.contractAddress);
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
/**
|
|
3137
|
+
* Returns the total number of payment requests created.
|
|
3138
|
+
*/
|
|
3139
|
+
async getRequestCount() {
|
|
3140
|
+
try {
|
|
3141
|
+
return await this.readContract.read.paymentRequestCounter();
|
|
3142
|
+
} catch (err) {
|
|
3143
|
+
throw wrapError3(err, this.contractAddress);
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
};
|
|
3147
|
+
function mapStatus2(status) {
|
|
3148
|
+
switch (status) {
|
|
3149
|
+
case 1:
|
|
3150
|
+
return "pending";
|
|
3151
|
+
case 2:
|
|
3152
|
+
return "processing";
|
|
3153
|
+
case 3:
|
|
3154
|
+
return "completed";
|
|
3155
|
+
case 4:
|
|
3156
|
+
return "failed";
|
|
3157
|
+
default:
|
|
3158
|
+
return "pending";
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
function wrapError4(err, contractAddress) {
|
|
3162
|
+
if (err instanceof types.FiatsendError) return err;
|
|
3163
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3164
|
+
if (message.includes("WithdrawalNotFound")) {
|
|
3165
|
+
return new types.FiatsendError("Withdrawal record not found", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3166
|
+
}
|
|
3167
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.NETWORK_ERROR, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
3168
|
+
}
|
|
3169
|
+
var WithdrawalsResource = class {
|
|
3170
|
+
publicClient;
|
|
3171
|
+
contractAddress;
|
|
3172
|
+
constructor(params) {
|
|
3173
|
+
this.publicClient = params.publicClient;
|
|
3174
|
+
this.contractAddress = params.contractAddress;
|
|
3175
|
+
}
|
|
3176
|
+
get contract() {
|
|
3177
|
+
return viem.getContract({
|
|
3178
|
+
address: this.contractAddress,
|
|
3179
|
+
abi: WithdrawalsABI,
|
|
3180
|
+
client: this.publicClient
|
|
3181
|
+
});
|
|
3182
|
+
}
|
|
3183
|
+
/**
|
|
3184
|
+
* Returns a withdrawal record by ID.
|
|
3185
|
+
*
|
|
3186
|
+
* @param id - Withdrawal ID
|
|
3187
|
+
*/
|
|
3188
|
+
async getWithdrawal(id) {
|
|
3189
|
+
try {
|
|
3190
|
+
const w = await this.contract.read.getWithdrawal([id]);
|
|
3191
|
+
return {
|
|
3192
|
+
id: w.id,
|
|
3193
|
+
user: w.user,
|
|
3194
|
+
token: w.token,
|
|
3195
|
+
amount: w.amount,
|
|
3196
|
+
fee: w.fee,
|
|
3197
|
+
status: mapStatus2(w.status),
|
|
3198
|
+
paymentMethod: w.paymentMethod,
|
|
3199
|
+
phoneNumber: w.phoneNumber,
|
|
3200
|
+
createdAt: w.createdAt,
|
|
3201
|
+
completedAt: w.completedAt
|
|
3202
|
+
};
|
|
3203
|
+
} catch (err) {
|
|
3204
|
+
throw wrapError4(err, this.contractAddress);
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
/**
|
|
3208
|
+
* Returns all withdrawal records for a user, resolved from their IDs.
|
|
3209
|
+
*
|
|
3210
|
+
* @param user - User address
|
|
3211
|
+
*/
|
|
3212
|
+
async getUserWithdrawals(user) {
|
|
3213
|
+
try {
|
|
3214
|
+
const ids = await this.contract.read.getUserWithdrawals([user]);
|
|
3215
|
+
const withdrawals = await Promise.all(ids.map((id) => this.getWithdrawal(id)));
|
|
3216
|
+
return withdrawals;
|
|
3217
|
+
} catch (err) {
|
|
3218
|
+
throw wrapError4(err, this.contractAddress);
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* Returns the total number of withdrawals ever created.
|
|
3223
|
+
*/
|
|
3224
|
+
async getWithdrawalCount() {
|
|
3225
|
+
try {
|
|
3226
|
+
return await this.contract.read.withdrawalCounter();
|
|
3227
|
+
} catch (err) {
|
|
3228
|
+
throw wrapError4(err, this.contractAddress);
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
};
|
|
3232
|
+
function wrapError5(err, contractAddress) {
|
|
3233
|
+
if (err instanceof types.FiatsendError) return err;
|
|
3234
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3235
|
+
if (message.includes("BelowMinDeposit")) {
|
|
3236
|
+
return new types.FiatsendError("Amount is below the minimum deposit for this pool", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
3237
|
+
}
|
|
3238
|
+
if (message.includes("LockPeriodActive")) {
|
|
3239
|
+
return new types.FiatsendError("Cannot withdraw \u2014 lock period is still active", types.FiatsendErrorCode.LOCK_PERIOD_ACTIVE, { contractAddress });
|
|
3240
|
+
}
|
|
3241
|
+
if (message.includes("InsufficientBalance")) {
|
|
3242
|
+
return new types.FiatsendError("Insufficient deposited balance", types.FiatsendErrorCode.INSUFFICIENT_BALANCE, { contractAddress });
|
|
3243
|
+
}
|
|
3244
|
+
if (message.includes("ZeroAmount")) {
|
|
3245
|
+
return new types.FiatsendError("Amount must be greater than zero", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
3246
|
+
}
|
|
3247
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
3248
|
+
}
|
|
3249
|
+
var LiquidityResource = class {
|
|
3250
|
+
publicClient;
|
|
3251
|
+
walletClient;
|
|
3252
|
+
contractAddress;
|
|
3253
|
+
constructor(params) {
|
|
3254
|
+
this.publicClient = params.publicClient;
|
|
3255
|
+
this.walletClient = params.walletClient;
|
|
3256
|
+
this.contractAddress = params.contractAddress;
|
|
3257
|
+
}
|
|
3258
|
+
get readContract() {
|
|
3259
|
+
return viem.getContract({
|
|
3260
|
+
address: this.contractAddress,
|
|
3261
|
+
abi: LiquidityPoolABI,
|
|
3262
|
+
client: this.publicClient
|
|
3263
|
+
});
|
|
3264
|
+
}
|
|
3265
|
+
requireWallet() {
|
|
3266
|
+
if (!this.walletClient) {
|
|
3267
|
+
throw new types.FiatsendError("A walletClient is required for write operations.", types.FiatsendErrorCode.UNAUTHORIZED);
|
|
3268
|
+
}
|
|
3269
|
+
return this.walletClient;
|
|
3270
|
+
}
|
|
3271
|
+
/**
|
|
3272
|
+
* Deposits stablecoins into the liquidity pool.
|
|
3273
|
+
*
|
|
3274
|
+
* The caller must approve `amount` of the pool's supported token to this contract.
|
|
3275
|
+
*
|
|
3276
|
+
* @param amount - Amount to deposit (must be >= pool minDeposit)
|
|
3277
|
+
* @returns Transaction result
|
|
3278
|
+
*/
|
|
3279
|
+
async deposit(amount) {
|
|
3280
|
+
try {
|
|
3281
|
+
const wallet = this.requireWallet();
|
|
3282
|
+
const hash = await wallet.writeContract({
|
|
3283
|
+
address: this.contractAddress,
|
|
3284
|
+
abi: LiquidityPoolABI,
|
|
3285
|
+
functionName: "deposit",
|
|
3286
|
+
args: [amount],
|
|
3287
|
+
account: wallet.account,
|
|
3288
|
+
chain: wallet.chain ?? null
|
|
3289
|
+
});
|
|
3290
|
+
return {
|
|
3291
|
+
hash,
|
|
3292
|
+
wait: async () => {
|
|
3293
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3294
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3295
|
+
}
|
|
3296
|
+
};
|
|
3297
|
+
} catch (err) {
|
|
3298
|
+
throw wrapError5(err, this.contractAddress);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
/**
|
|
3302
|
+
* Withdraws stablecoins from the pool (after the lock period has elapsed).
|
|
3303
|
+
*
|
|
3304
|
+
* @param amount - Amount to withdraw
|
|
3305
|
+
* @returns Transaction result
|
|
3306
|
+
*/
|
|
3307
|
+
async withdraw(amount) {
|
|
3308
|
+
try {
|
|
3309
|
+
const wallet = this.requireWallet();
|
|
3310
|
+
const hash = await wallet.writeContract({
|
|
3311
|
+
address: this.contractAddress,
|
|
3312
|
+
abi: LiquidityPoolABI,
|
|
3313
|
+
functionName: "withdraw",
|
|
3314
|
+
args: [amount],
|
|
3315
|
+
account: wallet.account,
|
|
3316
|
+
chain: wallet.chain ?? null
|
|
3317
|
+
});
|
|
3318
|
+
return {
|
|
3319
|
+
hash,
|
|
3320
|
+
wait: async () => {
|
|
3321
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3322
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3323
|
+
}
|
|
3324
|
+
};
|
|
3325
|
+
} catch (err) {
|
|
3326
|
+
throw wrapError5(err, this.contractAddress);
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
/**
|
|
3330
|
+
* Claims all pending fee rewards for the caller.
|
|
3331
|
+
*
|
|
3332
|
+
* @returns Transaction result
|
|
3333
|
+
*/
|
|
3334
|
+
async claimRewards() {
|
|
3335
|
+
try {
|
|
3336
|
+
const wallet = this.requireWallet();
|
|
3337
|
+
const hash = await wallet.writeContract({
|
|
3338
|
+
address: this.contractAddress,
|
|
3339
|
+
abi: LiquidityPoolABI,
|
|
3340
|
+
functionName: "claimRewards",
|
|
3341
|
+
args: [],
|
|
3342
|
+
account: wallet.account,
|
|
3343
|
+
chain: wallet.chain ?? null
|
|
3344
|
+
});
|
|
3345
|
+
return {
|
|
3346
|
+
hash,
|
|
3347
|
+
wait: async () => {
|
|
3348
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3349
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3350
|
+
}
|
|
3351
|
+
};
|
|
3352
|
+
} catch (err) {
|
|
3353
|
+
throw wrapError5(err, this.contractAddress);
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
/**
|
|
3357
|
+
* Returns pool-level statistics.
|
|
3358
|
+
*/
|
|
3359
|
+
async getPoolInfo() {
|
|
3360
|
+
try {
|
|
3361
|
+
const info = await this.readContract.read.getPoolInfo();
|
|
3362
|
+
return {
|
|
3363
|
+
token: info.supportedToken,
|
|
3364
|
+
totalDeposits: info.totalDeposits,
|
|
3365
|
+
rewardPerToken: info.rewardPerToken,
|
|
3366
|
+
minDeposit: info.minDeposit,
|
|
3367
|
+
lockPeriod: info.lockPeriod
|
|
3368
|
+
};
|
|
3369
|
+
} catch (err) {
|
|
3370
|
+
throw wrapError5(err, this.contractAddress);
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
/**
|
|
3374
|
+
* Returns a user's LP position including deposited balance and pending rewards.
|
|
3375
|
+
*
|
|
3376
|
+
* @param user - User address
|
|
3377
|
+
*/
|
|
3378
|
+
async getPosition(user) {
|
|
3379
|
+
try {
|
|
3380
|
+
const contract = this.readContract;
|
|
3381
|
+
const [deposited, pendingRewards] = await Promise.all([
|
|
3382
|
+
contract.read.getDeposit([user]),
|
|
3383
|
+
contract.read.getRewards([user])
|
|
3384
|
+
]);
|
|
3385
|
+
return {
|
|
3386
|
+
deposited,
|
|
3387
|
+
pendingRewards,
|
|
3388
|
+
depositTimestamp: 0n,
|
|
3389
|
+
canWithdraw: true
|
|
3390
|
+
};
|
|
3391
|
+
} catch (err) {
|
|
3392
|
+
throw wrapError5(err, this.contractAddress);
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
/**
|
|
3396
|
+
* Returns pending rewards for a user.
|
|
3397
|
+
*
|
|
3398
|
+
* @param user - User address
|
|
3399
|
+
*/
|
|
3400
|
+
async getPendingRewards(user) {
|
|
3401
|
+
try {
|
|
3402
|
+
return await this.readContract.read.getRewards([user]);
|
|
3403
|
+
} catch (err) {
|
|
3404
|
+
throw wrapError5(err, this.contractAddress);
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
};
|
|
3408
|
+
function wrapError6(err, contractAddress) {
|
|
3409
|
+
if (err instanceof types.FiatsendError) return err;
|
|
3410
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3411
|
+
if (message.includes("BelowMinDeposit")) {
|
|
3412
|
+
return new types.FiatsendError("Amount is below the minimum vault deposit", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
3413
|
+
}
|
|
3414
|
+
if (message.includes("InsufficientBalance")) {
|
|
3415
|
+
return new types.FiatsendError("Insufficient vault balance", types.FiatsendErrorCode.INSUFFICIENT_BALANCE, { contractAddress });
|
|
3416
|
+
}
|
|
3417
|
+
if (message.includes("NoYieldAvailable")) {
|
|
3418
|
+
return new types.FiatsendError("No yield available to claim yet", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
3419
|
+
}
|
|
3420
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress, ...err instanceof Error && { cause: err } });
|
|
3421
|
+
}
|
|
3422
|
+
var VaultsResource = class {
|
|
3423
|
+
publicClient;
|
|
3424
|
+
walletClient;
|
|
3425
|
+
contractAddress;
|
|
3426
|
+
supportedTokenAddress;
|
|
3427
|
+
constructor(params) {
|
|
3428
|
+
this.publicClient = params.publicClient;
|
|
3429
|
+
this.walletClient = params.walletClient;
|
|
3430
|
+
this.contractAddress = params.contractAddress;
|
|
3431
|
+
this.supportedTokenAddress = params.supportedTokenAddress;
|
|
3432
|
+
}
|
|
3433
|
+
get readContract() {
|
|
3434
|
+
return viem.getContract({
|
|
3435
|
+
address: this.contractAddress,
|
|
3436
|
+
abi: VaultControllerABI,
|
|
3437
|
+
client: this.publicClient
|
|
3438
|
+
});
|
|
3439
|
+
}
|
|
3440
|
+
requireWallet() {
|
|
3441
|
+
if (!this.walletClient) {
|
|
3442
|
+
throw new types.FiatsendError("A walletClient is required for write operations.", types.FiatsendErrorCode.UNAUTHORIZED);
|
|
3443
|
+
}
|
|
3444
|
+
return this.walletClient;
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* Deposits stablecoins into the vault.
|
|
3448
|
+
*
|
|
3449
|
+
* The caller must approve `amount` of the vault's supported token to this contract.
|
|
3450
|
+
*
|
|
3451
|
+
* @param amount - Amount to deposit (must be >= vault minDeposit)
|
|
3452
|
+
* @returns Transaction result
|
|
3453
|
+
*/
|
|
3454
|
+
async deposit(amount) {
|
|
3455
|
+
try {
|
|
3456
|
+
const wallet = this.requireWallet();
|
|
3457
|
+
const hash = await wallet.writeContract({
|
|
3458
|
+
address: this.contractAddress,
|
|
3459
|
+
abi: VaultControllerABI,
|
|
3460
|
+
functionName: "deposit",
|
|
3461
|
+
args: [amount],
|
|
3462
|
+
account: wallet.account,
|
|
3463
|
+
chain: wallet.chain ?? null
|
|
3464
|
+
});
|
|
3465
|
+
return {
|
|
3466
|
+
hash,
|
|
3467
|
+
wait: async () => {
|
|
3468
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3469
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3470
|
+
}
|
|
3471
|
+
};
|
|
3472
|
+
} catch (err) {
|
|
3473
|
+
throw wrapError6(err, this.contractAddress);
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
/**
|
|
3477
|
+
* Withdraws stablecoins from the vault. Accrued yield is claimed automatically.
|
|
3478
|
+
*
|
|
3479
|
+
* @param amount - Amount to withdraw
|
|
3480
|
+
* @returns Transaction result
|
|
3481
|
+
*/
|
|
3482
|
+
async withdraw(amount) {
|
|
3483
|
+
try {
|
|
3484
|
+
const wallet = this.requireWallet();
|
|
3485
|
+
const hash = await wallet.writeContract({
|
|
3486
|
+
address: this.contractAddress,
|
|
3487
|
+
abi: VaultControllerABI,
|
|
3488
|
+
functionName: "withdraw",
|
|
3489
|
+
args: [amount],
|
|
3490
|
+
account: wallet.account,
|
|
3491
|
+
chain: wallet.chain ?? null
|
|
3492
|
+
});
|
|
3493
|
+
return {
|
|
3494
|
+
hash,
|
|
3495
|
+
wait: async () => {
|
|
3496
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3497
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3498
|
+
}
|
|
3499
|
+
};
|
|
3500
|
+
} catch (err) {
|
|
3501
|
+
throw wrapError6(err, this.contractAddress);
|
|
3502
|
+
}
|
|
3503
|
+
}
|
|
3504
|
+
/**
|
|
3505
|
+
* Claims accrued yield without withdrawing principal.
|
|
3506
|
+
*
|
|
3507
|
+
* @returns Transaction result
|
|
3508
|
+
*/
|
|
3509
|
+
async claimYield() {
|
|
3510
|
+
try {
|
|
3511
|
+
const wallet = this.requireWallet();
|
|
3512
|
+
const hash = await wallet.writeContract({
|
|
3513
|
+
address: this.contractAddress,
|
|
3514
|
+
abi: VaultControllerABI,
|
|
3515
|
+
functionName: "claimYield",
|
|
3516
|
+
args: [],
|
|
3517
|
+
account: wallet.account,
|
|
3518
|
+
chain: wallet.chain ?? null
|
|
3519
|
+
});
|
|
3520
|
+
return {
|
|
3521
|
+
hash,
|
|
3522
|
+
wait: async () => {
|
|
3523
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3524
|
+
return { hash: receipt.transactionHash, status: receipt.status, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed };
|
|
3525
|
+
}
|
|
3526
|
+
};
|
|
3527
|
+
} catch (err) {
|
|
3528
|
+
throw wrapError6(err, this.contractAddress);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
/**
|
|
3532
|
+
* Returns vault-level configuration.
|
|
3533
|
+
*/
|
|
3534
|
+
async getVaultInfo() {
|
|
3535
|
+
try {
|
|
3536
|
+
const contract = this.readContract;
|
|
3537
|
+
const [annualYieldRate, minDeposit, totalDeposited] = await Promise.all([
|
|
3538
|
+
contract.read.annualYieldRate(),
|
|
3539
|
+
contract.read.minDeposit(),
|
|
3540
|
+
contract.read.totalDeposited()
|
|
3541
|
+
]);
|
|
3542
|
+
return {
|
|
3543
|
+
token: this.supportedTokenAddress,
|
|
3544
|
+
totalDeposited,
|
|
3545
|
+
annualYieldRate,
|
|
3546
|
+
minDeposit
|
|
3547
|
+
};
|
|
3548
|
+
} catch (err) {
|
|
3549
|
+
throw wrapError6(err, this.contractAddress);
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
/**
|
|
3553
|
+
* Returns a user's vault position.
|
|
3554
|
+
*
|
|
3555
|
+
* @param user - User address
|
|
3556
|
+
*/
|
|
3557
|
+
async getPosition(user) {
|
|
3558
|
+
try {
|
|
3559
|
+
const contract = this.readContract;
|
|
3560
|
+
const [vaultData, pendingYield] = await Promise.all([
|
|
3561
|
+
contract.read.getVault([user]),
|
|
3562
|
+
contract.read.calculateYield([user])
|
|
3563
|
+
]);
|
|
3564
|
+
return {
|
|
3565
|
+
balance: vaultData.balance,
|
|
3566
|
+
pendingYield,
|
|
3567
|
+
depositedAt: vaultData.depositedAt,
|
|
3568
|
+
lastYieldClaim: vaultData.lastYieldClaim
|
|
3569
|
+
};
|
|
3570
|
+
} catch (err) {
|
|
3571
|
+
throw wrapError6(err, this.contractAddress);
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
/**
|
|
3575
|
+
* Returns the pending yield for a user.
|
|
3576
|
+
*
|
|
3577
|
+
* @param user - User address
|
|
3578
|
+
*/
|
|
3579
|
+
async getPendingYield(user) {
|
|
3580
|
+
try {
|
|
3581
|
+
return await this.readContract.read.calculateYield([user]);
|
|
3582
|
+
} catch (err) {
|
|
3583
|
+
throw wrapError6(err, this.contractAddress);
|
|
3584
|
+
}
|
|
3585
|
+
}
|
|
3586
|
+
};
|
|
3587
|
+
function mapPayoutStatus(status) {
|
|
3588
|
+
switch (status) {
|
|
3589
|
+
case 0:
|
|
3590
|
+
return "pending";
|
|
3591
|
+
case 1:
|
|
3592
|
+
return "claimed";
|
|
3593
|
+
case 2:
|
|
3594
|
+
return "refunded";
|
|
3595
|
+
case 3:
|
|
3596
|
+
return "expired";
|
|
3597
|
+
default:
|
|
3598
|
+
return "pending";
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
function mapPayout(raw) {
|
|
3602
|
+
return {
|
|
3603
|
+
id: raw.id,
|
|
3604
|
+
sender: raw.sender,
|
|
3605
|
+
recipient: raw.recipient,
|
|
3606
|
+
token: raw.token,
|
|
3607
|
+
amount: raw.amount,
|
|
3608
|
+
phoneHash: raw.phoneHash,
|
|
3609
|
+
status: mapPayoutStatus(raw.status),
|
|
3610
|
+
expiresAt: raw.expiresAt,
|
|
3611
|
+
createdAt: raw.createdAt,
|
|
3612
|
+
claimedAt: raw.claimedAt
|
|
3613
|
+
};
|
|
3614
|
+
}
|
|
3615
|
+
function wrapError7(err, contractAddress) {
|
|
3616
|
+
if (err instanceof types.FiatsendError) return err;
|
|
3617
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3618
|
+
if (message.includes("PayoutAlreadyExists")) {
|
|
3619
|
+
return new types.FiatsendError("A payout with this ID already exists", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3620
|
+
}
|
|
3621
|
+
if (message.includes("PayoutNotFound")) {
|
|
3622
|
+
return new types.FiatsendError("Payout not found", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3623
|
+
}
|
|
3624
|
+
if (message.includes("NotAuthorizedSender")) {
|
|
3625
|
+
return new types.FiatsendError("Caller is not an authorized sender", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
3626
|
+
}
|
|
3627
|
+
if (message.includes("NotPending")) {
|
|
3628
|
+
return new types.FiatsendError("Payout is not in pending status", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3629
|
+
}
|
|
3630
|
+
if (message.includes("NotExpiredYet")) {
|
|
3631
|
+
return new types.FiatsendError("Payout has not expired yet \u2014 cannot refund", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3632
|
+
}
|
|
3633
|
+
if (message.includes("NotRefundEligible")) {
|
|
3634
|
+
return new types.FiatsendError("Only the original sender or owner may refund this payout", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
3635
|
+
}
|
|
3636
|
+
if (message.includes("PhoneHashMismatch")) {
|
|
3637
|
+
return new types.FiatsendError("Your phone hash does not match this payout", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
3638
|
+
}
|
|
3639
|
+
if (message.includes("NoMobileNFT")) {
|
|
3640
|
+
return new types.FiatsendError("You do not have a MobileNumber NFT \u2014 please register first", types.FiatsendErrorCode.NO_NFT, { contractAddress });
|
|
3641
|
+
}
|
|
3642
|
+
if (message.includes("ZeroAmount")) {
|
|
3643
|
+
return new types.FiatsendError("Amount must be greater than zero", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
3644
|
+
}
|
|
3645
|
+
if (message.includes("GatewayNotSet")) {
|
|
3646
|
+
return new types.FiatsendError("Gateway address has not been configured on PayoutEscrow", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3647
|
+
}
|
|
3648
|
+
if (message.includes("TokenNotSupportedByGateway")) {
|
|
3649
|
+
return new types.FiatsendError("This token is not supported by the gateway", types.FiatsendErrorCode.TOKEN_NOT_SUPPORTED, { contractAddress });
|
|
3650
|
+
}
|
|
3651
|
+
if (message.includes("ArrayLengthMismatch")) {
|
|
3652
|
+
return new types.FiatsendError("Batch payout arrays must all be the same length", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3653
|
+
}
|
|
3654
|
+
if (message.includes("InvalidExpiry")) {
|
|
3655
|
+
return new types.FiatsendError("Expiry timestamp must be in the future", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3656
|
+
}
|
|
3657
|
+
if (message.includes("Paused") || message.includes("EnforcedPause")) {
|
|
3658
|
+
return new types.FiatsendError("PayoutEscrow is currently paused", types.FiatsendErrorCode.CONTRACT_PAUSED, { contractAddress });
|
|
3659
|
+
}
|
|
3660
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, {
|
|
3661
|
+
contractAddress,
|
|
3662
|
+
...err instanceof Error && { cause: err }
|
|
3663
|
+
});
|
|
3664
|
+
}
|
|
3665
|
+
var PayoutsResource = class {
|
|
3666
|
+
publicClient;
|
|
3667
|
+
walletClient;
|
|
3668
|
+
contractAddress;
|
|
3669
|
+
constructor(params) {
|
|
3670
|
+
this.publicClient = params.publicClient;
|
|
3671
|
+
this.walletClient = params.walletClient;
|
|
3672
|
+
this.contractAddress = params.contractAddress;
|
|
3673
|
+
}
|
|
3674
|
+
get readContract() {
|
|
3675
|
+
return viem.getContract({
|
|
3676
|
+
address: this.contractAddress,
|
|
3677
|
+
abi: PayoutEscrowABI,
|
|
3678
|
+
client: this.publicClient
|
|
3679
|
+
});
|
|
3680
|
+
}
|
|
3681
|
+
requireWallet() {
|
|
3682
|
+
if (!this.walletClient) {
|
|
3683
|
+
throw new types.FiatsendError(
|
|
3684
|
+
"A walletClient is required for write operations.",
|
|
3685
|
+
types.FiatsendErrorCode.UNAUTHORIZED
|
|
3686
|
+
);
|
|
3687
|
+
}
|
|
3688
|
+
return this.walletClient;
|
|
3689
|
+
}
|
|
3690
|
+
buildTxResult(hash) {
|
|
3691
|
+
return {
|
|
3692
|
+
hash,
|
|
3693
|
+
wait: async () => {
|
|
3694
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
3695
|
+
return {
|
|
3696
|
+
hash: receipt.transactionHash,
|
|
3697
|
+
status: receipt.status,
|
|
3698
|
+
blockNumber: receipt.blockNumber,
|
|
3699
|
+
gasUsed: receipt.gasUsed
|
|
3700
|
+
};
|
|
3701
|
+
}
|
|
3702
|
+
};
|
|
3703
|
+
}
|
|
3704
|
+
// ─── Write: Business payout creation ────────────────────────────────────
|
|
3705
|
+
/**
|
|
3706
|
+
* Creates a single payout in the escrow.
|
|
3707
|
+
*
|
|
3708
|
+
* The caller must be an authorized sender (set by the contract owner) and must
|
|
3709
|
+
* have approved `amount` of `token` to the PayoutEscrow contract first.
|
|
3710
|
+
*
|
|
3711
|
+
* @param params - Payout parameters including token, amount, phone hash, and optional expiry
|
|
3712
|
+
* @returns Transaction result
|
|
3713
|
+
*/
|
|
3714
|
+
async createPayout(params) {
|
|
3715
|
+
try {
|
|
3716
|
+
const wallet = this.requireWallet();
|
|
3717
|
+
const hash = await wallet.writeContract({
|
|
3718
|
+
address: this.contractAddress,
|
|
3719
|
+
abi: PayoutEscrowABI,
|
|
3720
|
+
functionName: "createPayout",
|
|
3721
|
+
args: [
|
|
3722
|
+
params.payoutId,
|
|
3723
|
+
params.token,
|
|
3724
|
+
params.amount,
|
|
3725
|
+
params.phoneHash,
|
|
3726
|
+
params.expiresAt ?? 0n
|
|
3727
|
+
],
|
|
3728
|
+
account: wallet.account,
|
|
3729
|
+
chain: wallet.chain ?? null
|
|
3730
|
+
});
|
|
3731
|
+
return this.buildTxResult(hash);
|
|
3732
|
+
} catch (err) {
|
|
3733
|
+
throw wrapError7(err, this.contractAddress);
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
/**
|
|
3737
|
+
* Creates multiple payouts in a single transaction (single token approval).
|
|
3738
|
+
*
|
|
3739
|
+
* The caller must be an authorized sender and must have approved the total sum
|
|
3740
|
+
* of all amounts to the PayoutEscrow contract.
|
|
3741
|
+
*
|
|
3742
|
+
* @param params - Batch payout parameters
|
|
3743
|
+
* @returns Transaction result
|
|
3744
|
+
*/
|
|
3745
|
+
async createBatchPayout(params) {
|
|
3746
|
+
try {
|
|
3747
|
+
const wallet = this.requireWallet();
|
|
3748
|
+
const hash = await wallet.writeContract({
|
|
3749
|
+
address: this.contractAddress,
|
|
3750
|
+
abi: PayoutEscrowABI,
|
|
3751
|
+
functionName: "createBatchPayout",
|
|
3752
|
+
args: [
|
|
3753
|
+
params.payoutIds,
|
|
3754
|
+
params.token,
|
|
3755
|
+
params.amounts,
|
|
3756
|
+
params.phoneHashes,
|
|
3757
|
+
params.expiresAt ?? 0n
|
|
3758
|
+
],
|
|
3759
|
+
account: wallet.account,
|
|
3760
|
+
chain: wallet.chain ?? null
|
|
3761
|
+
});
|
|
3762
|
+
return this.buildTxResult(hash);
|
|
3763
|
+
} catch (err) {
|
|
3764
|
+
throw wrapError7(err, this.contractAddress);
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
// ─── Write: Recipient claim ──────────────────────────────────────────────
|
|
3768
|
+
/**
|
|
3769
|
+
* Claims a payout to the caller's wallet.
|
|
3770
|
+
*
|
|
3771
|
+
* The caller must hold a MobileNumberNFT whose phone hash matches the payout.
|
|
3772
|
+
*
|
|
3773
|
+
* @param payoutId - ID of the payout to claim
|
|
3774
|
+
* @returns Transaction result
|
|
3775
|
+
*/
|
|
3776
|
+
async claim(payoutId) {
|
|
3777
|
+
try {
|
|
3778
|
+
const wallet = this.requireWallet();
|
|
3779
|
+
const hash = await wallet.writeContract({
|
|
3780
|
+
address: this.contractAddress,
|
|
3781
|
+
abi: PayoutEscrowABI,
|
|
3782
|
+
functionName: "claim",
|
|
3783
|
+
args: [payoutId],
|
|
3784
|
+
account: wallet.account,
|
|
3785
|
+
chain: wallet.chain ?? null
|
|
3786
|
+
});
|
|
3787
|
+
return this.buildTxResult(hash);
|
|
3788
|
+
} catch (err) {
|
|
3789
|
+
throw wrapError7(err, this.contractAddress);
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
/**
|
|
3793
|
+
* Claims a payout and immediately routes funds through the gateway to mobile money.
|
|
3794
|
+
*
|
|
3795
|
+
* Requires the gateway to be set on the PayoutEscrow and the token to be supported.
|
|
3796
|
+
* The caller must hold a MobileNumberNFT whose phone hash matches the payout.
|
|
3797
|
+
*
|
|
3798
|
+
* @param payoutId - ID of the payout to claim
|
|
3799
|
+
* @param phoneNumber - Destination MoMo phone number (e.g., "+233241234567")
|
|
3800
|
+
* @returns Transaction result
|
|
3801
|
+
*/
|
|
3802
|
+
async claimToMoMo(payoutId, phoneNumber) {
|
|
3803
|
+
try {
|
|
3804
|
+
const wallet = this.requireWallet();
|
|
3805
|
+
const hash = await wallet.writeContract({
|
|
3806
|
+
address: this.contractAddress,
|
|
3807
|
+
abi: PayoutEscrowABI,
|
|
3808
|
+
functionName: "claimToMoMo",
|
|
3809
|
+
args: [payoutId, phoneNumber],
|
|
3810
|
+
account: wallet.account,
|
|
3811
|
+
chain: wallet.chain ?? null
|
|
3812
|
+
});
|
|
3813
|
+
return this.buildTxResult(hash);
|
|
3814
|
+
} catch (err) {
|
|
3815
|
+
throw wrapError7(err, this.contractAddress);
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
// ─── Write: Business refund ──────────────────────────────────────────────
|
|
3819
|
+
/**
|
|
3820
|
+
* Refunds an expired pending payout back to the original sender.
|
|
3821
|
+
*
|
|
3822
|
+
* Only the original sender or contract owner may call this. The payout must
|
|
3823
|
+
* be past its expiry timestamp.
|
|
3824
|
+
*
|
|
3825
|
+
* @param payoutId - ID of the expired payout to refund
|
|
3826
|
+
* @returns Transaction result
|
|
3827
|
+
*/
|
|
3828
|
+
async refund(payoutId) {
|
|
3829
|
+
try {
|
|
3830
|
+
const wallet = this.requireWallet();
|
|
3831
|
+
const hash = await wallet.writeContract({
|
|
3832
|
+
address: this.contractAddress,
|
|
3833
|
+
abi: PayoutEscrowABI,
|
|
3834
|
+
functionName: "refund",
|
|
3835
|
+
args: [payoutId],
|
|
3836
|
+
account: wallet.account,
|
|
3837
|
+
chain: wallet.chain ?? null
|
|
3838
|
+
});
|
|
3839
|
+
return this.buildTxResult(hash);
|
|
3840
|
+
} catch (err) {
|
|
3841
|
+
throw wrapError7(err, this.contractAddress);
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
// ─── Read operations ──────────────────────────────────────────────────────
|
|
3845
|
+
/**
|
|
3846
|
+
* Returns the full payout struct for a given ID.
|
|
3847
|
+
*
|
|
3848
|
+
* @param payoutId - ID of the payout to look up
|
|
3849
|
+
* @returns Full Payout object with TypeScript-mapped status
|
|
3850
|
+
*/
|
|
3851
|
+
async getPayout(payoutId) {
|
|
3852
|
+
try {
|
|
3853
|
+
const raw = await this.readContract.read.getPayout([payoutId]);
|
|
3854
|
+
return mapPayout(raw);
|
|
3855
|
+
} catch (err) {
|
|
3856
|
+
throw wrapError7(err, this.contractAddress);
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
/**
|
|
3860
|
+
* Returns all payout IDs associated with a phone hash.
|
|
3861
|
+
*
|
|
3862
|
+
* @param phoneHash - keccak256 of the recipient's encrypted phone bytes
|
|
3863
|
+
* @returns Array of payout IDs (as bytes32 hashes)
|
|
3864
|
+
*/
|
|
3865
|
+
async getPayoutsForPhone(phoneHash) {
|
|
3866
|
+
try {
|
|
3867
|
+
const ids = await this.readContract.read.getPayoutsForPhone([phoneHash]);
|
|
3868
|
+
return ids;
|
|
3869
|
+
} catch (err) {
|
|
3870
|
+
throw wrapError7(err, this.contractAddress);
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
/**
|
|
3874
|
+
* Returns full payout objects that are still pending for a given phone hash.
|
|
3875
|
+
*
|
|
3876
|
+
* Convenience wrapper around `getPayoutsForPhone` + `getPayout` — fetches all
|
|
3877
|
+
* payout IDs for the phone and filters to those with status 'pending'.
|
|
3878
|
+
*
|
|
3879
|
+
* @param phoneHash - keccak256 of the recipient's encrypted phone bytes
|
|
3880
|
+
* @returns Array of pending Payout objects
|
|
3881
|
+
*/
|
|
3882
|
+
async getPendingPayouts(phoneHash) {
|
|
3883
|
+
try {
|
|
3884
|
+
const ids = await this.readContract.read.getPayoutsByStatus([phoneHash, 0]);
|
|
3885
|
+
if (ids.length === 0) return [];
|
|
3886
|
+
const payouts = await Promise.all(
|
|
3887
|
+
ids.map((id) => this.getPayout(id))
|
|
3888
|
+
);
|
|
3889
|
+
return payouts;
|
|
3890
|
+
} catch (err) {
|
|
3891
|
+
throw wrapError7(err, this.contractAddress);
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
/**
|
|
3895
|
+
* Returns all payouts claimable by a user based on their MobileNumberNFT phone hash.
|
|
3896
|
+
*
|
|
3897
|
+
* This is a convenience method: it reads the user's NFT phone hash on-chain (if
|
|
3898
|
+
* the NFT contract is accessible via the escrow's `mobileNumberNFT` reference),
|
|
3899
|
+
* then returns all pending payouts for that phone hash.
|
|
3900
|
+
*
|
|
3901
|
+
* Note: This requires the MobileNumberNFT to be queryable. If the NFT contract
|
|
3902
|
+
* is not set, this will throw. Use `getPendingPayouts(phoneHash)` if you already
|
|
3903
|
+
* know the phone hash.
|
|
3904
|
+
*
|
|
3905
|
+
* @param userAddress - Wallet address of the potential recipient
|
|
3906
|
+
* @returns Array of pending Payout objects claimable by this user
|
|
3907
|
+
*/
|
|
3908
|
+
async getClaimablePayouts(userAddress) {
|
|
3909
|
+
try {
|
|
3910
|
+
const nftAddress = await this.readContract.read.mobileNumberNFT();
|
|
3911
|
+
const tokenId = await this.publicClient.readContract({
|
|
3912
|
+
address: nftAddress,
|
|
3913
|
+
abi: [
|
|
3914
|
+
{
|
|
3915
|
+
type: "function",
|
|
3916
|
+
name: "getTokenId",
|
|
3917
|
+
inputs: [{ name: "user", type: "address", internalType: "address" }],
|
|
3918
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
3919
|
+
stateMutability: "view"
|
|
3920
|
+
}
|
|
3921
|
+
],
|
|
3922
|
+
functionName: "getTokenId",
|
|
3923
|
+
args: [userAddress]
|
|
3924
|
+
});
|
|
3925
|
+
if (tokenId === 0n) return [];
|
|
3926
|
+
const encryptedPhone = await this.publicClient.readContract({
|
|
3927
|
+
address: nftAddress,
|
|
3928
|
+
abi: [
|
|
3929
|
+
{
|
|
3930
|
+
type: "function",
|
|
3931
|
+
name: "getEncryptedPhone",
|
|
3932
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
3933
|
+
outputs: [{ name: "", type: "bytes", internalType: "bytes" }],
|
|
3934
|
+
stateMutability: "view"
|
|
3935
|
+
}
|
|
3936
|
+
],
|
|
3937
|
+
functionName: "getEncryptedPhone",
|
|
3938
|
+
args: [tokenId]
|
|
3939
|
+
});
|
|
3940
|
+
const { keccak256 } = await import('viem');
|
|
3941
|
+
const phoneHash = keccak256(encryptedPhone);
|
|
3942
|
+
return this.getPendingPayouts(phoneHash);
|
|
3943
|
+
} catch (err) {
|
|
3944
|
+
throw wrapError7(err, this.contractAddress);
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
};
|
|
3948
|
+
function mapOrderStatus(status) {
|
|
3949
|
+
switch (status) {
|
|
3950
|
+
case 0:
|
|
3951
|
+
return "open";
|
|
3952
|
+
case 1:
|
|
3953
|
+
return "locked";
|
|
3954
|
+
case 2:
|
|
3955
|
+
return "completed";
|
|
3956
|
+
case 3:
|
|
3957
|
+
return "cancelled";
|
|
3958
|
+
case 4:
|
|
3959
|
+
return "disputed";
|
|
3960
|
+
default:
|
|
3961
|
+
return "open";
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
function mapOrder(raw) {
|
|
3965
|
+
return {
|
|
3966
|
+
id: raw.id,
|
|
3967
|
+
maker: raw.maker,
|
|
3968
|
+
taker: raw.taker,
|
|
3969
|
+
token: raw.token,
|
|
3970
|
+
amount: raw.amount,
|
|
3971
|
+
paymentReference: raw.paymentReference,
|
|
3972
|
+
exchangePlatform: raw.exchangePlatform,
|
|
3973
|
+
status: mapOrderStatus(raw.status),
|
|
3974
|
+
createdAt: raw.createdAt,
|
|
3975
|
+
lockedAt: raw.lockedAt,
|
|
3976
|
+
completedAt: raw.completedAt,
|
|
3977
|
+
expiryDuration: raw.expiryDuration
|
|
3978
|
+
};
|
|
3979
|
+
}
|
|
3980
|
+
function wrapError8(err, contractAddress) {
|
|
3981
|
+
if (err instanceof types.FiatsendError) return err;
|
|
3982
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3983
|
+
if (message.includes("OrderAlreadyExists")) {
|
|
3984
|
+
return new types.FiatsendError("An order with this ID already exists", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3985
|
+
}
|
|
3986
|
+
if (message.includes("OrderNotFound")) {
|
|
3987
|
+
return new types.FiatsendError("Order not found", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
3988
|
+
}
|
|
3989
|
+
if (message.includes("NotMaker")) {
|
|
3990
|
+
return new types.FiatsendError("Only the order maker can perform this action", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
3991
|
+
}
|
|
3992
|
+
if (message.includes("NotParty")) {
|
|
3993
|
+
return new types.FiatsendError("Only the maker or taker can dispute an order", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
3994
|
+
}
|
|
3995
|
+
if (message.includes("NotDisputeResolver")) {
|
|
3996
|
+
return new types.FiatsendError("Only the designated dispute resolver can resolve disputes", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
3997
|
+
}
|
|
3998
|
+
if (message.includes("OrderNotOpen")) {
|
|
3999
|
+
return new types.FiatsendError("Order is not open \u2014 it may have already been taken or cancelled", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
4000
|
+
}
|
|
4001
|
+
if (message.includes("OrderNotLocked")) {
|
|
4002
|
+
return new types.FiatsendError("Order is not locked \u2014 it must be taken before payment can be confirmed", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
4003
|
+
}
|
|
4004
|
+
if (message.includes("OrderNotDisputed")) {
|
|
4005
|
+
return new types.FiatsendError("Order is not in disputed status", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
4006
|
+
}
|
|
4007
|
+
if (message.includes("SelfTake")) {
|
|
4008
|
+
return new types.FiatsendError("Maker cannot take their own order", types.FiatsendErrorCode.UNAUTHORIZED, { contractAddress });
|
|
4009
|
+
}
|
|
4010
|
+
if (message.includes("ZeroAmount")) {
|
|
4011
|
+
return new types.FiatsendError("Amount must be greater than zero", types.FiatsendErrorCode.BELOW_MINIMUM, { contractAddress });
|
|
4012
|
+
}
|
|
4013
|
+
if (message.includes("ZeroExpiryDuration")) {
|
|
4014
|
+
return new types.FiatsendError("Expiry duration must be greater than zero", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
4015
|
+
}
|
|
4016
|
+
if (message.includes("InvalidWinner")) {
|
|
4017
|
+
return new types.FiatsendError("Winner must be either the maker or the taker", types.FiatsendErrorCode.TRANSACTION_FAILED, { contractAddress });
|
|
4018
|
+
}
|
|
4019
|
+
if (message.includes("Paused") || message.includes("EnforcedPause")) {
|
|
4020
|
+
return new types.FiatsendError("P2PExchange is currently paused", types.FiatsendErrorCode.CONTRACT_PAUSED, { contractAddress });
|
|
4021
|
+
}
|
|
4022
|
+
return new types.FiatsendError(message, types.FiatsendErrorCode.TRANSACTION_FAILED, {
|
|
4023
|
+
contractAddress,
|
|
4024
|
+
...err instanceof Error && { cause: err }
|
|
4025
|
+
});
|
|
4026
|
+
}
|
|
4027
|
+
var P2PResource = class {
|
|
4028
|
+
publicClient;
|
|
4029
|
+
walletClient;
|
|
4030
|
+
contractAddress;
|
|
4031
|
+
constructor(params) {
|
|
4032
|
+
this.publicClient = params.publicClient;
|
|
4033
|
+
this.walletClient = params.walletClient;
|
|
4034
|
+
this.contractAddress = params.contractAddress;
|
|
4035
|
+
}
|
|
4036
|
+
get readContract() {
|
|
4037
|
+
return viem.getContract({
|
|
4038
|
+
address: this.contractAddress,
|
|
4039
|
+
abi: P2PExchangeABI,
|
|
4040
|
+
client: this.publicClient
|
|
4041
|
+
});
|
|
4042
|
+
}
|
|
4043
|
+
requireWallet() {
|
|
4044
|
+
if (!this.walletClient) {
|
|
4045
|
+
throw new types.FiatsendError(
|
|
4046
|
+
"A walletClient is required for write operations.",
|
|
4047
|
+
types.FiatsendErrorCode.UNAUTHORIZED
|
|
4048
|
+
);
|
|
4049
|
+
}
|
|
4050
|
+
return this.walletClient;
|
|
4051
|
+
}
|
|
4052
|
+
buildTxResult(hash) {
|
|
4053
|
+
return {
|
|
4054
|
+
hash,
|
|
4055
|
+
wait: async () => {
|
|
4056
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
|
|
4057
|
+
return {
|
|
4058
|
+
hash: receipt.transactionHash,
|
|
4059
|
+
status: receipt.status,
|
|
4060
|
+
blockNumber: receipt.blockNumber,
|
|
4061
|
+
gasUsed: receipt.gasUsed
|
|
4062
|
+
};
|
|
4063
|
+
}
|
|
4064
|
+
};
|
|
4065
|
+
}
|
|
4066
|
+
// ─── Write operations ─────────────────────────────────────────────────────
|
|
4067
|
+
/**
|
|
4068
|
+
* Creates a new P2P order and escrows tokens from the maker.
|
|
4069
|
+
*
|
|
4070
|
+
* The caller must have approved `amount` of `token` to the P2PExchange contract.
|
|
4071
|
+
*
|
|
4072
|
+
* @param params - Order parameters
|
|
4073
|
+
* @returns Transaction result
|
|
4074
|
+
*/
|
|
4075
|
+
async createOrder(params) {
|
|
4076
|
+
try {
|
|
4077
|
+
const wallet = this.requireWallet();
|
|
4078
|
+
const hash = await wallet.writeContract({
|
|
4079
|
+
address: this.contractAddress,
|
|
4080
|
+
abi: P2PExchangeABI,
|
|
4081
|
+
functionName: "createOrder",
|
|
4082
|
+
args: [
|
|
4083
|
+
params.orderId,
|
|
4084
|
+
params.token,
|
|
4085
|
+
params.amount,
|
|
4086
|
+
params.paymentReference,
|
|
4087
|
+
params.exchangePlatform,
|
|
4088
|
+
params.expiryDuration
|
|
4089
|
+
],
|
|
4090
|
+
account: wallet.account,
|
|
4091
|
+
chain: wallet.chain ?? null
|
|
4092
|
+
});
|
|
4093
|
+
return this.buildTxResult(hash);
|
|
4094
|
+
} catch (err) {
|
|
4095
|
+
throw wrapError8(err, this.contractAddress);
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
/**
|
|
4099
|
+
* Locks an open order. Taker commits to pay via the exchange using the payment reference.
|
|
4100
|
+
*
|
|
4101
|
+
* Once taken, the taker must complete the off-chain payment using the exact reference
|
|
4102
|
+
* string from the order. The maker then calls `confirmPayment` to release funds.
|
|
4103
|
+
*
|
|
4104
|
+
* @param orderId - ID of the order to take
|
|
4105
|
+
* @returns Transaction result
|
|
4106
|
+
*/
|
|
4107
|
+
async takeOrder(orderId) {
|
|
4108
|
+
try {
|
|
4109
|
+
const wallet = this.requireWallet();
|
|
4110
|
+
const hash = await wallet.writeContract({
|
|
4111
|
+
address: this.contractAddress,
|
|
4112
|
+
abi: P2PExchangeABI,
|
|
4113
|
+
functionName: "takeOrder",
|
|
4114
|
+
args: [orderId],
|
|
4115
|
+
account: wallet.account,
|
|
4116
|
+
chain: wallet.chain ?? null
|
|
4117
|
+
});
|
|
4118
|
+
return this.buildTxResult(hash);
|
|
4119
|
+
} catch (err) {
|
|
4120
|
+
throw wrapError8(err, this.contractAddress);
|
|
4121
|
+
}
|
|
4122
|
+
}
|
|
4123
|
+
/**
|
|
4124
|
+
* Confirms payment received on the exchange and releases tokens to the taker.
|
|
4125
|
+
*
|
|
4126
|
+
* Only the maker can call this. After confirmation, the escrowed tokens are
|
|
4127
|
+
* transferred to the taker's wallet.
|
|
4128
|
+
*
|
|
4129
|
+
* @param orderId - ID of the locked order to confirm
|
|
4130
|
+
* @returns Transaction result
|
|
4131
|
+
*/
|
|
4132
|
+
async confirmPayment(orderId) {
|
|
4133
|
+
try {
|
|
4134
|
+
const wallet = this.requireWallet();
|
|
4135
|
+
const hash = await wallet.writeContract({
|
|
4136
|
+
address: this.contractAddress,
|
|
4137
|
+
abi: P2PExchangeABI,
|
|
4138
|
+
functionName: "confirmPayment",
|
|
4139
|
+
args: [orderId],
|
|
4140
|
+
account: wallet.account,
|
|
4141
|
+
chain: wallet.chain ?? null
|
|
4142
|
+
});
|
|
4143
|
+
return this.buildTxResult(hash);
|
|
4144
|
+
} catch (err) {
|
|
4145
|
+
throw wrapError8(err, this.contractAddress);
|
|
4146
|
+
}
|
|
4147
|
+
}
|
|
4148
|
+
/**
|
|
4149
|
+
* Cancels an open (not yet taken) order and returns tokens to the maker.
|
|
4150
|
+
*
|
|
4151
|
+
* Only the maker can cancel, and only while the order is still open.
|
|
4152
|
+
*
|
|
4153
|
+
* @param orderId - ID of the open order to cancel
|
|
4154
|
+
* @returns Transaction result
|
|
4155
|
+
*/
|
|
4156
|
+
async cancelOrder(orderId) {
|
|
4157
|
+
try {
|
|
4158
|
+
const wallet = this.requireWallet();
|
|
4159
|
+
const hash = await wallet.writeContract({
|
|
4160
|
+
address: this.contractAddress,
|
|
4161
|
+
abi: P2PExchangeABI,
|
|
4162
|
+
functionName: "cancelOrder",
|
|
4163
|
+
args: [orderId],
|
|
4164
|
+
account: wallet.account,
|
|
4165
|
+
chain: wallet.chain ?? null
|
|
4166
|
+
});
|
|
4167
|
+
return this.buildTxResult(hash);
|
|
4168
|
+
} catch (err) {
|
|
4169
|
+
throw wrapError8(err, this.contractAddress);
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
/**
|
|
4173
|
+
* Raises a dispute on a locked order.
|
|
4174
|
+
*
|
|
4175
|
+
* Either the maker or taker can dispute. Once disputed, the order is frozen
|
|
4176
|
+
* until the designated dispute resolver calls `resolveDispute`.
|
|
4177
|
+
*
|
|
4178
|
+
* @param orderId - ID of the locked order to dispute
|
|
4179
|
+
* @returns Transaction result
|
|
4180
|
+
*/
|
|
4181
|
+
async disputeOrder(orderId) {
|
|
4182
|
+
try {
|
|
4183
|
+
const wallet = this.requireWallet();
|
|
4184
|
+
const hash = await wallet.writeContract({
|
|
4185
|
+
address: this.contractAddress,
|
|
4186
|
+
abi: P2PExchangeABI,
|
|
4187
|
+
functionName: "disputeOrder",
|
|
4188
|
+
args: [orderId],
|
|
4189
|
+
account: wallet.account,
|
|
4190
|
+
chain: wallet.chain ?? null
|
|
4191
|
+
});
|
|
4192
|
+
return this.buildTxResult(hash);
|
|
4193
|
+
} catch (err) {
|
|
4194
|
+
throw wrapError8(err, this.contractAddress);
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
// ─── Read operations ──────────────────────────────────────────────────────
|
|
4198
|
+
/**
|
|
4199
|
+
* Returns the full order struct for a given ID.
|
|
4200
|
+
*
|
|
4201
|
+
* @param orderId - ID of the order to look up
|
|
4202
|
+
* @returns Full P2POrder object with TypeScript-mapped status
|
|
4203
|
+
*/
|
|
4204
|
+
async getOrder(orderId) {
|
|
4205
|
+
try {
|
|
4206
|
+
const raw = await this.readContract.read.getOrder([orderId]);
|
|
4207
|
+
return mapOrder(raw);
|
|
4208
|
+
} catch (err) {
|
|
4209
|
+
throw wrapError8(err, this.contractAddress);
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
/**
|
|
4213
|
+
* Returns all order IDs created by a user.
|
|
4214
|
+
*
|
|
4215
|
+
* @param user - Wallet address of the maker
|
|
4216
|
+
* @returns Array of order IDs (as bytes32 hashes)
|
|
4217
|
+
*/
|
|
4218
|
+
async getUserOrders(user) {
|
|
4219
|
+
try {
|
|
4220
|
+
const ids = await this.readContract.read.getUserOrders([user]);
|
|
4221
|
+
return ids;
|
|
4222
|
+
} catch (err) {
|
|
4223
|
+
throw wrapError8(err, this.contractAddress);
|
|
4224
|
+
}
|
|
4225
|
+
}
|
|
4226
|
+
/**
|
|
4227
|
+
* Returns open order IDs available for taking.
|
|
4228
|
+
*
|
|
4229
|
+
* @param limit - Maximum number of order IDs to return (0 = all)
|
|
4230
|
+
* @returns Array of open order IDs
|
|
4231
|
+
*/
|
|
4232
|
+
async getOpenOrders(limit = 0) {
|
|
4233
|
+
try {
|
|
4234
|
+
const ids = await this.readContract.read.getOpenOrders([BigInt(limit)]);
|
|
4235
|
+
return ids;
|
|
4236
|
+
} catch (err) {
|
|
4237
|
+
throw wrapError8(err, this.contractAddress);
|
|
4238
|
+
}
|
|
4239
|
+
}
|
|
4240
|
+
/**
|
|
4241
|
+
* Returns full order objects for all currently open orders.
|
|
4242
|
+
*
|
|
4243
|
+
* Convenience wrapper around `getOpenOrders` + `getOrder` — fetches all
|
|
4244
|
+
* open order IDs and resolves each to a full P2POrder.
|
|
4245
|
+
*
|
|
4246
|
+
* @param limit - Maximum number of orders to fetch (0 = all)
|
|
4247
|
+
* @returns Array of full P2POrder objects
|
|
4248
|
+
*/
|
|
4249
|
+
async getOpenOrdersDetailed(limit = 0) {
|
|
4250
|
+
try {
|
|
4251
|
+
const ids = await this.getOpenOrders(limit);
|
|
4252
|
+
if (ids.length === 0) return [];
|
|
4253
|
+
return Promise.all(ids.map((id) => this.getOrder(id)));
|
|
4254
|
+
} catch (err) {
|
|
4255
|
+
throw wrapError8(err, this.contractAddress);
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
};
|
|
4259
|
+
|
|
4260
|
+
// src/client.ts
|
|
4261
|
+
var FiatsendClient = class _FiatsendClient {
|
|
4262
|
+
/** Chain configuration used by this client */
|
|
4263
|
+
chainConfig;
|
|
4264
|
+
/** viem PublicClient used for all read operations */
|
|
4265
|
+
publicClient;
|
|
4266
|
+
/** viem WalletClient (optional) used for write operations */
|
|
4267
|
+
walletClient;
|
|
4268
|
+
/** Resolved contract addresses */
|
|
4269
|
+
addresses;
|
|
4270
|
+
// ─── Resources ────────────────────────────────────────────────────────────
|
|
4271
|
+
/** MobileNumberNFT interactions — register, resolve, KYC */
|
|
4272
|
+
identity;
|
|
4273
|
+
/** FiatsendGateway interactions — offramp, onramp, configuration */
|
|
4274
|
+
gateway;
|
|
4275
|
+
/** PaymentRouter interactions — send, sendToPhone, payment requests */
|
|
4276
|
+
payments;
|
|
4277
|
+
/** Withdrawals contract — read-only withdrawal tracking */
|
|
4278
|
+
withdrawals;
|
|
4279
|
+
/** LiquidityPool interactions — deposit, withdraw, claim rewards */
|
|
4280
|
+
liquidity;
|
|
4281
|
+
/** VaultController interactions — deposit, withdraw, claim yield */
|
|
4282
|
+
vaults;
|
|
4283
|
+
/**
|
|
4284
|
+
* PayoutEscrow interactions — core B2B payout claim flow.
|
|
4285
|
+
*
|
|
4286
|
+
* Businesses create payouts; recipients claim via their MobileNumberNFT identity.
|
|
4287
|
+
* Supports single-tx `claimToMoMo` for immediate mobile money delivery.
|
|
4288
|
+
*/
|
|
4289
|
+
payouts;
|
|
4290
|
+
/**
|
|
4291
|
+
* P2PExchange interactions — peer-to-peer exchange with payment references.
|
|
4292
|
+
*
|
|
4293
|
+
* Makers escrow tokens on-chain; takers pay via exchange platforms (Binance P2P,
|
|
4294
|
+
* Paxful, Noones) using the exact payment reference; makers confirm receipt.
|
|
4295
|
+
*/
|
|
4296
|
+
p2p;
|
|
4297
|
+
constructor(config) {
|
|
4298
|
+
this.chainConfig = getChainConfig(config.chain);
|
|
4299
|
+
this.addresses = {
|
|
4300
|
+
...this.chainConfig.contracts,
|
|
4301
|
+
...config.contractAddresses
|
|
4302
|
+
};
|
|
4303
|
+
this.publicClient = config.publicClient ?? viem.createPublicClient({
|
|
4304
|
+
transport: viem.http(config.rpcUrl ?? this.chainConfig.rpcUrl)
|
|
4305
|
+
});
|
|
4306
|
+
this.walletClient = config.walletClient;
|
|
4307
|
+
const walletOpt = this.walletClient !== void 0 ? { walletClient: this.walletClient } : {};
|
|
4308
|
+
this.identity = new IdentityResource({
|
|
4309
|
+
publicClient: this.publicClient,
|
|
4310
|
+
...walletOpt,
|
|
4311
|
+
contractAddress: this.addresses.mobileNumberNFT
|
|
4312
|
+
});
|
|
4313
|
+
this.gateway = new GatewayResource({
|
|
4314
|
+
publicClient: this.publicClient,
|
|
4315
|
+
...walletOpt,
|
|
4316
|
+
contractAddress: this.addresses.gateway
|
|
4317
|
+
});
|
|
4318
|
+
this.payments = new PaymentsResource({
|
|
4319
|
+
publicClient: this.publicClient,
|
|
4320
|
+
...walletOpt,
|
|
4321
|
+
contractAddress: this.addresses.paymentRouter
|
|
4322
|
+
});
|
|
4323
|
+
this.withdrawals = new WithdrawalsResource({
|
|
4324
|
+
publicClient: this.publicClient,
|
|
4325
|
+
contractAddress: this.addresses.withdrawals
|
|
4326
|
+
});
|
|
4327
|
+
this.liquidity = new LiquidityResource({
|
|
4328
|
+
publicClient: this.publicClient,
|
|
4329
|
+
...walletOpt,
|
|
4330
|
+
contractAddress: this.addresses.liquidityPool
|
|
4331
|
+
});
|
|
4332
|
+
this.vaults = new VaultsResource({
|
|
4333
|
+
publicClient: this.publicClient,
|
|
4334
|
+
...walletOpt,
|
|
4335
|
+
contractAddress: this.addresses.vaultController,
|
|
4336
|
+
supportedTokenAddress: this.addresses.ghsFiat
|
|
4337
|
+
});
|
|
4338
|
+
this.payouts = new PayoutsResource({
|
|
4339
|
+
publicClient: this.publicClient,
|
|
4340
|
+
...walletOpt,
|
|
4341
|
+
contractAddress: this.addresses.payoutEscrow
|
|
4342
|
+
});
|
|
4343
|
+
this.p2p = new P2PResource({
|
|
4344
|
+
publicClient: this.publicClient,
|
|
4345
|
+
...walletOpt,
|
|
4346
|
+
contractAddress: this.addresses.p2pExchange
|
|
4347
|
+
});
|
|
4348
|
+
}
|
|
4349
|
+
/**
|
|
4350
|
+
* Convenience: returns a copy of this client with a new walletClient attached.
|
|
4351
|
+
*
|
|
4352
|
+
* Useful when the wallet connects after the client is created.
|
|
4353
|
+
*
|
|
4354
|
+
* @param walletClient - The viem WalletClient to attach
|
|
4355
|
+
*/
|
|
4356
|
+
withWallet(walletClient) {
|
|
4357
|
+
return new _FiatsendClient({
|
|
4358
|
+
chain: this.chainConfig.chainId,
|
|
4359
|
+
publicClient: this.publicClient,
|
|
4360
|
+
walletClient,
|
|
4361
|
+
contractAddresses: this.addresses
|
|
4362
|
+
});
|
|
4363
|
+
}
|
|
4364
|
+
};
|
|
4365
|
+
|
|
4366
|
+
exports.CHAINS = CHAINS;
|
|
4367
|
+
exports.FiatsendClient = FiatsendClient;
|
|
4368
|
+
exports.FiatsendGatewayABI = FiatsendGatewayABI;
|
|
4369
|
+
exports.GHSFIATABI = GHSFIATABI;
|
|
4370
|
+
exports.GatewayResource = GatewayResource;
|
|
4371
|
+
exports.IdentityResource = IdentityResource;
|
|
4372
|
+
exports.LiquidityPoolABI = LiquidityPoolABI;
|
|
4373
|
+
exports.LiquidityResource = LiquidityResource;
|
|
4374
|
+
exports.MobileNumberNFTABI = MobileNumberNFTABI;
|
|
4375
|
+
exports.P2PExchangeABI = P2PExchangeABI;
|
|
4376
|
+
exports.P2PResource = P2PResource;
|
|
4377
|
+
exports.PaymentRouterABI = PaymentRouterABI;
|
|
4378
|
+
exports.PaymentsResource = PaymentsResource;
|
|
4379
|
+
exports.PayoutEscrowABI = PayoutEscrowABI;
|
|
4380
|
+
exports.PayoutsResource = PayoutsResource;
|
|
4381
|
+
exports.VaultControllerABI = VaultControllerABI;
|
|
4382
|
+
exports.VaultsResource = VaultsResource;
|
|
4383
|
+
exports.WithdrawalsABI = WithdrawalsABI;
|
|
4384
|
+
exports.WithdrawalsResource = WithdrawalsResource;
|
|
4385
|
+
exports.getChainConfig = getChainConfig;
|
|
4386
|
+
//# sourceMappingURL=index.js.map
|
|
4387
|
+
//# sourceMappingURL=index.js.map
|