@p2pdotme/sdk 1.0.5 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +103 -41
  2. package/dist/country.cjs +9 -2
  3. package/dist/country.cjs.map +1 -1
  4. package/dist/country.d.cts +35 -10
  5. package/dist/country.d.ts +35 -10
  6. package/dist/country.mjs +6 -2
  7. package/dist/country.mjs.map +1 -1
  8. package/dist/fraud-engine.cjs +52 -48
  9. package/dist/fraud-engine.cjs.map +1 -1
  10. package/dist/fraud-engine.mjs +46 -42
  11. package/dist/fraud-engine.mjs.map +1 -1
  12. package/dist/index.cjs +4 -14
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +41 -36
  15. package/dist/index.d.ts +41 -36
  16. package/dist/index.mjs +4 -12
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/orders.cjs +5961 -0
  19. package/dist/orders.cjs.map +1 -0
  20. package/dist/orders.d.cts +620 -0
  21. package/dist/orders.d.ts +620 -0
  22. package/dist/orders.mjs +5911 -0
  23. package/dist/orders.mjs.map +1 -0
  24. package/dist/prices.cjs +1432 -0
  25. package/dist/prices.cjs.map +1 -0
  26. package/dist/prices.d.cts +109 -0
  27. package/dist/prices.d.ts +109 -0
  28. package/dist/prices.mjs +1404 -0
  29. package/dist/prices.mjs.map +1 -0
  30. package/dist/profile.cjs +899 -69
  31. package/dist/profile.cjs.map +1 -1
  32. package/dist/profile.d.cts +39 -27
  33. package/dist/profile.d.ts +39 -27
  34. package/dist/profile.mjs +892 -62
  35. package/dist/profile.mjs.map +1 -1
  36. package/dist/qr-parsers.cjs +88 -7
  37. package/dist/qr-parsers.cjs.map +1 -1
  38. package/dist/qr-parsers.d.cts +38 -16
  39. package/dist/qr-parsers.d.ts +38 -16
  40. package/dist/qr-parsers.mjs +88 -7
  41. package/dist/qr-parsers.mjs.map +1 -1
  42. package/dist/react.cjs +2955 -1105
  43. package/dist/react.cjs.map +1 -1
  44. package/dist/react.d.cts +384 -104
  45. package/dist/react.d.ts +384 -104
  46. package/dist/react.mjs +2841 -992
  47. package/dist/react.mjs.map +1 -1
  48. package/dist/zkkyc.cjs +405 -24
  49. package/dist/zkkyc.cjs.map +1 -1
  50. package/dist/zkkyc.d.cts +14 -9
  51. package/dist/zkkyc.d.ts +14 -9
  52. package/dist/zkkyc.mjs +405 -24
  53. package/dist/zkkyc.mjs.map +1 -1
  54. package/package.json +12 -12
  55. package/dist/order-routing.cjs +0 -888
  56. package/dist/order-routing.cjs.map +0 -1
  57. package/dist/order-routing.d.cts +0 -68
  58. package/dist/order-routing.d.ts +0 -68
  59. package/dist/order-routing.mjs +0 -860
  60. package/dist/order-routing.mjs.map +0 -1
  61. package/dist/payload.cjs +0 -3168
  62. package/dist/payload.cjs.map +0 -1
  63. package/dist/payload.d.cts +0 -147
  64. package/dist/payload.d.ts +0 -147
  65. package/dist/payload.mjs +0 -3124
  66. package/dist/payload.mjs.map +0 -1
