@usdctofiat/offramp 1.0.0 → 1.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.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -25,12 +35,15 @@ __export(index_exports, {
25
35
  PLATFORMS: () => PLATFORMS,
26
36
  close: () => close,
27
37
  deposits: () => deposits,
38
+ disableOtc: () => disableOtc,
39
+ enableOtc: () => enableOtc,
40
+ getOtcLink: () => getOtcLink,
28
41
  offramp: () => offramp
29
42
  });
30
43
  module.exports = __toCommonJS(index_exports);
31
44
 
32
45
  // src/deposit.ts
33
- var import_viem2 = require("viem");
46
+ var import_viem3 = require("viem");
34
47
  var import_chains = require("viem/chains");
35
48
  var import_sdk4 = require("@zkp2p/sdk");
36
49
 
@@ -45,7 +58,10 @@ var addresses = contracts.addresses;
45
58
  var addrs = addresses;
46
59
  var USDC_ADDRESS = addrs.token || "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
47
60
  var ESCROW_ADDRESS = addrs.escrowV2 || addrs.escrow || "";
48
- var GATING_SERVICE_ADDRESS = (0, import_sdk.getGatingServiceAddress)(BASE_CHAIN_ID, RUNTIME_ENV);
61
+ var GATING_SERVICE_ADDRESS = (0, import_sdk.getGatingServiceAddress)(
62
+ BASE_CHAIN_ID,
63
+ RUNTIME_ENV
64
+ );
49
65
  var DELEGATE_RATE_MANAGER_ID = "0x8666d6fb0f6797c56e95339fd7ca82fdd348b9db200e10a4c4aa0a0b879fc41c";
50
66
  var RATE_MANAGER_REGISTRY_ADDRESS = "0xeed7db23e724ac4590d6db6f78fda6db203535f3";
51
67
  var REFERRER = "galleonlabs";
@@ -65,8 +81,64 @@ var FALLBACK_CURRENCIES = {
65
81
  venmo: ["USD"],
66
82
  cashapp: ["USD"],
67
83
  chime: ["USD"],
68
- revolut: ["USD", "EUR", "GBP", "SGD", "NZD", "AUD", "CAD", "HKD", "MXN", "SAR", "AED", "THB", "TRY", "PLN", "CHF", "ZAR", "CZK", "CNY", "DKK", "HUF", "NOK", "RON", "SEK"],
69
- wise: ["USD", "CNY", "EUR", "GBP", "AUD", "NZD", "CAD", "AED", "CHF", "ZAR", "SGD", "ILS", "HKD", "JPY", "PLN", "TRY", "IDR", "KES", "MYR", "MXN", "THB", "VND", "UGX", "CZK", "DKK", "HUF", "INR", "NOK", "PHP", "RON", "SEK"],
84
+ revolut: [
85
+ "USD",
86
+ "EUR",
87
+ "GBP",
88
+ "SGD",
89
+ "NZD",
90
+ "AUD",
91
+ "CAD",
92
+ "HKD",
93
+ "MXN",
94
+ "SAR",
95
+ "AED",
96
+ "THB",
97
+ "TRY",
98
+ "PLN",
99
+ "CHF",
100
+ "ZAR",
101
+ "CZK",
102
+ "CNY",
103
+ "DKK",
104
+ "HUF",
105
+ "NOK",
106
+ "RON",
107
+ "SEK"
108
+ ],
109
+ wise: [
110
+ "USD",
111
+ "CNY",
112
+ "EUR",
113
+ "GBP",
114
+ "AUD",
115
+ "NZD",
116
+ "CAD",
117
+ "AED",
118
+ "CHF",
119
+ "ZAR",
120
+ "SGD",
121
+ "ILS",
122
+ "HKD",
123
+ "JPY",
124
+ "PLN",
125
+ "TRY",
126
+ "IDR",
127
+ "KES",
128
+ "MYR",
129
+ "MXN",
130
+ "THB",
131
+ "VND",
132
+ "UGX",
133
+ "CZK",
134
+ "DKK",
135
+ "HUF",
136
+ "INR",
137
+ "NOK",
138
+ "PHP",
139
+ "RON",
140
+ "SEK"
141
+ ],
70
142
  mercadopago: ["ARS"],
71
143
  zelle: ["USD"],
72
144
  paypal: ["USD", "EUR", "GBP", "SGD", "NZD", "AUD", "CAD"],
@@ -93,19 +165,95 @@ function resolveSupportedCurrencies(platform) {
93
165
  return Array.from(codes).sort();
94
166
  }
95
167
  var BLUEPRINTS = {
96
- venmo: { id: "venmo", name: "Venmo", identifierLabel: "Username", placeholder: "venmo username (no @)", helperText: "Username without @ (publicly discoverable)", validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/), transform: (v) => v.replace(/^@+/, "") },
97
- cashapp: { id: "cashapp", name: "Cash App", identifierLabel: "Cashtag", placeholder: "cashtag (no $)", helperText: "Cashtag without $ (publicly discoverable)", validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9]+$/), transform: (v) => v.replace(/^\$+/, "") },
98
- chime: { id: "chime", name: "Chime", identifierLabel: "ChimeSign", placeholder: "$chimesign", helperText: "ChimeSign with $ (must be discoverable)", validation: import_zod.z.string().min(2).regex(/^\$[a-zA-Z0-9]+$/), transform: (v) => {
99
- const t = v.trim().toLowerCase();
100
- return t.startsWith("$") ? t : `$${t}`;
101
- } },
102
- revolut: { id: "revolut", name: "Revolut", identifierLabel: "Revtag", placeholder: "revtag (no @)", helperText: "Revtag without @ (must be public)", validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9]+$/), transform: (v) => v.replace(/^@+/, "").trim() },
103
- wise: { id: "wise", name: "Wise", identifierLabel: "Wisetag", placeholder: "wisetag (no @)", helperText: "Your Wise @wisetag (no @)", validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/), transform: (v) => v.replace(/^@+/, "").trim() },
104
- mercadopago: { id: "mercadopago", name: "Mercado Pago", identifierLabel: "CVU", placeholder: "22-digit CVU", helperText: "CVU must be exactly 22 digits", validation: import_zod.z.string().length(22).regex(/^\d{22}$/) },
105
- zelle: { id: "zelle", name: "Zelle", identifierLabel: "Email", placeholder: "email", helperText: "Registered Zelle email", validation: import_zod.z.string().email() },
106
- paypal: { id: "paypal", name: "PayPal", identifierLabel: "Email", placeholder: "email", helperText: "Email linked to PayPal account", validation: import_zod.z.string().email() },
107
- monzo: { id: "monzo", name: "Monzo", identifierLabel: "Username", placeholder: "monzo.me username", helperText: "Your Monzo.me username", validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/) },
108
- n26: { id: "n26", name: "N26", identifierLabel: "IBAN", placeholder: "IBAN (e.g. DE89...)", helperText: "Your IBAN (spaces will be removed)", validation: import_zod.z.string().min(15).max(34).regex(/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/i), transform: (v) => v.replace(/\s/g, "").toUpperCase() }
168
+ venmo: {
169
+ id: "venmo",
170
+ name: "Venmo",
171
+ identifierLabel: "Username",
172
+ placeholder: "venmo username (no @)",
173
+ helperText: "Username without @ (publicly discoverable)",
174
+ validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/),
175
+ transform: (v) => v.replace(/^@+/, "")
176
+ },
177
+ cashapp: {
178
+ id: "cashapp",
179
+ name: "Cash App",
180
+ identifierLabel: "Cashtag",
181
+ placeholder: "cashtag (no $)",
182
+ helperText: "Cashtag without $ (publicly discoverable)",
183
+ validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9]+$/),
184
+ transform: (v) => v.replace(/^\$+/, "")
185
+ },
186
+ chime: {
187
+ id: "chime",
188
+ name: "Chime",
189
+ identifierLabel: "ChimeSign",
190
+ placeholder: "$chimesign",
191
+ helperText: "ChimeSign with $ (must be discoverable)",
192
+ validation: import_zod.z.string().min(2).regex(/^\$[a-zA-Z0-9]+$/),
193
+ transform: (v) => {
194
+ const t = v.trim().toLowerCase();
195
+ return t.startsWith("$") ? t : `$${t}`;
196
+ }
197
+ },
198
+ revolut: {
199
+ id: "revolut",
200
+ name: "Revolut",
201
+ identifierLabel: "Revtag",
202
+ placeholder: "revtag (no @)",
203
+ helperText: "Revtag without @ (must be public)",
204
+ validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9]+$/),
205
+ transform: (v) => v.replace(/^@+/, "").trim()
206
+ },
207
+ wise: {
208
+ id: "wise",
209
+ name: "Wise",
210
+ identifierLabel: "Wisetag",
211
+ placeholder: "wisetag (no @)",
212
+ helperText: "Your Wise @wisetag (no @)",
213
+ validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/),
214
+ transform: (v) => v.replace(/^@+/, "").trim()
215
+ },
216
+ mercadopago: {
217
+ id: "mercadopago",
218
+ name: "Mercado Pago",
219
+ identifierLabel: "CVU",
220
+ placeholder: "22-digit CVU",
221
+ helperText: "CVU must be exactly 22 digits",
222
+ validation: import_zod.z.string().length(22).regex(/^\d{22}$/)
223
+ },
224
+ zelle: {
225
+ id: "zelle",
226
+ name: "Zelle",
227
+ identifierLabel: "Email",
228
+ placeholder: "email",
229
+ helperText: "Registered Zelle email",
230
+ validation: import_zod.z.string().email()
231
+ },
232
+ paypal: {
233
+ id: "paypal",
234
+ name: "PayPal",
235
+ identifierLabel: "Email",
236
+ placeholder: "email",
237
+ helperText: "Email linked to PayPal account",
238
+ validation: import_zod.z.string().email()
239
+ },
240
+ monzo: {
241
+ id: "monzo",
242
+ name: "Monzo",
243
+ identifierLabel: "Username",
244
+ placeholder: "monzo.me username",
245
+ helperText: "Your Monzo.me username",
246
+ validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/)
247
+ },
248
+ n26: {
249
+ id: "n26",
250
+ name: "N26",
251
+ identifierLabel: "IBAN",
252
+ placeholder: "IBAN (e.g. DE89...)",
253
+ helperText: "Your IBAN (spaces will be removed)",
254
+ validation: import_zod.z.string().min(15).max(34).regex(/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/i),
255
+ transform: (v) => v.replace(/\s/g, "").toUpperCase()
256
+ }
109
257
  };