@@ -1,860 +0,0 @@
1
- // src/order-routing/client.ts
2
- import { stringToHex as stringToHex3 } from "viem";
3
-
4
- // src/contracts/abis/index.ts
5
- import { erc20Abi } from "viem";
6
-
7
- // src/contracts/abis/order-flow-facet.ts
8
- var orderFlowFacetAbi = [
9
- {
10
- inputs: [
11
- { internalType: "uint256", name: "circleId", type: "uint256" },
12
- { internalType: "uint256", name: "assignUpto", type: "uint256" },
13
- { internalType: "bytes32", name: "currency", type: "bytes32" },
14
- { internalType: "address", name: "user", type: "address" },
15
- { internalType: "uint256", name: "usdtAmount", type: "uint256" },
16
- { internalType: "uint256", name: "fiatAmount", type: "uint256" },
17
- { internalType: "int256", name: "orderType", type: "int256" },
18
- { internalType: "uint256", name: "preferredPCConfigId", type: "uint256" }
19
- ],
20
- name: "getAssignableMerchantsFromCircle",
21
- outputs: [{ internalType: "address[]", name: "", type: "address[]" }],
22
- stateMutability: "view",
23
- type: "function"
24
- },
25
- {
26
- inputs: [
27
- { internalType: "address", name: "_user", type: "address" },
28
- { internalType: "bytes32", name: "_nativeCurrency", type: "bytes32" }
29
- ],
30
- name: "userTxLimit",
31
- outputs: [
32
- { internalType: "uint256", name: "", type: "uint256" },
33
- { internalType: "uint256", name: "", type: "uint256" }
34
- ],
35
- stateMutability: "view",
36
- type: "function"
37
- }
38
- ];
39
-
40
- // src/contracts/abis/p2p-config-facet.ts
41
- var p2pConfigFacetAbi = [
42
- {
43
- inputs: [
44
- {
45
- internalType: "bytes32",
46
- name: "_currency",
47
- type: "bytes32"
48
- }
49
- ],
50
- name: "getPriceConfig",
51
- outputs: [
52
- {
53
- components: [
54
- {
55
- internalType: "uint256",
56
- name: "buyPrice",
57
- type: "uint256"
58
- },
59
- {
60
- internalType: "uint256",
61
- name: "sellPrice",
62
- type: "uint256"
63
- },
64
- {
65
- internalType: "int256",
66
- name: "buyPriceOffset",
67
- type: "int256"
68
- },
69
- {
70
- internalType: "uint256",
71
- name: "baseSpread",
72
- type: "uint256"
73
- }
74
- ],
75
- internalType: "struct P2pConfigStorage.PriceConfig",
76
- name: "",
77
- type: "tuple"
78
- }
79
- ],
80
- stateMutability: "view",
81
- type: "function"
82
- },
83
- {
84
- inputs: [
85
- {
86
- internalType: "bytes32",
87
- name: "_nativeCurrency",
88
- type: "bytes32"
89
- }
90
- ],
91
- name: "getRpPerUsdtLimitRational",
92
- outputs: [
93
- {
94
- internalType: "uint256",
95
- name: "numerator",
96
- type: "uint256"
97
- },
98
- {
99
- internalType: "uint256",
100
- name: "denominator",
101
- type: "uint256"
102
- }
103
- ],
104
- stateMutability: "view",
105
- type: "function"
106
- }
107
- ];
108
-
109
- // src/contracts/abis/reputation-manager.ts
110
- var reputationManagerAbi = [
111
- {
112
- inputs: [
113
- {
114
- internalType: "string",
115
- name: "_socialName",
116
- type: "string"
117
- },
118
- {
119
- components: [
120
- {
121
- components: [
122
- {
123
- internalType: "string",
124
- name: "provider",
125
- type: "string"
126
- },
127
- {
128
- internalType: "string",
129
- name: "parameters",
130
- type: "string"
131
- },
132
- {
133
- internalType: "string",
134
- name: "context",
135
- type: "string"
136
- }
137
- ],
138
- internalType: "struct IReclaimSDK.ClaimInfo",
139
- name: "claimInfo",
140
- type: "tuple"
141
- },
142
- {
143
- components: [
144
- {
145
- components: [
146
- {
147
- internalType: "bytes32",
148
- name: "identifier",
149
- type: "bytes32"
150
- },
151
- {
152
- internalType: "address",
153
- name: "owner",
154
- type: "address"
155
- },
156
- {
157
- internalType: "uint32",
158
- name: "timestampS",
159
- type: "uint32"
160
- },
161
- {
162
- internalType: "uint32",
163
- name: "epoch",
164
- type: "uint32"
165
- }
166
- ],
167
- internalType: "struct IReclaimSDK.CompleteClaimData",
168
- name: "claim",
169
- type: "tuple"
170
- },
171
- {
172
- internalType: "bytes[]",
173
- name: "signatures",
174
- type: "bytes[]"
175
- }
176
- ],
177
- internalType: "struct IReclaimSDK.SignedClaim",
178
- name: "signedClaim",
179
- type: "tuple"
180
- }
181
- ],
182
- internalType: "struct IReclaimSDK.Proof[]",
183
- name: "proofs",
184
- type: "tuple[]"
185
- }
186
- ],
187
- name: "socialVerify",
188
- outputs: [],
189
- stateMutability: "nonpayable",
190
- type: "function"
191
- },
192
- {
193
- inputs: [
194
- {
195
- internalType: "uint256",
196
- name: "nullifierSeed",
197
- type: "uint256"
198
- },
199
- {
200
- internalType: "uint256",
201
- name: "nullifier",
202
- type: "uint256"
203
- },
204
- {
205
- internalType: "uint256",
206
- name: "timestamp",
207
- type: "uint256"
208
- },
209
- {
210
- internalType: "uint256",
211
- name: "signal",
212
- type: "uint256"
213
- },
214
- {
215
- internalType: "uint256[4]",
216
- name: "revealArray",
217
- type: "uint256[4]"
218
- },
219
- {
220
- internalType: "uint256[8]",
221
- name: "groth16Proof",
222
- type: "uint256[8]"
223
- }
224
- ],
225
- name: "submitAnonAadharProof",
226
- outputs: [],
227
- stateMutability: "nonpayable",
228
- type: "function"
229
- },
230
- {
231
- inputs: [
232
- {
233
- components: [
234
- {
235
- internalType: "bytes32",
236
- name: "version",
237
- type: "bytes32"
238
- },
239
- {
240
- components: [
241
- {
242
- internalType: "bytes32",
243
- name: "vkeyHash",
244
- type: "bytes32"
245
- },
246
- {
247
- internalType: "bytes",
248
- name: "proof",
249
- type: "bytes"
250
- },
251
- {
252
- internalType: "bytes32[]",
253
- name: "publicInputs",
254
- type: "bytes32[]"
255
- }
256
- ],
257
- internalType: "struct ProofVerificationData",
258
- name: "proofVerificationData",
259
- type: "tuple"
260
- },
261
- {
262
- internalType: "bytes",
263
- name: "committedInputs",
264
- type: "bytes"
265
- },
266
- {
267
- components: [
268
- {
269
- internalType: "uint256",
270
- name: "validityPeriodInSeconds",
271
- type: "uint256"
272
- },
273
- {
274
- internalType: "string",
275
- name: "domain",
276
- type: "string"
277
- },
278
- {
279
- internalType: "string",
280
- name: "scope",
281
- type: "string"
282
- },
283
- {
284
- internalType: "bool",
285
- name: "devMode",
286
- type: "bool"
287
- }
288
- ],
289
- internalType: "struct ServiceConfig",
290
- name: "serviceConfig",
291
- type: "tuple"
292
- }
293
- ],
294
- internalType: "struct ProofVerificationParams",
295
- name: "params",
296
- type: "tuple"
297
- },
298
- {
299
- internalType: "bool",
300
- name: "isIDCard",
301
- type: "bool"
302
- }
303
- ],
304
- name: "zkPassportRegister",
305
- outputs: [],
306
- stateMutability: "nonpayable",
307
- type: "function"
308
- }
309
- ];
310
-
311
- // src/contracts/abis/index.ts
312
- var DIAMOND_ABI = [...orderFlowFacetAbi, ...p2pConfigFacetAbi];
313
- var ABIS = {
314
- DIAMOND: DIAMOND_ABI,
315
- FACETS: {
316
- ORDER_FLOW: orderFlowFacetAbi,
317
- CONFIG: p2pConfigFacetAbi
318
- },
319
- EXTERNAL: {
320
- USDC: erc20Abi,
321
- REPUTATION_MANAGER: reputationManagerAbi
322
- }
323
- };
324
-
325
- // src/contracts/order-flow/index.ts
326
- import { ResultAsync } from "neverthrow";
327
-
328
- // src/lib/logger.ts
329
- var noop = () => {
330
- };
331
- var noopLogger = {
332
- debug: noop,
333
- info: noop,
334
- warn: noop,
335
- error: noop
336
- };
337
-
338
- // src/lib/sleep.ts
339
- function sleep(ms) {
340
- return new Promise((resolve) => setTimeout(resolve, ms));
341
- }
342
-
343
- // src/validation/errors.validation.ts
344
- var SdkError = class extends Error {
345
- code;
346
- cause;
347
- context;
348
- constructor(message, options) {
349
- super(message);
350
- this.name = "SdkError";
351
- this.code = options.code;
352
- this.cause = options.cause;
353
- this.context = options.context;
354
- }
355
- };
356
-
357
- // src/validation/schemas.validation.ts
358
- import { err, ok } from "neverthrow";
359
- import { isAddress } from "viem";
360
- import { z } from "zod";
361
-
362
- // src/constants/currencies.constant.ts
363
- var CURRENCY = {
364
- IDR: "IDR",
365
- INR: "INR",
366
- BRL: "BRL",
367
- ARS: "ARS",
368
- MEX: "MEX",
369
- VEN: "VEN",
370
- EUR: "EUR",
371
- NGN: "NGN",
372
- USD: "USD",
373
- COP: "COP"
374
- };
375
-
376
- // src/validation/schemas.validation.ts
377
- var ZodAddressSchema = z.string().refine((s) => isAddress(s), { message: "Invalid Ethereum address" });
378
- var ZodCurrencySchema = z.enum(Object.values(CURRENCY));
379
- function validate(schema, data, toError) {
380
- const result = schema.safeParse(data);
381
- if (result.success) {
382
- return ok(result.data);
383
- }
384
- return err(toError(z.prettifyError(result.error), result.error, data));
385
- }
386
-
387
- // src/order-routing/errors.ts
388
- var OrderRoutingError = class extends SdkError {
389
- constructor(message, options) {
390
- super(message, options);
391
- this.name = "OrderRoutingError";
392
- }
393
- };
394
-
395
- // src/order-routing/validation.ts
396
- import { z as z2 } from "zod";
397
- var ZodCircleScoreStateSchema = z2.object({
398
- activeMerchantsCount: z2.coerce.number()
399
- });
400
- var ZodCircleMetricsForRoutingSchema = z2.object({
401
- circleScore: z2.coerce.number(),
402
- circleStatus: z2.string(),
403
- scoreState: ZodCircleScoreStateSchema
404
- });
405
- var ZodCircleForRoutingSchema = z2.object({
406
- circleId: z2.string(),
407
- currency: z2.string(),
408
- metrics: ZodCircleMetricsForRoutingSchema
409
- });
410
- var ZodCirclesForRoutingResponseSchema = z2.object({
411
- circles: z2.array(ZodCircleForRoutingSchema)
412
- });
413
- var ZodCheckCircleEligibilityParamsSchema = z2.object({
414
- circleId: z2.bigint(),
415
- currency: z2.string(),
416
- user: ZodAddressSchema,
417
- usdtAmount: z2.bigint(),
418
- fiatAmount: z2.bigint(),
419
- orderType: z2.bigint(),
420
- preferredPCConfigId: z2.bigint()
421
- });
422
- var ZodSelectCircleParamsSchema = z2.object({
423
- currency: z2.string().min(1),
424
- user: ZodAddressSchema,
425
- usdtAmount: z2.bigint(),
426
- fiatAmount: z2.bigint(),
427
- orderType: z2.bigint(),
428
- preferredPCConfigId: z2.bigint()
429
- });
430
-
431
- // src/contracts/order-flow/index.ts
432
- function checkCircleEligibility(publicClient, contractAddress, params, logger = noopLogger) {
433
- return validate(
434
- ZodCheckCircleEligibilityParamsSchema,
435
- params,
436
- (message, cause, d) => new OrderRoutingError(message, { code: "VALIDATION_ERROR", cause, context: { data: d } })
437
- ).asyncAndThen((validated) => {
438
- logger.debug("checking on-chain eligibility", {
439
- circleId: String(validated.circleId),
440
- contractAddress
441
- });
442
- return ResultAsync.fromPromise(
443
- publicClient.readContract({
444
- address: contractAddress,
445
- abi: ABIS.FACETS.ORDER_FLOW,
446
- functionName: "getAssignableMerchantsFromCircle",
447
- args: [
448
- validated.circleId,
449
- 1n,
450
- validated.currency,
451
- validated.user,
452
- validated.usdtAmount,
453
- validated.fiatAmount,
454
- validated.orderType,
455
- validated.preferredPCConfigId
456
- ]
457
- }),
458
- (error) => new OrderRoutingError("Eligibility check failed", {
459
- code: "CONTRACT_READ_ERROR",
460
- cause: error,
461
- context: { circleId: String(params.circleId) }
462
- })
463
- );
464
- }).map((merchants) => {
465
- const arr = merchants;
466
- const eligible = arr.length >= 1;
467
- logger.debug("eligibility check result", {
468
- circleId: String(params.circleId),
469
- assignableMerchants: arr.length,
470
- eligible
471
- });
472
- return eligible;
473
- });
474
- }
475
-
476
- // src/contracts/p2p-config/index.ts
477
- import { ResultAsync as ResultAsync2 } from "neverthrow";
478
- import { stringToHex } from "viem";
479
-
480
- // src/profile/validation.ts
481
- import { z as z3 } from "zod";
482
- var ZodUsdcBalanceParamsSchema = z3.object({
483
- address: ZodAddressSchema
484
- });
485
- var ZodGetBalancesParamsSchema = z3.object({
486
- address: ZodAddressSchema,
487
- currency: ZodCurrencySchema
488
- });
489
- var ZodTxLimitsParamsSchema = z3.object({
490
- address: ZodAddressSchema,
491
- currency: ZodCurrencySchema
492
- });
493
- var ZodPriceConfigParamsSchema = z3.object({
494
- currency: ZodCurrencySchema
495
- });
496
-
497
- // src/contracts/reputation-manager/writes.ts
498
- import { Result } from "neverthrow";
499
- import { encodeFunctionData } from "viem";
500
-
501
- // src/zkkyc/validation.ts
502
- import { z as z4 } from "zod";
503
- var ZodAnonAadharProofParamsSchema = z4.object({
504
- nullifierSeed: z4.bigint(),
505
- nullifier: z4.bigint(),
506
- timestamp: z4.bigint(),
507
- signal: z4.bigint(),
508
- revealArray: z4.tuple([z4.bigint(), z4.bigint(), z4.bigint(), z4.bigint()]),
509
- packedGroth16Proof: z4.tuple([
510
- z4.bigint(),
511
- z4.bigint(),
512
- z4.bigint(),
513
- z4.bigint(),
514
- z4.bigint(),
515
- z4.bigint(),
516
- z4.bigint(),
517
- z4.bigint()
518
- ])
519
- });
520
- var ZodSocialVerifyParamsSchema = z4.object({
521
- _socialName: z4.string(),
522
- proofs: z4.array(
523
- z4.object({
524
- claimInfo: z4.object({
525
- provider: z4.string(),
526
- parameters: z4.string(),
527
- context: z4.string()
528
- }),
529
- signedClaim: z4.object({
530
- claim: z4.object({
531
- identifier: z4.string(),
532
- owner: ZodAddressSchema,
533
- timestampS: z4.number(),
534
- epoch: z4.number()
535
- }),
536
- signatures: z4.array(z4.string())
537
- })
538
- })
539
- )
540
- });
541
- var ZodSolidityVerifierParametersSchema = z4.object({
542
- version: z4.string().refine((val) => val.startsWith("0x"), {
543
- message: "Version must be a hex string"
544
- }),
545
- proofVerificationData: z4.object({
546
- vkeyHash: z4.string().refine((val) => /^0x[a-fA-F0-9]{64}$/.test(val), {
547
- message: "Invalid bytes32 hex string"
548
- }),
549
- proof: z4.string().refine((val) => val.startsWith("0x"), {
550
- message: "Proof must be a hex string"
551
- }),
552
- publicInputs: z4.array(
553
- z4.string().refine((val) => /^0x[a-fA-F0-9]{64}$/.test(val), {
554
- message: "Each public input must be a valid bytes32 hex string"
555
- })
556
- )
557
- }),
558
- committedInputs: z4.string().refine((val) => val.startsWith("0x"), {
559
- message: "Committed inputs must be a hex string"
560
- }),
561
- serviceConfig: z4.object({
562
- validityPeriodInSeconds: z4.number().int().nonnegative(),
563
- domain: z4.string(),
564
- scope: z4.string(),
565
- devMode: z4.boolean()
566
- })
567
- });
568
- var ZodZkPassportRegisterParamsSchema = z4.object({
569
- params: ZodSolidityVerifierParametersSchema,
570
- isIDCard: z4.boolean()
571
- });
572
-
573
- // src/contracts/tx-limits/index.ts
574
- import { ResultAsync as ResultAsync3 } from "neverthrow";
575
- import { formatUnits, stringToHex as stringToHex2 } from "viem";
576
-
577
- // src/contracts/usdc/index.ts
578
- import { ResultAsync as ResultAsync4 } from "neverthrow";
579
-
580
- // src/order-routing/routing.ts
581
- import { errAsync, okAsync } from "neverthrow";
582
- var EPSILON = 0.25;
583
- var RECOVERY_SCALE = 0.3;
584
- var BOOTSTRAP_MAX_WEIGHT = 25;
585
- var MAX_VALIDATION_ATTEMPTS = 3;
586
- function circleWeight(c) {
587
- const score = c.metrics.circleScore;
588
- if (c.metrics.circleStatus === "paused") {
589
- return score * RECOVERY_SCALE;
590
- }
591
- if (c.metrics.circleStatus === "bootstrap") {
592
- return Math.min(score, BOOTSTRAP_MAX_WEIGHT);
593
- }
594
- return score;
595
- }
596
- function filterEligibleCircles(circles, orderCurrency) {
597
- return circles.filter((c) => c.currency.toLowerCase() === orderCurrency.toLowerCase());
598
- }
599
- function weightedRandomChoice(arr, weights) {
600
- const totalWeight = weights.reduce((sum, w) => sum + w, 0);
601
- if (totalWeight === 0) {
602
- return arr[Math.floor(Math.random() * arr.length)];
603
- }
604
- let rand = Math.random() * totalWeight;
605
- for (let i = 0; i < arr.length; i++) {
606
- rand -= weights[i];
607
- if (rand <= 0) {
608
- return arr[i];
609
- }
610
- }
611
- return arr[arr.length - 1];
612
- }
613
- function selectCircle(eligible) {
614
- if (eligible.length === 0) {
615
- return null;
616
- }
617
- const activeCircles = eligible.filter((c) => c.metrics.circleStatus === "active");
618
- const isExplore = Math.random() < EPSILON;
619
- if (isExplore) {
620
- const weights2 = eligible.map(circleWeight);
621
- return weightedRandomChoice(eligible, weights2);
622
- }
623
- if (activeCircles.length === 0) {
624
- const weights2 = eligible.map(circleWeight);
625
- return weightedRandomChoice(eligible, weights2);
626
- }
627
- const weights = activeCircles.map((c) => c.metrics.circleScore);
628
- return weightedRandomChoice(activeCircles, weights);
629
- }
630
- function selectCircleForOrderAsync(circles, orderCurrency, validateCircle, logger = noopLogger) {
631
- const eligible = filterEligibleCircles(circles, orderCurrency);
632
- let remaining = [...eligible];
633
- logger.debug("filtering eligible circles", {
634
- total: circles.length,
635
- eligible: eligible.length,
636
- currency: orderCurrency,
637
- circles: eligible
638
- });
639
- if (eligible.length === 0) {
640
- logger.warn("no eligible circles found for currency", { currency: orderCurrency });
641
- }
642
- function attempt(attemptsLeft) {
643
- if (attemptsLeft <= 0 || remaining.length === 0) {
644
- logger.warn("exhausted all attempts or circles", {
645
- attemptsLeft,
646
- remainingCircles: remaining.length
647
- });
648
- return errAsync(
649
- new OrderRoutingError("No eligible circles found", {
650
- code: "NO_ELIGIBLE_CIRCLES"
651
- })
652
- );
653
- }
654
- const selected = selectCircle(remaining);
655
- if (!selected) {
656
- return errAsync(
657
- new OrderRoutingError("No eligible circles found", {
658
- code: "NO_ELIGIBLE_CIRCLES"
659
- })
660
- );
661
- }
662
- const circleId = BigInt(selected.circleId);
663
- logger.debug("selected circle, validating on-chain", {
664
- circleId: String(circleId),
665
- status: selected.metrics.circleStatus,
666
- score: selected.metrics.circleScore,
667
- attemptsLeft
668
- });
669
- return validateCircle(circleId).orElse((error) => {
670
- logger.warn("validation errored, treating as ineligible", {
671
- circleId: String(circleId),
672
- error: String(error)
673
- });
674
- return okAsync(false);
675
- }).andThen((isValid) => {
676
- if (isValid) {
677
- logger.info("circle validated successfully", { circleId: String(circleId) });
678
- return okAsync(circleId);
679
- }
680
- logger.debug("circle failed validation, retrying", {
681
- circleId: String(circleId),
682
- remainingCircles: remaining.length - 1
683
- });
684
- remaining = remaining.filter((c) => c.circleId !== selected.circleId);
685
- return attempt(attemptsLeft - 1);
686
- });
687
- }
688
- return attempt(MAX_VALIDATION_ATTEMPTS);
689
- }
690
-
691
- // src/order-routing/subgraph/client.ts
692
- import { ResultAsync as ResultAsync5 } from "neverthrow";
693
- var DEFAULT_TIMEOUT_MS = 1e4;
694
- var MAX_RETRIES = 3;
695
- var BACKOFF_MS = 500;
696
- function isTransient(error) {
697
- if (error instanceof OrderRoutingError) return false;
698
- if (error instanceof DOMException && error.name === "AbortError") return true;
699
- if (error instanceof TypeError) return true;
700
- return false;
701
- }
702
- function querySubgraph(url, params) {
703
- const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
704
- const fetchOnce = async () => {
705
- const controller = new AbortController();
706
- const timer = setTimeout(() => controller.abort(), timeoutMs);
707
- try {
708
- const response = await fetch(url, {
709
- method: "POST",
710
- headers: { "Content-Type": "application/json" },
711
- body: JSON.stringify({
712
- query: params.query,
713
- variables: params.variables
714
- }),
715
- signal: controller.signal
716
- });
717
- if (!response.ok) {
718
- throw new OrderRoutingError(`Subgraph request failed (status: ${response.status})`, {
719
- code: "SUBGRAPH_ERROR",
720
- cause: response,
721
- context: { status: response.status }
722
- });
723
- }
724
- const json = await response.json();
725
- if (json.errors?.length > 0) {
726
- throw new OrderRoutingError("Subgraph returned GraphQL errors", {
727
- code: "SUBGRAPH_ERROR",
728
- cause: json.errors,
729
- context: { errors: json.errors }
730
- });
731
- }
732
- if (!json.data) {
733
- throw new OrderRoutingError("Subgraph returned no data", {
734
- code: "SUBGRAPH_ERROR",
735
- cause: "Missing data field in GraphQL response",
736
- context: { response: json }
737
- });
738
- }
739
- return json.data;
740
- } finally {
741
- clearTimeout(timer);
742
- }
743
- };
744
- const fetchWithRetry = async () => {
745
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
746
- try {
747
- return await fetchOnce();
748
- } catch (error) {
749
- const lastAttempt = attempt === MAX_RETRIES;
750
- if (lastAttempt || !isTransient(error)) throw error;
751
- await sleep(BACKOFF_MS * (attempt + 1));
752
- }
753
- }
754
- throw new OrderRoutingError("Subgraph query exhausted retries", {
755
- code: "SUBGRAPH_ERROR"
756
- });
757
- };
758
- return ResultAsync5.fromPromise(
759
- fetchWithRetry(),
760
- (error) => error instanceof OrderRoutingError ? error : new OrderRoutingError("Subgraph query failed", {
761
- code: "SUBGRAPH_ERROR",
762
- cause: error
763
- })
764
- );
765
- }
766
-
767
- // src/order-routing/subgraph/queries.ts
768
- var CIRCLES_FOR_ROUTING_QUERY = (
769
- /* GraphQL */
770
- `
771
- query CirclesForRouting($currency: Bytes!) {
772
- circles(
773
- first: 1000
774
- where: {
775
- currency: $currency
776
- metrics_: {
777
- circleStatus_in: ["active", "bootstrap", "paused"]
778
- }
779
- }
780
- ) {
781
- circleId
782
- currency
783
- metrics {
784
- circleScore
785
- circleStatus
786
- scoreState {
787
- activeMerchantsCount
788
- }
789
- }
790
- }
791
- }
792
- `
793
- );
794
-
795
- // src/order-routing/subgraph/index.ts
796
- function getCirclesForRouting(subgraphUrl, currency, logger = noopLogger) {
797
- logger.debug("fetching circles from subgraph", { subgraphUrl, currency });
798
- return querySubgraph(subgraphUrl, {
799
- query: CIRCLES_FOR_ROUTING_QUERY,
800
- variables: { currency }
801
- }).andThen(
802
- (data) => validate(
803
- ZodCirclesForRoutingResponseSchema,
804
- data,
805
- (message, cause, d) => new OrderRoutingError(message, { code: "VALIDATION_ERROR", cause, context: { data: d } })
806
- ).map((validated) => {
807
- const circles = validated.circles.filter(
808
- (item) => Number(item.metrics.scoreState.activeMerchantsCount) > 0
809
- );
810
- logger.info("fetched circles from subgraph", {
811
- total: validated.circles.length,
812
- withActiveMerchants: circles.length,
813
- circles
814
- });
815
- return circles;
816
- })
817
- );
818
- }
819
-
820
- // src/order-routing/client.ts
821
- function createOrderRouter(config) {
822
- const { subgraphUrl, publicClient, contractAddress } = config;
823
- const logger = config.logger ?? noopLogger;
824
- return {
825
- selectCircle(params) {
826
- const currencyHex = stringToHex3(params.currency, { size: 32 });
827
- logger.info("selectCircle started", {
828
- currency: params.currency,
829
- user: params.user,
830
- orderType: String(params.orderType)
831
- });
832
- return getCirclesForRouting(subgraphUrl, currencyHex, logger).andThen(
833
- (circles) => selectCircleForOrderAsync(
834
- circles,
835
- currencyHex,
836
- (circleId) => checkCircleEligibility(
837
- publicClient,
838
- contractAddress,
839
- {
840
- circleId,
841
- currency: currencyHex,
842
- user: params.user,
843
- usdtAmount: params.usdtAmount,
844
- fiatAmount: params.fiatAmount,
845
- orderType: params.orderType,
846
- preferredPCConfigId: params.preferredPCConfigId
847
- },
848
- logger
849
- ),
850
- logger
851
- )
852
- );
853
- }
854
- };
855
- }
856
- export {
857
- OrderRoutingError,
858
- createOrderRouter
859
- };
860
- //# sourceMappingURL=order-routing.mjs.map