110
258
  function buildPlatformEntry(bp) {
111
259
  const currencies = resolveSupportedCurrencies(bp.id);
@@ -122,7 +270,11 @@ function buildPlatformEntry(bp) {
122
270
  const transformed = bp.transform ? bp.transform(input) : input;
123
271
  const result = bp.validation.safeParse(transformed);
124
272
  if (!result.success) {
125
- return { valid: false, normalized: transformed, error: result.error.issues[0]?.message || "Invalid input" };
273
+ return {
274
+ valid: false,
275
+ normalized: transformed,
276
+ error: result.error.issues[0]?.message || "Invalid input"
277
+ };
126
278
  }
127
279
  return { valid: true, normalized: transformed };
128
280
  }
@@ -233,8 +385,455 @@ function isUserCancellation(error) {
233
385
  return msg.includes("user rejected") || msg.includes("user denied") || msg.includes("user cancelled") || msg.includes("rejected the request") || msg.includes("action_rejected");
234
386
  }
235
387
 
236
- // src/queries.ts
388
+ // src/otc.ts
237
389
  var import_viem = require("viem");
390
+
391
+ // ../../node_modules/@zkp2p/contracts-v2/abis/base/WhitelistPreIntentHook.json
392
+ var WhitelistPreIntentHook_default = [
393
+ {
394
+ inputs: [
395
+ {
396
+ internalType: "address",
397
+ name: "_orchestratorRegistry",
398
+ type: "address"
399
+ }
400
+ ],
401
+ stateMutability: "nonpayable",
402
+ type: "constructor"
403
+ },
404
+ {
405
+ inputs: [],
406
+ name: "EmptyArray",
407
+ type: "error"
408
+ },
409
+ {
410
+ inputs: [
411
+ {
412
+ internalType: "address",
413
+ name: "taker",
414
+ type: "address"
415
+ },
416
+ {
417
+ internalType: "address",
418
+ name: "escrow",
419
+ type: "address"
420
+ },
421
+ {
422
+ internalType: "uint256",
423
+ name: "depositId",
424
+ type: "uint256"
425
+ }
426
+ ],
427
+ name: "TakerNotInWhitelist",
428
+ type: "error"
429
+ },
430
+ {
431
+ inputs: [
432
+ {
433
+ internalType: "address",
434
+ name: "taker",
435
+ type: "address"
436
+ },
437
+ {
438
+ internalType: "address",
439
+ name: "escrow",
440
+ type: "address"
441
+ },
442
+ {
443
+ internalType: "uint256",
444
+ name: "depositId",
445
+ type: "uint256"
446
+ }
447
+ ],
448
+ name: "TakerNotWhitelisted",
449
+ type: "error"
450
+ },
451
+ {
452
+ inputs: [
453
+ {
454
+ internalType: "address",
455
+ name: "caller",
456
+ type: "address"
457
+ },
458
+ {
459
+ internalType: "address",
460
+ name: "owner",
461
+ type: "address"
462
+ },
463
+ {
464
+ internalType: "address",
465
+ name: "delegate",
466
+ type: "address"
467
+ }
468
+ ],
469
+ name: "UnauthorizedCallerOrDelegate",
470
+ type: "error"
471
+ },
472
+ {
473
+ inputs: [
474
+ {
475
+ internalType: "address",
476
+ name: "caller",
477
+ type: "address"
478
+ }
479
+ ],
480
+ name: "UnauthorizedOrchestratorCaller",
481
+ type: "error"
482
+ },
483
+ {
484
+ inputs: [],
485
+ name: "ZeroAddress",
486
+ type: "error"
487
+ },
488
+ {
489
+ anonymous: false,
490
+ inputs: [
491
+ {
492
+ indexed: true,
493
+ internalType: "address",
494
+ name: "escrow",
495
+ type: "address"
496
+ },
497
+ {
498
+ indexed: true,
499
+ internalType: "uint256",
500
+ name: "depositId",
501
+ type: "uint256"
502
+ },
503
+ {
504
+ indexed: true,
505
+ internalType: "address",
506
+ name: "taker",
507
+ type: "address"
508
+ }
509
+ ],
510
+ name: "TakerRemovedFromWhitelist",
511
+ type: "event"
512
+ },
513
+ {
514
+ anonymous: false,
515
+ inputs: [
516
+ {
517
+ indexed: true,
518
+ internalType: "address",
519
+ name: "escrow",
520
+ type: "address"
521
+ },
522
+ {
523
+ indexed: true,
524
+ internalType: "uint256",
525
+ name: "depositId",
526
+ type: "uint256"
527
+ },
528
+ {
529
+ indexed: true,
530
+ internalType: "address",
531
+ name: "taker",
532
+ type: "address"
533
+ }
534
+ ],
535
+ name: "TakerWhitelisted",
536
+ type: "event"
537
+ },
538
+ {
539
+ inputs: [
540
+ {
541
+ internalType: "address",
542
+ name: "_escrow",
543
+ type: "address"
544
+ },
545
+ {
546
+ internalType: "uint256",
547
+ name: "_depositId",
548
+ type: "uint256"
549
+ },
550
+ {
551
+ internalType: "address[]",
552
+ name: "_takers",
553
+ type: "address[]"
554
+ }
555
+ ],
556
+ name: "addToWhitelist",
557
+ outputs: [],
558
+ stateMutability: "nonpayable",
559
+ type: "function"
560
+ },
561
+ {
562
+ inputs: [
563
+ {
564
+ internalType: "address",
565
+ name: "_escrow",
566
+ type: "address"
567
+ },
568
+ {
569
+ internalType: "uint256",
570
+ name: "_depositId",
571
+ type: "uint256"
572
+ },
573
+ {
574
+ internalType: "address",
575
+ name: "_taker",
576
+ type: "address"
577
+ }
578
+ ],
579
+ name: "isWhitelisted",
580
+ outputs: [
581
+ {
582
+ internalType: "bool",
583
+ name: "",
584
+ type: "bool"
585
+ }
586
+ ],
587
+ stateMutability: "view",
588
+ type: "function"
589
+ },
590
+ {
591
+ inputs: [],
592
+ name: "orchestratorRegistry",
593
+ outputs: [
594
+ {
595
+ internalType: "contract IOrchestratorRegistry",
596
+ name: "",
597
+ type: "address"
598
+ }
599
+ ],
600
+ stateMutability: "view",
601
+ type: "function"
602
+ },
603
+ {
604
+ inputs: [
605
+ {
606
+ internalType: "address",
607
+ name: "_escrow",
608
+ type: "address"
609
+ },
610
+ {
611
+ internalType: "uint256",
612
+ name: "_depositId",
613
+ type: "uint256"
614
+ },
615
+ {
616
+ internalType: "address[]",
617
+ name: "_takers",
618
+ type: "address[]"
619
+ }
620
+ ],
621
+ name: "removeFromWhitelist",
622
+ outputs: [],
623
+ stateMutability: "nonpayable",
624
+ type: "function"
625
+ },
626
+ {
627
+ inputs: [
628
+ {
629
+ components: [
630
+ {
631
+ internalType: "address",
632
+ name: "taker",
633
+ type: "address"
634
+ },
635
+ {
636
+ internalType: "address",
637
+ name: "escrow",
638
+ type: "address"
639
+ },
640
+ {
641
+ internalType: "uint256",
642
+ name: "depositId",
643
+ type: "uint256"
644
+ },
645
+ {
646
+ internalType: "uint256",
647
+ name: "amount",
648
+ type: "uint256"
649
+ },
650
+ {
651
+ internalType: "address",
652
+ name: "to",
653
+ type: "address"
654
+ },
655
+ {
656
+ internalType: "bytes32",
657
+ name: "paymentMethod",
658
+ type: "bytes32"
659
+ },
660
+ {
661
+ internalType: "bytes32",
662
+ name: "fiatCurrency",
663
+ type: "bytes32"
664
+ },
665
+ {
666
+ internalType: "uint256",
667
+ name: "conversionRate",
668
+ type: "uint256"
669
+ },
670
+ {
671
+ internalType: "address",
672
+ name: "referrer",
673
+ type: "address"
674
+ },
675
+ {
676
+ internalType: "uint256",
677
+ name: "referrerFee",
678
+ type: "uint256"
679
+ },
680
+ {
681
+ internalType: "bytes",
682
+ name: "preIntentHookData",
683
+ type: "bytes"
684
+ }
685
+ ],
686
+ internalType: "struct IPreIntentHook.PreIntentContext",
687
+ name: "_ctx",
688
+ type: "tuple"
689
+ }
690
+ ],
691
+ name: "validateSignalIntent",
692
+ outputs: [],
693
+ stateMutability: "view",
694
+ type: "function"
695
+ },
696
+ {
697
+ inputs: [
698
+ {
699
+ internalType: "address",
700
+ name: "",
701
+ type: "address"
702
+ },
703
+ {
704
+ internalType: "uint256",
705
+ name: "",
706
+ type: "uint256"
707
+ },
708
+ {
709
+ internalType: "address",
710
+ name: "",
711
+ type: "address"
712
+ }
713
+ ],
714
+ name: "whitelist",
715
+ outputs: [
716
+ {
717
+ internalType: "bool",
718
+ name: "",
719
+ type: "bool"
720
+ }
721
+ ],
722
+ stateMutability: "view",
723
+ type: "function"
724
+ }
725
+ ];
726
+
727
+ // src/otc.ts
728
+ var WHITELIST_HOOK_ADDRESS = "0xd793369b11357cdd076A9c631F6c44ff8e6353eA";
729
+ var OTC_BASE_URL = "https://usdctofiat.xyz";
730
+ async function enableOtc(walletClient, depositId, takerAddress, escrowAddress) {
731
+ if (!(0, import_viem.isAddress)(takerAddress)) {
732
+ throw new OfframpError("Invalid taker address", "VALIDATION");
733
+ }
734
+ const escrow = escrowAddress || ESCROW_ADDRESS;
735
+ const taker = takerAddress;
736
+ const depositIdBig = BigInt(depositId);
737
+ const client = createSdkClient(walletClient);
738
+ const txOverrides = { referrer: [REFERRER] };
739
+ try {
740
+ const currentHook = await client.getDepositWhitelistHook(depositIdBig, {
741
+ escrowAddress: escrow
742
+ });
743
+ if (currentHook !== import_viem.zeroAddress) {
744
+ const isAlready = await readIsWhitelisted(
745
+ walletClient,
746
+ escrow,
747
+ depositIdBig,
748
+ taker
749
+ );
750
+ if (isAlready) {
751
+ return {
752
+ depositId,
753
+ takerAddress: taker,
754
+ otcLink: getOtcLink(depositId, escrow)
755
+ };
756
+ }
757
+ }
758
+ await writeContract(walletClient, "addToWhitelist", [escrow, depositIdBig, [taker]]);
759
+ if (currentHook === import_viem.zeroAddress) {
760
+ await client.setDepositWhitelistHook({
761
+ depositId: depositIdBig,
762
+ whitelistHook: WHITELIST_HOOK_ADDRESS,
763
+ escrowAddress: escrow,
764
+ txOverrides
765
+ });
766
+ }
767
+ return {
768
+ depositId,
769
+ takerAddress: taker,
770
+ otcLink: getOtcLink(depositId, escrow)
771
+ };
772
+ } catch (err) {
773
+ if (err instanceof OfframpError) throw err;
774
+ if (isUserCancellation(err)) {
775
+ throw new OfframpError("User cancelled", "USER_CANCELLED", void 0, err, { depositId });
776
+ }
777
+ const detail = err instanceof Error ? err.message : String(err);
778
+ throw new OfframpError(`Failed to enable OTC: ${detail}`, "DEPOSIT_FAILED", void 0, err, {
779
+ depositId
780
+ });
781
+ }
782
+ }
783
+ async function disableOtc(walletClient, depositId, escrowAddress) {
784
+ const escrow = escrowAddress || ESCROW_ADDRESS;
785
+ const client = createSdkClient(walletClient);
786
+ const txOverrides = { referrer: [REFERRER] };
787
+ try {
788
+ await client.setDepositWhitelistHook({
789
+ depositId: BigInt(depositId),
790
+ whitelistHook: import_viem.zeroAddress,
791
+ escrowAddress: escrow,
792
+ txOverrides
793
+ });
794
+ } catch (err) {
795
+ if (isUserCancellation(err)) {
796
+ throw new OfframpError("User cancelled", "USER_CANCELLED", void 0, err, { depositId });
797
+ }
798
+ const detail = err instanceof Error ? err.message : String(err);
799
+ throw new OfframpError(`Failed to disable OTC: ${detail}`, "DEPOSIT_FAILED", void 0, err, {
800
+ depositId
801
+ });
802
+ }
803
+ }
804
+ function getOtcLink(depositId, escrowAddress) {
805
+ const escrow = escrowAddress || ESCROW_ADDRESS;
806
+ return `${OTC_BASE_URL}/deposit/${escrow}/${depositId}`;
807
+ }
808
+ async function writeContract(walletClient, functionName, args) {
809
+ const wc = walletClient;
810
+ if (typeof wc.writeContract !== "function") {
811
+ throw new OfframpError("Wallet client does not support writeContract", "VALIDATION");
812
+ }
813
+ await wc.writeContract({
814
+ address: WHITELIST_HOOK_ADDRESS,
815
+ abi: WhitelistPreIntentHook_default,
816
+ functionName,
817
+ args
818
+ });
819
+ }
820
+ async function readIsWhitelisted(walletClient, escrow, depositId, taker) {
821
+ const { createPublicClient: createPublicClient2, http: http2 } = await import("viem");
822
+ const { base: base2 } = await import("viem/chains");
823
+ const publicClient = createPublicClient2({
824
+ chain: base2,
825
+ transport: http2("https://mainnet.base.org")
826
+ });
827
+ return publicClient.readContract({
828
+ address: WHITELIST_HOOK_ADDRESS,
829
+ abi: WhitelistPreIntentHook_default,
830
+ functionName: "isWhitelisted",
831
+ args: [escrow, depositId, taker]
832
+ });
833
+ }
834
+
835
+ // src/queries.ts
836
+ var import_viem2 = require("viem");
238
837
  var import_sdk3 = require("@zkp2p/sdk");
239
838
  var indexerService = null;
240
839
  function getIndexerService() {
@@ -253,7 +852,7 @@ function toBigInt(value) {
253
852
  }
254
853
  }
255
854
  function toUsdc(value) {
256
- return Number((0, import_viem.formatUnits)(toBigInt(value), 6));
855
+ return Number((0, import_viem2.formatUnits)(toBigInt(value), 6));
257
856
  }
258
857
  function resolveStatus(deposit) {
259
858
  if (deposit.status === "CLOSED") return "closed";
@@ -302,8 +901,10 @@ function mapDeposit(d) {
302
901
  }
303
902
  function extractTxHash(result) {
304
903
  if (typeof result === "string") return result;
305
- if (result && typeof result === "object" && "hash" in result) return result.hash;
306
- if (result && typeof result === "object" && "transactionHash" in result) return result.transactionHash;
904
+ if (result && typeof result === "object" && "hash" in result)
905
+ return result.hash;
906
+ if (result && typeof result === "object" && "transactionHash" in result)
907
+ return result.transactionHash;
307
908
  throw new Error("Unexpected transaction result format");
308
909
  }
309
910
  async function deposits(walletAddress) {
@@ -331,7 +932,7 @@ async function close(walletClient, depositId, escrowAddress) {
331
932
 
332
933
  // src/deposit.ts
333
934
  function usdcToUnits(amount) {
334
- return (0, import_viem2.parseUnits)(amount, 6);
935
+ return (0, import_viem3.parseUnits)(amount, 6);
335
936
  }
336
937
  var DEPOSIT_RECEIVED_ABI = [
337
938
  {
@@ -342,10 +943,15 @@ var DEPOSIT_RECEIVED_ABI = [
342
943
  { indexed: true, name: "depositor", type: "address" },
343
944
  { indexed: true, name: "token", type: "address" },
344
945
  { indexed: false, name: "amount", type: "uint256" },
345
- { indexed: false, name: "intentAmountRange", type: "tuple", components: [
346
- { name: "min", type: "uint256" },
347
- { name: "max", type: "uint256" }
348
- ] },
946
+ {
947
+ indexed: false,
948
+ name: "intentAmountRange",
949
+ type: "tuple",
950
+ components: [
951
+ { name: "min", type: "uint256" },
952
+ { name: "max", type: "uint256" }
953
+ ]
954
+ },
349
955
  { indexed: false, name: "delegate", type: "address" },
350
956
  { indexed: false, name: "intentGuardian", type: "address" }
351
957
  ]
@@ -355,7 +961,7 @@ function extractDepositIdFromLogs(logs) {
355
961
  for (const log of logs) {
356
962
  if (!log?.topics?.length || !log.data) continue;
357
963
  try {
358
- const decoded = (0, import_viem2.decodeEventLog)({
964
+ const decoded = (0, import_viem3.decodeEventLog)({
359
965
  abi: DEPOSIT_RECEIVED_ABI,
360
966
  data: log.data,
361
967
  topics: log.topics
@@ -413,8 +1019,10 @@ function attachOracleConfig(entries, conversionRates) {
413
1019
  }
414
1020
  function extractTxHash2(result) {
415
1021
  if (typeof result === "string") return result;
416
- if (result && typeof result === "object" && "hash" in result) return result.hash;
417
- if (result && typeof result === "object" && "transactionHash" in result) return result.transactionHash;
1022
+ if (result && typeof result === "object" && "hash" in result)
1023
+ return result.hash;
1024
+ if (result && typeof result === "object" && "transactionHash" in result)
1025
+ return result.transactionHash;
418
1026
  throw new Error("Unexpected transaction result format");
419
1027
  }
420
1028
  function createSdkClient(walletClient) {
@@ -434,7 +1042,7 @@ async function findUndelegatedDeposit(walletAddress) {
434
1042
  { limit: 50 }
435
1043
  );
436
1044
  const escrowLower = ESCROW_ADDRESS.toLowerCase();
437
- return (raw || []).find((d) => {
1045
+ const undelegated = (raw || []).filter((d) => {
438
1046
  if (d.status === "CLOSED") return false;
439
1047
  if (d.escrowAddress.toLowerCase() !== escrowLower) return false;
440
1048
  const remaining = (() => {
@@ -445,9 +1053,10 @@ async function findUndelegatedDeposit(walletAddress) {
445
1053
  }
446
1054
  })();
447
1055
  if (remaining === 0n) return false;
448
- const hasOurVault = d.rateManagerId === DELEGATE_RATE_MANAGER_ID;
449
- return !hasOurVault;
450
- }) ?? null;
1056
+ return d.rateManagerId !== DELEGATE_RATE_MANAGER_ID;
1057
+ });
1058
+ undelegated.sort((a, b) => Number(BigInt(b.depositId) - BigInt(a.depositId)));
1059
+ return undelegated[0] ?? null;
451
1060
  } catch {
452
1061
  return null;
453
1062
  }
@@ -493,7 +1102,8 @@ async function offramp(walletClient, params, onProgress) {
493
1102
  onProgress?.({ step: "done", txHash, depositId: existing.depositId });
494
1103
  return { depositId: existing.depositId, txHash, resumed: true };
495
1104
  } catch (err) {
496
- if (isUserCancellation(err)) throw new OfframpError("User cancelled", "USER_CANCELLED", "resuming", err);
1105
+ if (isUserCancellation(err))
1106
+ throw new OfframpError("User cancelled", "USER_CANCELLED", "resuming", err);
497
1107
  throw new OfframpError(
498
1108
  "Found undelegated deposit but delegation failed. Try again.",
499
1109
  "DELEGATION_FAILED",
@@ -508,16 +1118,27 @@ async function offramp(walletClient, params, onProgress) {
508
1118
  const minUnits = usdcToUnits(String(MIN_ORDER_USDC));
509
1119
  const maxUnits = usdcToUnits(String(Math.min(amt, 2500)));
510
1120
  try {
511
- const publicClient = (0, import_viem2.createPublicClient)({ chain: import_chains.base, transport: (0, import_viem2.http)(BASE_RPC_URL) });
1121
+ const publicClient = (0, import_viem3.createPublicClient)({ chain: import_chains.base, transport: (0, import_viem3.http)(BASE_RPC_URL) });
512
1122
  const balance = await publicClient.readContract({
513
1123
  address: USDC_ADDRESS,
514
- abi: [{ name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "", type: "uint256" }] }],
1124
+ abi: [
1125
+ {
1126
+ name: "balanceOf",
1127
+ type: "function",
1128
+ stateMutability: "view",
1129
+ inputs: [{ name: "account", type: "address" }],
1130
+ outputs: [{ name: "", type: "uint256" }]
1131
+ }
1132
+ ],
515
1133
  functionName: "balanceOf",
516
1134
  args: [walletAddress]
517
1135
  });
518
1136
  if (balance < amountUnits) {
519
- const available = Number((0, import_viem2.formatUnits)(balance, 6));
520
- throw new OfframpError(`Insufficient USDC balance. Have ${available.toFixed(2)}, need ${truncatedAmount}.`, "VALIDATION");
1137
+ const available = Number((0, import_viem3.formatUnits)(balance, 6));
1138
+ throw new OfframpError(
1139
+ `Insufficient USDC balance. Have ${available.toFixed(2)}, need ${truncatedAmount}.`,
1140
+ "VALIDATION"
1141
+ );
521
1142
  }
522
1143
  } catch (err) {
523
1144
  if (err instanceof OfframpError) throw err;
@@ -534,7 +1155,8 @@ async function offramp(walletClient, params, onProgress) {
534
1155
  txOverrides
535
1156
  });
536
1157
  } catch (err) {
537
- if (isUserCancellation(err)) throw new OfframpError("User cancelled", "USER_CANCELLED", "approving", err);
1158
+ if (isUserCancellation(err))
1159
+ throw new OfframpError("User cancelled", "USER_CANCELLED", "approving", err);
538
1160
  const detail = err instanceof Error ? err.message : String(err);
539
1161
  throw new OfframpError(`USDC approval failed: ${detail}`, "APPROVAL_FAILED", "approving", err);
540
1162
  }
@@ -564,11 +1186,13 @@ async function offramp(walletClient, params, onProgress) {
564
1186
  depositData: [buildDepositData(platformId, normalizedIdentifier)],
565
1187
  conversionRates,
566
1188
  paymentMethodsOverride: [methodHash],
567
- paymentMethodDataOverride: [{
568
- intentGatingService: GATING_SERVICE_ADDRESS,
569
- payeeDetails: hashedOnchainId,
570
- data: "0x"
571
- }],
1189
+ paymentMethodDataOverride: [
1190
+ {
1191
+ intentGatingService: GATING_SERVICE_ADDRESS,
1192
+ payeeDetails: hashedOnchainId,
1193
+ data: "0x"
1194
+ }
1195
+ ],
572
1196
  currenciesOverride,
573
1197
  escrowAddress: ESCROW_ADDRESS,
574
1198
  txOverrides
@@ -576,9 +1200,15 @@ async function offramp(walletClient, params, onProgress) {
576
1200
  if (!result?.hash) throw new Error("No transaction hash returned");
577
1201
  hash = result.hash;
578
1202
  } catch (err) {
579
- if (isUserCancellation(err)) throw new OfframpError("User cancelled", "USER_CANCELLED", "depositing", err);
1203
+ if (isUserCancellation(err))
1204
+ throw new OfframpError("User cancelled", "USER_CANCELLED", "depositing", err);
580
1205
  const detail = err instanceof Error ? err.message : String(err);
581
- throw new OfframpError(`Deposit transaction failed: ${detail}`, "DEPOSIT_FAILED", "depositing", err);
1206
+ throw new OfframpError(
1207
+ `Deposit transaction failed: ${detail}`,
1208
+ "DEPOSIT_FAILED",
1209
+ "depositing",
1210
+ err
1211
+ );
582
1212
  }
583
1213
  onProgress?.({ step: "confirming", txHash: hash });
584
1214
  let depositId = "";
@@ -629,7 +1259,13 @@ async function offramp(walletClient, params, onProgress) {
629
1259
  });
630
1260
  } catch (delegationError) {
631
1261
  if (isUserCancellation(delegationError)) {
632
- throw new OfframpError("User cancelled delegation", "USER_CANCELLED", "delegating", delegationError, { txHash: hash, depositId });
1262
+ throw new OfframpError(
1263
+ "User cancelled delegation",
1264
+ "USER_CANCELLED",
1265
+ "delegating",
1266
+ delegationError,
1267
+ { txHash: hash, depositId }
1268
+ );
633
1269
  }
634
1270
  throw new OfframpError(
635
1271
  "Deposit created but delegation failed. Call offramp() again to resume delegation.",
@@ -639,15 +1275,45 @@ async function offramp(walletClient, params, onProgress) {
639
1275
  { txHash: hash, depositId }
640
1276
  );
641
1277
  }
1278
+ let otcLink;
1279
+ if (params.otcTaker) {
1280
+ onProgress?.({ step: "restricting", txHash: hash, depositId });
1281
+ try {
1282
+ const otcResult = await enableOtc(walletClient, depositId, params.otcTaker);
1283
+ otcLink = otcResult.otcLink;
1284
+ } catch (otcError) {
1285
+ if (isUserCancellation(otcError)) {
1286
+ throw new OfframpError(
1287
+ "User cancelled OTC restriction",
1288
+ "USER_CANCELLED",
1289
+ "restricting",
1290
+ otcError,
1291
+ {
1292
+ txHash: hash,
1293
+ depositId
1294
+ }
1295
+ );
1296
+ }
1297
+ throw new OfframpError(
1298
+ "Deposit created and delegated but OTC restriction failed. Use enableOtc() to retry.",
1299
+ "DEPOSIT_FAILED",
1300
+ "restricting",
1301
+ otcError,
1302
+ { txHash: hash, depositId }
1303
+ );
1304
+ }
1305
+ }
642
1306
  onProgress?.({ step: "done", txHash: hash, depositId });
643
- return { depositId, txHash: hash, resumed: false };
1307
+ return { depositId, txHash: hash, resumed: false, otcLink };
644
1308
  }
645
1309
 
646
1310
  // src/currencies.ts
647
1311
  var import_sdk5 = require("@zkp2p/sdk");
648
1312
  function buildCurrencies() {
649
1313
  const entries = {};
650
- for (const [code, info] of Object.entries(import_sdk5.currencyInfo)) {
1314
+ for (const [code, info] of Object.entries(
1315
+ import_sdk5.currencyInfo
1316
+ )) {
651
1317
  entries[code] = {
652
1318
  code: info.currencyCode ?? code,
653
1319
  name: info.currencyName ?? code,
@@ -665,6 +1331,9 @@ var CURRENCIES = buildCurrencies();
665
1331
  PLATFORMS,
666
1332
  close,
667
1333
  deposits,
1334
+ disableOtc,
1335
+ enableOtc,
1336
+ getOtcLink,
668
1337
  offramp
669
1338
  });
670
1339
  //# sourceMappingURL=index.cjs.map