@zkp2p/sdk 0.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,2205 @@
1
+ import { ValidationError, APIError, NetworkError } from './chunk-GHQK65J2.mjs';
2
+ export { APIError, ContractError, ErrorCode, NetworkError, ValidationError, ZKP2PError } from './chunk-GHQK65J2.mjs';
3
+ export { PAYMENT_PLATFORMS, PLATFORM_METADATA, SUPPORTED_CHAIN_IDS, TOKEN_METADATA } from './chunk-JLEW4EOG.mjs';
4
+ import { getContracts, getPaymentMethodsCatalog, getGatingServiceAddress } from './chunk-O7DHVBCL.mjs';
5
+ export { enrichPvDepositView, enrichPvIntentView, getContracts, getGatingServiceAddress, getPaymentMethodsCatalog, parseDepositView, parseIntentView } from './chunk-O7DHVBCL.mjs';
6
+ import { resolvePaymentMethodHashFromCatalog, resolveFiatCurrencyBytes32 } from './chunk-M6S5FL2X.mjs';
7
+ export { asciiToBytes32, ensureBytes32, resolveFiatCurrencyBytes32, resolvePaymentMethodHash, resolvePaymentMethodHashFromCatalog, resolvePaymentMethodNameFromHash } from './chunk-M6S5FL2X.mjs';
8
+ import { currencyKeccak256 } from './chunk-PBBMWRNE.mjs';
9
+ export { Currency, currencyInfo, getCurrencyCodeFromHash, getCurrencyInfoFromCountryCode, getCurrencyInfoFromHash, isSupportedCurrencyHash, mapConversionRatesToOnchainMinRate } from './chunk-PBBMWRNE.mjs';
10
+ import { concatHex, encodeFunctionData, createPublicClient, http } from 'viem';
11
+ import { hardhat, baseSepolia, base } from 'viem/chains';
12
+ import { AbiCoder } from 'ethers';
13
+ import { Attribution } from 'ox/erc8021';
14
+
15
+ // src/indexer/client.ts
16
+ var IndexerClient = class {
17
+ constructor(endpoint) {
18
+ this.endpoint = endpoint;
19
+ }
20
+ async _post(request, init) {
21
+ const res = await fetch(this.endpoint, {
22
+ method: "POST",
23
+ headers: { "Content-Type": "application/json" },
24
+ body: JSON.stringify(request),
25
+ cache: "no-store",
26
+ ...init
27
+ });
28
+ if (!res.ok) throw new Error(`Indexer request failed: ${res.status} ${res.statusText}`);
29
+ const json = await res.json();
30
+ if (json.errors?.length) {
31
+ const msg = json.errors.map((e) => e.message).join(", ");
32
+ throw new Error(`GraphQL errors: ${msg}`);
33
+ }
34
+ if (!json.data) throw new Error("No data returned from indexer");
35
+ return json.data;
36
+ }
37
+ async query(request, init) {
38
+ const retries = init?.retries ?? 1;
39
+ let lastErr;
40
+ for (let i = 0; i <= retries; i++) {
41
+ try {
42
+ return await this._post(request, init);
43
+ } catch (e) {
44
+ lastErr = e;
45
+ if (i === retries) break;
46
+ await new Promise((r) => setTimeout(r, 200 * (i + 1)));
47
+ }
48
+ }
49
+ throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
50
+ }
51
+ };
52
+ function defaultIndexerEndpoint(env = "PRODUCTION") {
53
+ switch (env) {
54
+ case "PRODUCTION":
55
+ return "https://indexer.hyperindex.xyz/8fd74dc/v1/graphql";
56
+ case "PREPRODUCTION":
57
+ return "https://indexer.hyperindex.xyz/186c193/v1/graphql";
58
+ case "STAGING":
59
+ return "https://indexer.dev.hyperindex.xyz/3b6e163/v1/graphql";
60
+ case "DEV":
61
+ case "LOCAL":
62
+ case "STAGING_TESTNET":
63
+ return "https://indexer.dev.hyperindex.xyz/3b6e163/v1/graphql";
64
+ default:
65
+ return "https://indexer.hyperindex.xyz/8fd74dc/v1/graphql";
66
+ }
67
+ }
68
+
69
+ // src/indexer/queries.ts
70
+ var DEPOSIT_FIELDS = `
71
+ id
72
+ chainId
73
+ escrowAddress
74
+ depositId
75
+ depositor
76
+ token
77
+ remainingDeposits
78
+ intentAmountMin
79
+ intentAmountMax
80
+ acceptingIntents
81
+ status
82
+ outstandingIntentAmount
83
+ totalAmountTaken
84
+ totalWithdrawn
85
+ successRateBps
86
+ totalIntents
87
+ signaledIntents
88
+ fulfilledIntents
89
+ prunedIntents
90
+ blockNumber
91
+ timestamp
92
+ txHash
93
+ updatedAt
94
+ `;
95
+ var DEPOSITS_QUERY = (
96
+ /* GraphQL */
97
+ `
98
+ query GetDeposits(
99
+ $where: Deposit_bool_exp
100
+ $order_by: [Deposit_order_by!]
101
+ $limit: Int
102
+ $offset: Int
103
+ ) {
104
+ Deposit(where: $where, order_by: $order_by, limit: $limit, offset: $offset) {
105
+ ${DEPOSIT_FIELDS}
106
+ }
107
+ }
108
+ `
109
+ );
110
+ var DEPOSITS_BY_IDS_QUERY = (
111
+ /* GraphQL */
112
+ `
113
+ query GetDepositsByIds($ids: [String!]) {
114
+ Deposit(where: { id: { _in: $ids } }) {
115
+ ${DEPOSIT_FIELDS}
116
+ }
117
+ }
118
+ `
119
+ );
120
+ var DEPOSIT_RELATIONS_QUERY = (
121
+ /* GraphQL */
122
+ `
123
+ query GetDepositRelations($depositIds: [String!]) {
124
+ DepositPaymentMethod(where: { depositId: { _in: $depositIds } }) {
125
+ id
126
+ chainId
127
+ depositIdOnContract
128
+ depositId
129
+ paymentMethodHash
130
+ verifierAddress
131
+ intentGatingService
132
+ payeeDetailsHash
133
+ active
134
+ }
135
+ MethodCurrency(where: { depositId: { _in: $depositIds } }) {
136
+ id
137
+ chainId
138
+ depositIdOnContract
139
+ depositId
140
+ paymentMethodHash
141
+ currencyCode
142
+ minConversionRate
143
+ }
144
+ }
145
+ `
146
+ );
147
+ var PAYMENT_METHODS_BY_PAYEE_HASH_QUERY = (
148
+ /* GraphQL */
149
+ `
150
+ query GetPaymentMethodsByPayeeHash(
151
+ $where: DepositPaymentMethod_bool_exp!
152
+ $limit: Int
153
+ ) {
154
+ DepositPaymentMethod(where: $where, limit: $limit) {
155
+ id
156
+ chainId
157
+ depositIdOnContract
158
+ depositId
159
+ paymentMethodHash
160
+ verifierAddress
161
+ intentGatingService
162
+ payeeDetailsHash
163
+ active
164
+ }
165
+ }
166
+ `
167
+ );
168
+ var DEPOSIT_WITH_RELATIONS_QUERY = (
169
+ /* GraphQL */
170
+ `
171
+ query GetDepositWithRelations($id: String!) {
172
+ Deposit_by_pk(id: $id) {
173
+ ${DEPOSIT_FIELDS}
174
+ }
175
+ DepositPaymentMethod(where: { depositId: { _eq: $id } }) {
176
+ id
177
+ chainId
178
+ depositIdOnContract
179
+ depositId
180
+ paymentMethodHash
181
+ verifierAddress
182
+ intentGatingService
183
+ payeeDetailsHash
184
+ active
185
+ }
186
+ MethodCurrency(where: { depositId: { _eq: $id } }) {
187
+ id
188
+ chainId
189
+ depositIdOnContract
190
+ depositId
191
+ paymentMethodHash
192
+ currencyCode
193
+ minConversionRate
194
+ }
195
+ }
196
+ `
197
+ );
198
+ var INTENTS_QUERY = (
199
+ /* GraphQL */
200
+ `
201
+ query GetIntents(
202
+ $where: Intent_bool_exp
203
+ $order_by: [Intent_order_by!]
204
+ $limit: Int
205
+ $offset: Int
206
+ ) {
207
+ Intent(where: $where, order_by: $order_by, limit: $limit, offset: $offset) {
208
+ id
209
+ intentHash
210
+ depositId
211
+ orchestratorAddress
212
+ verifier
213
+ owner
214
+ toAddress
215
+ amount
216
+ fiatCurrency
217
+ conversionRate
218
+ status
219
+ isExpired
220
+ signalTimestamp
221
+ expiryTime
222
+ fulfillTimestamp
223
+ pruneTimestamp
224
+ updatedAt
225
+ signalTxHash
226
+ fulfillTxHash
227
+ pruneTxHash
228
+ paymentMethodHash
229
+ paymentAmount
230
+ paymentCurrency
231
+ paymentTimestamp
232
+ paymentId
233
+ releasedAmount
234
+ takerAmountNetFees
235
+ }
236
+ }
237
+ `
238
+ );
239
+ var EXPIRED_INTENTS_QUERY = (
240
+ /* GraphQL */
241
+ `
242
+ query GetExpiredIntents(
243
+ $now: numeric!
244
+ $limit: Int
245
+ $depositIds: [String!]
246
+ ) {
247
+ Intent(
248
+ where: {
249
+ status: { _eq: "SIGNALED" }
250
+ expiryTime: { _lt: $now }
251
+ depositId: { _in: $depositIds }
252
+ }
253
+ order_by: { expiryTime: asc }
254
+ limit: $limit
255
+ ) {
256
+ id
257
+ intentHash
258
+ depositId
259
+ owner
260
+ toAddress
261
+ amount
262
+ expiryTime
263
+ isExpired
264
+ updatedAt
265
+ paymentMethodHash
266
+ }
267
+ }
268
+ `
269
+ );
270
+ var INTENT_FULFILLMENTS_QUERY = (
271
+ /* GraphQL */
272
+ `
273
+ query GetFulfilledIntents($intentHashes: [String!]) {
274
+ Orchestrator_V21_IntentFulfilled(
275
+ where: { intentHash: { _in: $intentHashes } }
276
+ ) {
277
+ intentHash
278
+ isManualRelease
279
+ fundsTransferredTo
280
+ }
281
+ }
282
+ `
283
+ );
284
+ var FULFILLMENT_AND_PAYMENT_QUERY = (
285
+ /* GraphQL */
286
+ `
287
+ query PaymentVerificationForFulfilledIntent($intentHash: String!) {
288
+ Orchestrator_V21_IntentFulfilled(
289
+ where: { intentHash: { _eq: $intentHash } }
290
+ ) {
291
+ id
292
+ intentHash
293
+ amount
294
+ isManualRelease
295
+ fundsTransferredTo
296
+ }
297
+ UnifiedVerifier_V21_PaymentVerified(
298
+ where: { intentHash: { _eq: $intentHash } }
299
+ ) {
300
+ id
301
+ intentHash
302
+ method
303
+ currency
304
+ amount
305
+ timestamp
306
+ paymentId
307
+ payeeId
308
+ }
309
+ }
310
+ `
311
+ );
312
+
313
+ // src/indexer/converters.ts
314
+ var ZERO = "0x0000000000000000000000000000000000000000";
315
+ function toBigInt(value) {
316
+ if (value === null || value === void 0) return 0n;
317
+ try {
318
+ return typeof value === "bigint" ? value : BigInt(value);
319
+ } catch {
320
+ return 0n;
321
+ }
322
+ }
323
+ function normalizeAddress(value) {
324
+ if (!value) return ZERO;
325
+ return value.startsWith("0x") ? value : ZERO;
326
+ }
327
+ function extractDepositId(compositeId) {
328
+ const parts = compositeId.split("_");
329
+ return parts[1] || "0";
330
+ }
331
+ function createCompositeDepositId(escrowAddress, depositId) {
332
+ return `${escrowAddress.toLowerCase()}_${depositId.toString()}`;
333
+ }
334
+ function convertIndexerDepositToEscrowView(deposit, _chainId, _escrowAddress) {
335
+ const paymentMethods = (deposit.paymentMethods ?? []).filter((pm) => pm.active !== false);
336
+ const currencies = deposit.currencies ?? [];
337
+ const currenciesByPaymentMethod = /* @__PURE__ */ new Map();
338
+ for (const c of currencies) {
339
+ const bucket = currenciesByPaymentMethod.get(c.paymentMethodHash) ?? [];
340
+ bucket.push(c);
341
+ currenciesByPaymentMethod.set(c.paymentMethodHash, bucket);
342
+ }
343
+ const verifiers = paymentMethods.map((pm) => ({
344
+ verifier: normalizeAddress(pm.verifierAddress),
345
+ verificationData: {
346
+ intentGatingService: normalizeAddress(pm.intentGatingService),
347
+ payeeDetails: pm.payeeDetailsHash ?? "",
348
+ data: ""
349
+ },
350
+ currencies: (currenciesByPaymentMethod.get(pm.paymentMethodHash) ?? []).map((cur) => ({
351
+ code: cur.currencyCode,
352
+ conversionRate: toBigInt(cur.minConversionRate)
353
+ })),
354
+ methodHash: pm.paymentMethodHash
355
+ }));
356
+ const uniqueIntentHashes = new Set((deposit.intents ?? []).map((i) => i.intentHash));
357
+ const remaining = toBigInt(deposit.remainingDeposits);
358
+ const outstanding = toBigInt(deposit.outstandingIntentAmount);
359
+ const depositAmount = remaining + outstanding + toBigInt(deposit.totalAmountTaken ?? 0) + toBigInt(deposit.totalWithdrawn ?? 0);
360
+ return {
361
+ depositId: toBigInt(deposit.depositId),
362
+ deposit: {
363
+ depositor: normalizeAddress(deposit.depositor),
364
+ token: normalizeAddress(deposit.token),
365
+ depositAmount,
366
+ intentAmountRange: { min: toBigInt(deposit.intentAmountMin), max: toBigInt(deposit.intentAmountMax) },
367
+ acceptingIntents: Boolean(deposit.acceptingIntents),
368
+ remainingDepositAmount: remaining,
369
+ outstandingIntentAmount: outstanding,
370
+ intentHashes: Array.from(uniqueIntentHashes)
371
+ },
372
+ verifiers
373
+ };
374
+ }
375
+ function convertDepositsForLiquidity(deposits, chainId, escrowAddress) {
376
+ return deposits.filter((d) => d.depositor && d.depositor.toLowerCase() !== ZERO && d.acceptingIntents && toBigInt(d.remainingDeposits) > 0n && d.status === "ACTIVE").map((d) => convertIndexerDepositToEscrowView(d));
377
+ }
378
+ function convertIndexerIntentsToEscrowViews(intents, depositViewsById) {
379
+ const result = [];
380
+ for (const intent of intents) {
381
+ const depositView = depositViewsById.get(intent.depositId.toLowerCase());
382
+ if (!depositView) continue;
383
+ const rawDepositId = extractDepositId(intent.depositId);
384
+ result.push({
385
+ intentHash: intent.intentHash,
386
+ intent: {
387
+ owner: normalizeAddress(intent.owner),
388
+ to: normalizeAddress(intent.toAddress),
389
+ depositId: toBigInt(rawDepositId),
390
+ amount: toBigInt(intent.amount),
391
+ timestamp: toBigInt(intent.signalTimestamp),
392
+ paymentVerifier: normalizeAddress(intent.verifier),
393
+ fiatCurrency: intent.fiatCurrency,
394
+ conversionRate: toBigInt(intent.conversionRate)
395
+ },
396
+ deposit: depositView
397
+ });
398
+ }
399
+ return result;
400
+ }
401
+
402
+ // src/indexer/service.ts
403
+ function groupByDepositId(items) {
404
+ const map = /* @__PURE__ */ new Map();
405
+ for (const item of items) {
406
+ if (!item.depositId) continue;
407
+ const key = item.depositId.toLowerCase();
408
+ const bucket = map.get(key);
409
+ if (bucket) bucket.push(item);
410
+ else map.set(key, [item]);
411
+ }
412
+ return map;
413
+ }
414
+ var DEFAULT_LIMIT = 100;
415
+ var DEFAULT_ORDER_FIELD = "remainingDeposits";
416
+ var IndexerDepositService = class {
417
+ constructor(client) {
418
+ this.client = client;
419
+ }
420
+ buildDepositWhere(filter) {
421
+ if (!filter) return void 0;
422
+ const where = {};
423
+ if (filter.status) where.status = { _eq: filter.status };
424
+ if (filter.depositor) where.depositor = { _ilike: filter.depositor };
425
+ if (filter.chainId) where.chainId = { _eq: filter.chainId };
426
+ if (filter.escrowAddresses && filter.escrowAddresses.length) {
427
+ where.escrowAddress = { _in: filter.escrowAddresses };
428
+ } else if (filter.escrowAddress) {
429
+ where.escrowAddress = { _ilike: filter.escrowAddress };
430
+ }
431
+ if (filter.acceptingIntents !== void 0) where.acceptingIntents = { _eq: filter.acceptingIntents };
432
+ if (filter.minLiquidity) where.remainingDeposits = { _gte: filter.minLiquidity };
433
+ return Object.keys(where).length ? where : void 0;
434
+ }
435
+ buildOrderBy(pagination) {
436
+ const field = pagination?.orderBy ?? DEFAULT_ORDER_FIELD;
437
+ const direction = pagination?.orderDirection === "asc" ? "asc" : "desc";
438
+ return [{ [field]: direction }];
439
+ }
440
+ async fetchRelations(depositIds) {
441
+ if (!depositIds.length) {
442
+ return {
443
+ paymentMethodsByDeposit: /* @__PURE__ */ new Map(),
444
+ currenciesByDeposit: /* @__PURE__ */ new Map()
445
+ };
446
+ }
447
+ const result = await this.client.query({ query: DEPOSIT_RELATIONS_QUERY, variables: { depositIds } });
448
+ const paymentMethodsByDeposit = groupByDepositId(result.DepositPaymentMethod ?? []);
449
+ const currenciesByDeposit = groupByDepositId(result.MethodCurrency ?? []);
450
+ return { paymentMethodsByDeposit, currenciesByDeposit };
451
+ }
452
+ async fetchIntents(params) {
453
+ const where = {};
454
+ if (params.depositIds?.length) where.depositId = { _in: params.depositIds };
455
+ if (params.owner) where.owner = { _ilike: params.owner };
456
+ if (params.statuses?.length) where.status = { _in: params.statuses };
457
+ if (!Object.keys(where).length) return [];
458
+ const result = await this.client.query({
459
+ query: INTENTS_QUERY,
460
+ variables: { where, order_by: [{ signalTimestamp: "desc" }], limit: params.limit, offset: params.offset }
461
+ });
462
+ return result.Intent ?? [];
463
+ }
464
+ async attachRelations(deposits, options = {}) {
465
+ if (!deposits.length) return [];
466
+ const depositIds = deposits.map((d) => d.id);
467
+ const [{ paymentMethodsByDeposit, currenciesByDeposit }, intents] = await Promise.all([
468
+ this.fetchRelations(depositIds),
469
+ options.includeIntents ? this.fetchIntents({ depositIds, statuses: options.intentStatuses }) : Promise.resolve([])
470
+ ]);
471
+ const intentsByDeposit = options.includeIntents ? groupByDepositId(intents) : /* @__PURE__ */ new Map();
472
+ return deposits.map((d) => {
473
+ const key = d.id.toLowerCase();
474
+ return {
475
+ ...d,
476
+ paymentMethods: paymentMethodsByDeposit.get(key) ?? [],
477
+ currencies: currenciesByDeposit.get(key) ?? [],
478
+ intents: options.includeIntents ? intentsByDeposit.get(key) ?? [] : void 0
479
+ };
480
+ });
481
+ }
482
+ async fetchDeposits(filter, pagination) {
483
+ const result = await this.client.query({
484
+ query: DEPOSITS_QUERY,
485
+ variables: {
486
+ where: this.buildDepositWhere(filter),
487
+ order_by: this.buildOrderBy(pagination),
488
+ limit: pagination?.limit ?? DEFAULT_LIMIT,
489
+ offset: pagination?.offset ?? 0
490
+ }
491
+ });
492
+ return result.Deposit ?? [];
493
+ }
494
+ async fetchDepositsWithRelations(filter, pagination, options = {}) {
495
+ const deposits = await this.fetchDeposits(filter, pagination);
496
+ return this.attachRelations(deposits, options);
497
+ }
498
+ async fetchDepositsByIds(ids) {
499
+ if (!ids.length) return [];
500
+ const result = await this.client.query({ query: DEPOSITS_BY_IDS_QUERY, variables: { ids } });
501
+ return result.Deposit ?? [];
502
+ }
503
+ async fetchDepositsByIdsWithRelations(ids, options = {}) {
504
+ const deposits = await this.fetchDepositsByIds(ids);
505
+ return this.attachRelations(deposits, options);
506
+ }
507
+ async fetchIntentsForDeposits(depositIds, statuses) {
508
+ if (!depositIds.length) return [];
509
+ return this.fetchIntents({ depositIds, statuses });
510
+ }
511
+ async fetchIntentsByOwner(owner, statuses) {
512
+ if (!owner) return [];
513
+ return this.fetchIntents({ owner, statuses });
514
+ }
515
+ async fetchDepositWithRelations(id, options = {}) {
516
+ const result = await this.client.query({ query: DEPOSIT_WITH_RELATIONS_QUERY, variables: { id } });
517
+ const deposit = result.Deposit_by_pk;
518
+ if (!deposit) return null;
519
+ const base2 = { ...deposit, paymentMethods: result.DepositPaymentMethod ?? [], currencies: result.MethodCurrency ?? [] };
520
+ if (!options.includeIntents) return base2;
521
+ const intents = await this.fetchIntents({ depositIds: [deposit.id], statuses: options.intentStatuses });
522
+ return { ...base2, intents };
523
+ }
524
+ async fetchExpiredIntents(params) {
525
+ const depositIds = params.depositIds.map((id) => id.toLowerCase());
526
+ if (!depositIds.length) return [];
527
+ const result = await this.client.query({
528
+ query: EXPIRED_INTENTS_QUERY,
529
+ variables: {
530
+ now: typeof params.now === "bigint" ? params.now.toString() : params.now,
531
+ limit: params.limit ?? 1e3,
532
+ depositIds
533
+ }
534
+ });
535
+ return result.Intent ?? [];
536
+ }
537
+ async fetchFulfilledIntentEvents(intentHashes) {
538
+ if (!intentHashes.length) return [];
539
+ const uniqueHashes = Array.from(new Set(intentHashes)).filter(Boolean);
540
+ if (!uniqueHashes.length) return [];
541
+ const result = await this.client.query({
542
+ query: INTENT_FULFILLMENTS_QUERY,
543
+ variables: { intentHashes: uniqueHashes }
544
+ });
545
+ return result.Orchestrator_V21_IntentFulfilled ?? [];
546
+ }
547
+ async resolvePayeeHash(params) {
548
+ try {
549
+ const { escrowAddress, depositId, paymentMethodHash } = params;
550
+ if (!escrowAddress || depositId === null || depositId === void 0 || !paymentMethodHash) return null;
551
+ const compositeId = createCompositeDepositId(
552
+ escrowAddress,
553
+ typeof depositId === "bigint" ? depositId : depositId?.toString() ?? ""
554
+ );
555
+ const detail = await this.fetchDepositWithRelations(compositeId, { includeIntents: false });
556
+ if (!detail?.paymentMethods?.length) return null;
557
+ const target = paymentMethodHash.toLowerCase();
558
+ const match = detail.paymentMethods.find((pm) => (pm.paymentMethodHash ?? "").toLowerCase() === target);
559
+ return match?.payeeDetailsHash ?? null;
560
+ } catch {
561
+ return null;
562
+ }
563
+ }
564
+ async fetchDepositsByPayeeHash(payeeHash, options = {}) {
565
+ if (!payeeHash) return [];
566
+ const normalizedHash = payeeHash.toLowerCase();
567
+ const where = {
568
+ payeeDetailsHash: { _ilike: normalizedHash }
569
+ };
570
+ if (options.paymentMethodHash) {
571
+ where.paymentMethodHash = { _eq: options.paymentMethodHash.toLowerCase?.() ?? options.paymentMethodHash };
572
+ }
573
+ const result = await this.client.query({
574
+ query: PAYMENT_METHODS_BY_PAYEE_HASH_QUERY,
575
+ variables: { where, limit: options.limit }
576
+ });
577
+ const seen = /* @__PURE__ */ new Set();
578
+ const depositIds = [];
579
+ for (const pm of result.DepositPaymentMethod ?? []) {
580
+ const id = pm.depositId;
581
+ if (!id) continue;
582
+ const key = id.toLowerCase();
583
+ if (seen.has(key)) continue;
584
+ seen.add(key);
585
+ depositIds.push(id);
586
+ }
587
+ if (!depositIds.length) return [];
588
+ return this.fetchDepositsByIdsWithRelations(depositIds, {
589
+ includeIntents: options.includeIntents,
590
+ intentStatuses: options.intentStatuses
591
+ });
592
+ }
593
+ };
594
+
595
+ // src/indexer/intentVerification.ts
596
+ async function fetchFulfillmentAndPayment(client, intentHash) {
597
+ return client.query({
598
+ query: FULFILLMENT_AND_PAYMENT_QUERY,
599
+ variables: { intentHash }
600
+ });
601
+ }
602
+
603
+ // src/adapters/verification.ts
604
+ async function apiSignIntentV2(request, opts) {
605
+ const controller = new AbortController();
606
+ const id = setTimeout(() => controller.abort(), opts.timeoutMs ?? 15e3);
607
+ try {
608
+ const headers2 = { "Content-Type": "application/json" };
609
+ if (opts.apiKey) headers2["x-api-key"] = opts.apiKey;
610
+ if (opts.authorizationToken) headers2["authorization"] = `Bearer ${opts.authorizationToken}`;
611
+ const res = await fetch(`${opts.baseApiUrl.replace(/\/$/, "")}/v2/verify/intent`, {
612
+ method: "POST",
613
+ headers: headers2,
614
+ body: JSON.stringify(request),
615
+ signal: controller.signal
616
+ });
617
+ if (!res.ok) {
618
+ const text = await res.text().catch(() => "");
619
+ throw new Error(`verify/intent failed: ${res.status} ${res.statusText} ${text}`);
620
+ }
621
+ const json = await res.json();
622
+ const sig = json?.responseObject?.signedIntent;
623
+ const expStr = json?.responseObject?.intentData?.signatureExpiration ?? json?.responseObject?.signatureExpiration;
624
+ if (!sig || !expStr) throw new Error("verify/intent missing signature or expiration");
625
+ return { signature: sig, signatureExpiration: BigInt(expStr) };
626
+ } finally {
627
+ clearTimeout(id);
628
+ }
629
+ }
630
+
631
+ // src/errors/utils.ts
632
+ function parseAPIError(response, responseText) {
633
+ let message = `Request failed: ${response.statusText}`;
634
+ try {
635
+ const parsed = responseText ? JSON.parse(responseText) : void 0;
636
+ if (parsed && (parsed.error || parsed.message)) {
637
+ message = parsed.error || parsed.message;
638
+ }
639
+ } catch {
640
+ if (responseText && responseText.length < 200) message = responseText;
641
+ }
642
+ if (response.status === 429) {
643
+ message = "Too many requests. Please try again later.";
644
+ }
645
+ return new APIError(message, response.status, { url: response.url });
646
+ }
647
+ async function withRetry(fn, maxRetries = 3, delayMs = 1e3, timeoutMs) {
648
+ let lastErr;
649
+ for (let i = 0; i < maxRetries; i++) {
650
+ try {
651
+ if (timeoutMs) {
652
+ const { withTimeout } = await import('./timeout-QB7K5SOB.mjs');
653
+ return await withTimeout(fn(), timeoutMs, `Operation timed out after ${timeoutMs}ms`);
654
+ }
655
+ return await fn();
656
+ } catch (err) {
657
+ lastErr = err;
658
+ const isNetwork = err instanceof NetworkError;
659
+ const isRateLimit = err instanceof APIError && err.status === 429;
660
+ const retryable = isNetwork || isRateLimit;
661
+ if (!retryable || i === maxRetries - 1) throw err;
662
+ const base2 = isRateLimit ? delayMs * Math.pow(2, i) : delayMs;
663
+ const jitter = Math.floor(Math.random() * Math.min(1e3, base2));
664
+ await new Promise((r) => setTimeout(r, base2 + jitter));
665
+ }
666
+ }
667
+ throw lastErr;
668
+ }
669
+
670
+ // src/adapters/attestation.ts
671
+ function headers() {
672
+ return { "Content-Type": "application/json" };
673
+ }
674
+ async function apiCreatePaymentAttestation(payload, attestationServiceUrl, platform, actionType) {
675
+ return withRetry(async () => {
676
+ let res;
677
+ try {
678
+ const endpoint = `/verify/${encodeURIComponent(platform)}/${encodeURIComponent(actionType)}`;
679
+ res = await fetch(`${attestationServiceUrl}${endpoint}`, {
680
+ method: "POST",
681
+ headers: headers(),
682
+ body: JSON.stringify(payload)
683
+ });
684
+ } catch (error) {
685
+ throw new NetworkError("Failed to connect to Attestation Service", {
686
+ endpoint: `/verify/${platform}/${actionType}`,
687
+ error
688
+ });
689
+ }
690
+ if (!res.ok) {
691
+ const errorText = await res.text();
692
+ throw parseAPIError(res, errorText);
693
+ }
694
+ return res.json();
695
+ });
696
+ }
697
+ var abiCoder = AbiCoder.defaultAbiCoder();
698
+ function encodeVerifyPaymentData(params) {
699
+ return abiCoder.encode(
700
+ ["tuple(bytes32,bytes,bytes)"],
701
+ [[params.intentHash, params.paymentProof, params.data]]
702
+ );
703
+ }
704
+ function encodeAddressAsBytes(addr) {
705
+ return abiCoder.encode(["address"], [addr]);
706
+ }
707
+ function encodePaymentAttestation(attestation) {
708
+ const resp = attestation.responseObject;
709
+ const td = resp.typedDataValue;
710
+ const intentHash = td.intentHash;
711
+ const releaseAmount = BigInt(td.releaseAmount);
712
+ const dataHash = td.dataHash;
713
+ const signatures = [resp.signature];
714
+ const encodedPaymentDetails = resp.encodedPaymentDetails;
715
+ if (!intentHash || !releaseAmount || !dataHash || !encodedPaymentDetails) {
716
+ throw new Error("Attestation response missing required fields");
717
+ }
718
+ return abiCoder.encode(
719
+ ["tuple(bytes32,uint256,bytes32,bytes[],bytes,bytes)"],
720
+ [[intentHash, releaseAmount, dataHash, signatures, encodedPaymentDetails, "0x"]]
721
+ );
722
+ }
723
+
724
+ // src/adapters/api.ts
725
+ function createHeaders(apiKey, authToken) {
726
+ const headers2 = { "Content-Type": "application/json" };
727
+ if (apiKey) headers2["x-api-key"] = apiKey;
728
+ if (authToken) headers2["Authorization"] = authToken.startsWith("Bearer ") ? authToken : `Bearer ${authToken}`;
729
+ return headers2;
730
+ }
731
+ function withApiBase(baseApiUrl) {
732
+ const trimmed = (baseApiUrl || "").trim();
733
+ let base2 = trimmed.replace(/\/+$/, "");
734
+ base2 = base2.replace(/\/v1$/i, "");
735
+ base2 = base2.replace(/\/v2$/i, "");
736
+ return base2;
737
+ }
738
+ async function apiFetch({
739
+ url,
740
+ method = "GET",
741
+ body,
742
+ apiKey,
743
+ authToken,
744
+ timeoutMs,
745
+ retryCount = 3,
746
+ retryDelayMs = 1e3
747
+ }) {
748
+ const endpoint = url.replace(/^[^/]*\/\/[^/]*/, "");
749
+ return withRetry(async () => {
750
+ let res;
751
+ try {
752
+ const options = {
753
+ method,
754
+ headers: createHeaders(apiKey, authToken)
755
+ };
756
+ if (body && method !== "GET") {
757
+ options.body = JSON.stringify(body);
758
+ }
759
+ res = await fetch(url, options);
760
+ } catch (error) {
761
+ throw new NetworkError("Failed to connect to API server", { endpoint, error });
762
+ }
763
+ if (!res.ok) {
764
+ const errorText = await res.text();
765
+ throw parseAPIError(res, errorText);
766
+ }
767
+ return res.json();
768
+ }, retryCount, retryDelayMs, timeoutMs);
769
+ }
770
+ async function apiPostDepositDetails(req, baseApiUrl, timeoutMs) {
771
+ return apiFetch({
772
+ url: `${baseApiUrl.replace(/\/$/, "")}/v1/makers/create`,
773
+ method: "POST",
774
+ body: req,
775
+ timeoutMs
776
+ });
777
+ }
778
+ async function apiGetQuote(req, baseApiUrl, timeoutMs, apiKey, authToken) {
779
+ if (req.quotesToReturn !== void 0) {
780
+ if (!Number.isInteger(req.quotesToReturn) || req.quotesToReturn < 1) {
781
+ throw new ValidationError("quotesToReturn must be a positive integer", "quotesToReturn");
782
+ }
783
+ }
784
+ const isExactFiat = req.isExactFiat !== false;
785
+ const endpoint = isExactFiat ? "exact-fiat" : "exact-token";
786
+ let url = `${withApiBase(baseApiUrl)}/v2/quote/${endpoint}`;
787
+ if (req.quotesToReturn) url += `?quotesToReturn=${req.quotesToReturn}`;
788
+ const requestBody = {
789
+ ...req,
790
+ [isExactFiat ? "exactFiatAmount" : "exactTokenAmount"]: req.amount,
791
+ amount: void 0,
792
+ isExactFiat: void 0,
793
+ quotesToReturn: void 0
794
+ };
795
+ Object.keys(requestBody).forEach((k) => requestBody[k] === void 0 && delete requestBody[k]);
796
+ return apiFetch({
797
+ url,
798
+ method: "POST",
799
+ body: requestBody,
800
+ apiKey,
801
+ authToken,
802
+ timeoutMs
803
+ });
804
+ }
805
+ async function apiGetPayeeDetails(req, apiKey, baseApiUrl, authToken, timeoutMs) {
806
+ return apiFetch({
807
+ url: `${baseApiUrl.replace(/\/$/, "")}/v1/makers/${req.processorName}/${req.hashedOnchainId}`,
808
+ method: "GET",
809
+ apiKey,
810
+ authToken,
811
+ timeoutMs
812
+ });
813
+ }
814
+ async function apiValidatePayeeDetails(req, baseApiUrl, timeoutMs) {
815
+ const data = await apiFetch({
816
+ url: `${baseApiUrl.replace(/\/$/, "")}/v1/makers/validate`,
817
+ method: "POST",
818
+ body: req,
819
+ timeoutMs
820
+ });
821
+ if (typeof data?.responseObject === "boolean") {
822
+ return {
823
+ ...data,
824
+ responseObject: { isValid: data.responseObject }
825
+ };
826
+ }
827
+ return data;
828
+ }
829
+ async function apiGetTakerTier(req, apiKey, baseApiUrl, authToken, timeoutMs) {
830
+ const normalizedOwner = req.owner.toLowerCase();
831
+ const query = new URLSearchParams({
832
+ owner: normalizedOwner,
833
+ chainId: String(req.chainId)
834
+ });
835
+ const endpoint = `/v2/taker/tier?${query.toString()}`;
836
+ return apiFetch({
837
+ url: `${withApiBase(baseApiUrl)}${endpoint}`,
838
+ method: "GET",
839
+ apiKey,
840
+ authToken,
841
+ timeoutMs
842
+ });
843
+ }
844
+
845
+ // src/utils/erc20.ts
846
+ var ERC20_ABI = [
847
+ {
848
+ type: "function",
849
+ name: "allowance",
850
+ stateMutability: "view",
851
+ inputs: [
852
+ { name: "owner", type: "address" },
853
+ { name: "spender", type: "address" }
854
+ ],
855
+ outputs: [{ name: "amount", type: "uint256" }]
856
+ },
857
+ {
858
+ type: "function",
859
+ name: "approve",
860
+ stateMutability: "nonpayable",
861
+ inputs: [
862
+ { name: "spender", type: "address" },
863
+ { name: "amount", type: "uint256" }
864
+ ],
865
+ outputs: [{ name: "success", type: "bool" }]
866
+ }
867
+ ];
868
+ var BASE_BUILDER_CODE = "bc_nbn6qkni";
869
+ var ZKP2P_IOS_REFERRER = "zkp2p-ios";
870
+ var ZKP2P_ANDROID_REFERRER = "zkp2p-android";
871
+ function getAttributionDataSuffix(referrer) {
872
+ const codes = [];
873
+ if (referrer) {
874
+ if (Array.isArray(referrer)) {
875
+ codes.push(...referrer);
876
+ } else {
877
+ codes.push(referrer);
878
+ }
879
+ }
880
+ codes.push(BASE_BUILDER_CODE);
881
+ return Attribution.toDataSuffix({ codes });
882
+ }
883
+ function appendAttributionToCalldata(calldata, referrer) {
884
+ const suffix = getAttributionDataSuffix(referrer);
885
+ return concatHex([calldata, suffix]);
886
+ }
887
+ async function sendTransactionWithAttribution(walletClient, request, referrer, overrides) {
888
+ const functionData = encodeFunctionData({
889
+ abi: request.abi,
890
+ functionName: request.functionName,
891
+ args: request.args || []
892
+ });
893
+ const dataWithAttribution = appendAttributionToCalldata(functionData, referrer);
894
+ const {
895
+ gas,
896
+ gasPrice,
897
+ maxFeePerGas,
898
+ maxPriorityFeePerGas,
899
+ nonce,
900
+ value,
901
+ accessList,
902
+ authorizationList
903
+ } = overrides ?? {};
904
+ const optionalOverrides = {
905
+ ...gas !== void 0 ? { gas } : {},
906
+ ...gasPrice !== void 0 ? { gasPrice } : {},
907
+ ...maxFeePerGas !== void 0 ? { maxFeePerGas } : {},
908
+ ...maxPriorityFeePerGas !== void 0 ? { maxPriorityFeePerGas } : {},
909
+ ...nonce !== void 0 ? { nonce } : {},
910
+ ...accessList !== void 0 ? { accessList } : {},
911
+ ...authorizationList !== void 0 ? { authorizationList } : {}
912
+ };
913
+ return walletClient.sendTransaction({
914
+ to: request.address,
915
+ data: dataWithAttribution,
916
+ value: value ?? request.value,
917
+ account: walletClient.account,
918
+ chain: walletClient.chain,
919
+ ...optionalOverrides
920
+ });
921
+ }
922
+
923
+ // src/client/Zkp2pClient.ts
924
+ var Zkp2pClient = class {
925
+ /**
926
+ * Creates a new Zkp2pClient instance.
927
+ *
928
+ * @param opts - Configuration options
929
+ * @throws Error if walletClient is missing an account
930
+ */
931
+ constructor(opts) {
932
+ this.walletClient = opts.walletClient;
933
+ this.chainId = opts.chainId;
934
+ this.runtimeEnv = opts.runtimeEnv ?? "production";
935
+ const inferredRpc = this.walletClient?.chain?.rpcUrls?.default?.http?.[0];
936
+ const defaultRpcUrls = {
937
+ [base.id]: "https://mainnet.base.org",
938
+ [baseSepolia.id]: "https://sepolia.base.org",
939
+ [hardhat.id]: "http://127.0.0.1:8545"
940
+ };
941
+ const rpc = opts.rpcUrl ?? inferredRpc ?? defaultRpcUrls[opts.chainId] ?? "https://mainnet.base.org";
942
+ const chainMap = { [base.id]: base, [baseSepolia.id]: baseSepolia, [hardhat.id]: hardhat };
943
+ const selectedChain = chainMap[this.chainId];
944
+ this.publicClient = createPublicClient({ chain: selectedChain, transport: http(rpc, { batch: false }) });
945
+ const { addresses, abis } = getContracts(this.chainId, this.runtimeEnv);
946
+ this.escrowAddress = addresses.escrow;
947
+ this.escrowAbi = abis.escrow;
948
+ this.orchestratorAddress = addresses.orchestrator;
949
+ this.orchestratorAbi = abis.orchestrator;
950
+ this.unifiedPaymentVerifier = addresses.unifiedPaymentVerifier;
951
+ this.protocolViewerAddress = addresses.protocolViewer;
952
+ this.protocolViewerAbi = abis.protocolViewer;
953
+ const maybeUsdc = addresses.usdc;
954
+ if (maybeUsdc) this._usdcAddress = maybeUsdc;
955
+ const indexerEndpoint = opts.indexerUrl ?? defaultIndexerEndpoint(this.runtimeEnv === "staging" ? "STAGING" : "PRODUCTION");
956
+ this._indexerClient = new IndexerClient(indexerEndpoint);
957
+ this._indexerService = new IndexerDepositService(this._indexerClient);
958
+ this.baseApiUrl = opts.baseApiUrl;
959
+ this.apiKey = opts.apiKey;
960
+ this.authorizationToken = opts.authorizationToken;
961
+ this.apiTimeoutMs = opts.timeouts?.api ?? 15e3;
962
+ }
963
+ isValidHexAddress(addr) {
964
+ if (typeof addr !== "string") return false;
965
+ return /^0x[0-9a-fA-F]{40}$/.test(addr);
966
+ }
967
+ /**
968
+ * Simulate a contract call (validation only) and send with ERC-8021 attribution.
969
+ * Referrer codes are stripped from overrides for simulation and appended to calldata.
970
+ */
971
+ async simulateAndSendWithAttribution(opts) {
972
+ const { referrer, ...txOverrides } = opts.txOverrides ?? {};
973
+ await this.publicClient.simulateContract({
974
+ address: opts.address,
975
+ abi: opts.abi,
976
+ functionName: opts.functionName,
977
+ args: opts.args ?? [],
978
+ account: this.walletClient.account,
979
+ ...txOverrides
980
+ });
981
+ return sendTransactionWithAttribution(
982
+ this.walletClient,
983
+ {
984
+ address: opts.address,
985
+ abi: opts.abi,
986
+ functionName: opts.functionName,
987
+ args: opts.args ?? [],
988
+ value: opts.value ?? txOverrides.value
989
+ },
990
+ referrer,
991
+ txOverrides
992
+ );
993
+ }
994
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
995
+ // ║ CORE: DEPOSIT QUERIES (RPC-first via ProtocolViewer) ║
996
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
997
+ /**
998
+ * Fetches all deposits owned by the connected wallet from on-chain.
999
+ *
1000
+ * This is the primary method for liquidity providers to query their deposits.
1001
+ * Uses ProtocolViewer for instant on-chain reads (no indexer lag).
1002
+ *
1003
+ * @returns Array of deposit views with payment methods and currencies
1004
+ *
1005
+ * @example
1006
+ * ```typescript
1007
+ * const deposits = await client.getDeposits();
1008
+ * for (const d of deposits) {
1009
+ * console.log(`Deposit ${d.depositId}: ${d.availableLiquidity} available`);
1010
+ * }
1011
+ * ```
1012
+ */
1013
+ async getDeposits() {
1014
+ const owner = this.walletClient.account?.address;
1015
+ if (!owner) throw new Error("Wallet client is missing account");
1016
+ return this.getAccountDeposits(owner);
1017
+ }
1018
+ /**
1019
+ * Fetches all deposits owned by a specific address from on-chain.
1020
+ *
1021
+ * Uses ProtocolViewer for instant on-chain reads.
1022
+ *
1023
+ * @param owner - The owner's Ethereum address
1024
+ * @returns Array of deposit views with payment methods and currencies
1025
+ *
1026
+ * @example
1027
+ * ```typescript
1028
+ * const deposits = await client.getAccountDeposits('0x...');
1029
+ * ```
1030
+ */
1031
+ async getAccountDeposits(owner) {
1032
+ return this.getPvAccountDeposits(owner);
1033
+ }
1034
+ /**
1035
+ * Fetches a single deposit by its numeric ID from on-chain.
1036
+ *
1037
+ * Uses ProtocolViewer for instant on-chain reads.
1038
+ *
1039
+ * @param depositId - The deposit ID (numeric)
1040
+ * @returns Deposit view with payment methods, currencies, and intent hashes
1041
+ *
1042
+ * @example
1043
+ * ```typescript
1044
+ * const deposit = await client.getDeposit(42n);
1045
+ * console.log(`Available: ${deposit.availableLiquidity}`);
1046
+ * console.log(`Payment methods: ${deposit.paymentMethods.length}`);
1047
+ * ```
1048
+ */
1049
+ async getDeposit(depositId) {
1050
+ const id = typeof depositId === "bigint" ? depositId : BigInt(depositId);
1051
+ return this.getPvDepositById(id);
1052
+ }
1053
+ /**
1054
+ * Fetches multiple deposits by their IDs from on-chain in a batch.
1055
+ *
1056
+ * @param depositIds - Array of deposit IDs
1057
+ * @returns Array of deposit views
1058
+ */
1059
+ async getDepositsById(depositIds) {
1060
+ const ids = depositIds.map((id) => typeof id === "bigint" ? id : BigInt(id));
1061
+ return this.getPvDepositsFromIds(ids);
1062
+ }
1063
+ /**
1064
+ * Fetches all intents created by the connected wallet from on-chain.
1065
+ *
1066
+ * Uses ProtocolViewer for instant on-chain reads.
1067
+ *
1068
+ * @returns Array of intent views with deposit context
1069
+ *
1070
+ * @example
1071
+ * ```typescript
1072
+ * const intents = await client.getIntents();
1073
+ * for (const i of intents) {
1074
+ * console.log(`Intent ${i.intentHash}: ${i.intent.amount} tokens`);
1075
+ * }
1076
+ * ```
1077
+ */
1078
+ async getIntents() {
1079
+ const owner = this.walletClient.account?.address;
1080
+ if (!owner) throw new Error("Wallet client is missing account");
1081
+ return this.getAccountIntents(owner);
1082
+ }
1083
+ /**
1084
+ * Fetches all intents created by a specific address from on-chain.
1085
+ *
1086
+ * @param owner - The owner's Ethereum address
1087
+ * @returns Array of intent views with deposit context
1088
+ */
1089
+ async getAccountIntents(owner) {
1090
+ return this.getPvAccountIntents(owner);
1091
+ }
1092
+ /**
1093
+ * Fetches a single intent by its hash from on-chain.
1094
+ *
1095
+ * @param intentHash - The intent hash (0x-prefixed, 32 bytes)
1096
+ * @returns Intent view with deposit context
1097
+ */
1098
+ async getIntent(intentHash) {
1099
+ return this.getPvIntent(intentHash);
1100
+ }
1101
+ /**
1102
+ * Resolves the payee details hash for a deposit's payment method from on-chain.
1103
+ *
1104
+ * @param depositId - The deposit ID
1105
+ * @param paymentMethodHash - The payment method hash
1106
+ * @returns The payee details hash, or null if not found
1107
+ */
1108
+ async resolvePayeeHash(depositId, paymentMethodHash) {
1109
+ const deposit = await this.getDeposit(depositId);
1110
+ const pmLower = paymentMethodHash.toLowerCase();
1111
+ for (const pm of deposit.paymentMethods) {
1112
+ if (pm.paymentMethod.toLowerCase() === pmLower) {
1113
+ return pm.verificationData.payeeDetails;
1114
+ }
1115
+ }
1116
+ return null;
1117
+ }
1118
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
1119
+ // ║ ADVANCED: INDEXER QUERIES (for historical/filtered data) ║
1120
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
1121
+ /**
1122
+ * Access to the indexer for advanced queries.
1123
+ *
1124
+ * Use this for:
1125
+ * - Historical data (totalAmountTaken, totalWithdrawn)
1126
+ * - Filtered queries across all deposits (not just by owner)
1127
+ * - Pagination with ordering
1128
+ * - Fulfillment/verification records
1129
+ *
1130
+ * @example
1131
+ * ```typescript
1132
+ * // Query deposits with filters and pagination
1133
+ * const deposits = await client.indexer.getDeposits(
1134
+ * { status: 'ACTIVE', minLiquidity: '1000000' },
1135
+ * { limit: 50, orderBy: 'remainingDeposits', orderDirection: 'desc' }
1136
+ * );
1137
+ *
1138
+ * // Get historical fulfillment data
1139
+ * const fulfillments = await client.indexer.getFulfilledIntentEvents(['0x...']);
1140
+ * ```
1141
+ */
1142
+ get indexer() {
1143
+ const service = this._indexerService;
1144
+ const client = this._indexerClient;
1145
+ return {
1146
+ /** Raw GraphQL client for custom queries */
1147
+ client,
1148
+ /**
1149
+ * Fetches deposits from the indexer with optional filtering and pagination.
1150
+ * Use for advanced queries across all deposits, not just by owner.
1151
+ */
1152
+ getDeposits: (filter, pagination) => {
1153
+ return service.fetchDeposits(filter, pagination);
1154
+ },
1155
+ /**
1156
+ * Fetches deposits with their related payment methods and optionally intents.
1157
+ */
1158
+ getDepositsWithRelations: (filter, pagination, options) => {
1159
+ return service.fetchDepositsWithRelations(filter, pagination, options);
1160
+ },
1161
+ /**
1162
+ * Fetches a single deposit by its composite ID with all related data.
1163
+ * @param id - Composite ID format: "chainId_escrowAddress_depositId"
1164
+ */
1165
+ getDepositById: (id, options) => {
1166
+ return service.fetchDepositWithRelations(id, options);
1167
+ },
1168
+ /**
1169
+ * Fetches intents for multiple deposits.
1170
+ */
1171
+ getIntentsForDeposits: (depositIds, statuses = ["SIGNALED"]) => {
1172
+ return service.fetchIntentsForDeposits(depositIds, statuses);
1173
+ },
1174
+ /**
1175
+ * Fetches all intents created by a specific owner address.
1176
+ */
1177
+ getOwnerIntents: (owner, statuses) => {
1178
+ return service.fetchIntentsByOwner(owner, statuses);
1179
+ },
1180
+ /**
1181
+ * Fetches intents that have expired.
1182
+ */
1183
+ getExpiredIntents: (params) => {
1184
+ return service.fetchExpiredIntents(params);
1185
+ },
1186
+ /**
1187
+ * Fetches fulfillment events for completed intents.
1188
+ */
1189
+ getFulfilledIntentEvents: (intentHashes) => {
1190
+ return service.fetchFulfilledIntentEvents(intentHashes);
1191
+ },
1192
+ /**
1193
+ * Fetches both the fulfillment record and payment verification for an intent.
1194
+ */
1195
+ getFulfillmentAndPayment: (intentHash) => {
1196
+ return fetchFulfillmentAndPayment(client, intentHash);
1197
+ },
1198
+ /**
1199
+ * Fetches deposits that match a specific payee details hash.
1200
+ */
1201
+ getDepositsByPayeeHash: (payeeHash, options = {}) => {
1202
+ return service.fetchDepositsByPayeeHash(payeeHash, options);
1203
+ }
1204
+ };
1205
+ }
1206
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
1207
+ // ║ CORE: DEPOSIT CREATION ║
1208
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
1209
+ /**
1210
+ * Ensures ERC20 token allowance is sufficient for the Escrow contract.
1211
+ *
1212
+ * If the current allowance is less than the requested amount, this method
1213
+ * will submit an approval transaction. Use `maxApprove: true` for unlimited
1214
+ * approval to avoid repeated approval transactions.
1215
+ *
1216
+ * @param params.token - ERC20 token address to approve
1217
+ * @param params.amount - Minimum required allowance amount
1218
+ * @param params.spender - Spender address (defaults to Escrow contract)
1219
+ * @param params.maxApprove - If true, approves MaxUint256 instead of exact amount
1220
+ * @param params.txOverrides - Optional viem transaction overrides
1221
+ * @returns Object with `hadAllowance` (true if no approval needed) and optional `hash`
1222
+ *
1223
+ * @example
1224
+ * ```typescript
1225
+ * // Ensure allowance for 1000 USDC
1226
+ * const { hadAllowance, hash } = await client.ensureAllowance({
1227
+ * token: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
1228
+ * amount: 1000_000000n,
1229
+ * maxApprove: true,
1230
+ * });
1231
+ *
1232
+ * if (!hadAllowance) {
1233
+ * console.log('Approval tx:', hash);
1234
+ * }
1235
+ * ```
1236
+ */
1237
+ async ensureAllowance(params) {
1238
+ const owner = this.walletClient.account?.address;
1239
+ if (!owner) throw new Error("Wallet client is missing account");
1240
+ const spender = params.spender ?? this.escrowAddress;
1241
+ const allowance = await this.publicClient.readContract({ address: params.token, abi: ERC20_ABI, functionName: "allowance", args: [owner, spender] });
1242
+ if (allowance >= params.amount) return { hadAllowance: true };
1243
+ const MAX = (1n << 256n) - 1n;
1244
+ const value = params.maxApprove ? MAX : params.amount;
1245
+ const hash = await this.simulateAndSendWithAttribution({
1246
+ address: params.token,
1247
+ abi: ERC20_ABI,
1248
+ functionName: "approve",
1249
+ args: [spender, value],
1250
+ txOverrides: params.txOverrides
1251
+ });
1252
+ return { hadAllowance: false, hash };
1253
+ }
1254
+ /**
1255
+ * Creates a new USDC deposit in the Escrow contract.
1256
+ *
1257
+ * This is the primary method for liquidity providers to add funds to the protocol.
1258
+ * The deposit can accept intents from multiple payment platforms with different
1259
+ * conversion rates per currency.
1260
+ *
1261
+ * **Important**: Requires `apiKey` or `authorizationToken` to be set.
1262
+ * Call `ensureAllowance()` first to approve USDC spending.
1263
+ *
1264
+ * @param params.token - Token address (USDC)
1265
+ * @param params.amount - Total deposit amount in token units (6 decimals for USDC)
1266
+ * @param params.intentAmountRange - Min/max amount per intent
1267
+ * @param params.processorNames - Payment platforms to accept (e.g., ['wise', 'revolut'])
1268
+ * @param params.depositData - Payee details per processor (e.g., [{ email: '...' }])
1269
+ * @param params.conversionRates - Conversion rates per processor, grouped by currency
1270
+ * @param params.delegate - Optional delegate address that can manage the deposit
1271
+ * @param params.intentGuardian - Optional guardian for intent approval
1272
+ * @param params.retainOnEmpty - Keep deposit active when balance reaches zero
1273
+ * @param params.txOverrides - Optional viem transaction overrides
1274
+ * @returns The deposit details posted to API and the transaction hash
1275
+ *
1276
+ * @throws Error if apiKey/authorizationToken is missing
1277
+ * @throws Error if processorNames, depositData, and conversionRates lengths don't match
1278
+ * @throws Error if a currency is not supported by the specified processor
1279
+ *
1280
+ * @example
1281
+ * ```typescript
1282
+ * // Create a 1000 USDC deposit accepting Wise payments in USD and EUR
1283
+ * const { hash } = await client.createDeposit({
1284
+ * token: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
1285
+ * amount: 1000_000000n,
1286
+ * intentAmountRange: { min: 10_000000n, max: 500_000000n },
1287
+ * processorNames: ['wise'],
1288
+ * depositData: [{ email: 'you@example.com' }],
1289
+ * conversionRates: [[
1290
+ * { currency: 'USD', conversionRate: '1020000000000000000' }, // 1.02
1291
+ * { currency: 'EUR', conversionRate: '1100000000000000000' }, // 1.10
1292
+ * ]],
1293
+ * });
1294
+ * ```
1295
+ */
1296
+ async createDeposit(params) {
1297
+ const methods = getPaymentMethodsCatalog(this.chainId, this.runtimeEnv);
1298
+ if (!Array.isArray(params.processorNames) || params.processorNames.length === 0) {
1299
+ throw new Error("processorNames must be a non-empty array");
1300
+ }
1301
+ if (params.processorNames.length !== params.conversionRates.length) {
1302
+ throw new Error("processorNames and conversionRates length mismatch");
1303
+ }
1304
+ if (params.processorNames.length !== params.depositData.length) {
1305
+ throw new Error("processorNames and depositData length mismatch");
1306
+ }
1307
+ const paymentMethods = params.processorNames.map((name) => resolvePaymentMethodHashFromCatalog(name, methods));
1308
+ const intentGatingService = getGatingServiceAddress(this.chainId, this.runtimeEnv);
1309
+ const baseApiUrl = (this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(/\/$/, "");
1310
+ if (!this.apiKey && !this.authorizationToken) {
1311
+ throw new Error("createDeposit requires apiKey or authorizationToken to post deposit details");
1312
+ }
1313
+ const depositDetails = params.processorNames.map((processorName, index) => ({
1314
+ processorName,
1315
+ depositData: params.depositData[index] || {}
1316
+ }));
1317
+ const apiResponses = await Promise.all(
1318
+ depositDetails.map((req) => apiPostDepositDetails(req, baseApiUrl, this.apiTimeoutMs))
1319
+ );
1320
+ if (!apiResponses.every((r) => r?.success)) {
1321
+ const failed = apiResponses.find((r) => !r?.success);
1322
+ throw new Error(failed?.message || "Failed to create deposit details");
1323
+ }
1324
+ const hashedOnchainIds = apiResponses.map((r) => r.responseObject?.hashedOnchainId);
1325
+ const paymentMethodData = hashedOnchainIds.map((hid) => ({ intentGatingService, payeeDetails: hid, data: "0x" }));
1326
+ params.conversionRates.forEach((group, i) => {
1327
+ const key = params.processorNames[i]?.toLowerCase();
1328
+ const allowed = methods[key]?.currencies?.map((c) => c.toLowerCase());
1329
+ if (allowed && allowed.length) {
1330
+ for (const { currency } of group) {
1331
+ const codeHash = currencyKeccak256(String(currency).toUpperCase()).toLowerCase();
1332
+ if (!allowed.includes(codeHash)) {
1333
+ throw new Error(`Currency ${currency} not supported by ${params.processorNames[i]}. Allowed: ${allowed.join(", ")}`);
1334
+ }
1335
+ }
1336
+ }
1337
+ });
1338
+ const { mapConversionRatesToOnchainMinRate: mapConversionRatesToOnchainMinRate2 } = await import('./currency-ULYH5HL2.mjs');
1339
+ const normalized = params.conversionRates.map((group) => group.map((r) => ({ currency: r.currency, conversionRate: r.conversionRate })));
1340
+ const currencies = mapConversionRatesToOnchainMinRate2(normalized, paymentMethods.length);
1341
+ const args = [{
1342
+ token: params.token,
1343
+ amount: params.amount,
1344
+ intentAmountRange: params.intentAmountRange,
1345
+ paymentMethods,
1346
+ paymentMethodData,
1347
+ currencies,
1348
+ delegate: params.delegate ?? "0x0000000000000000000000000000000000000000",
1349
+ intentGuardian: params.intentGuardian ?? "0x0000000000000000000000000000000000000000",
1350
+ retainOnEmpty: Boolean(params.retainOnEmpty ?? false)
1351
+ }];
1352
+ const hash = await this.simulateAndSendWithAttribution({
1353
+ address: this.escrowAddress,
1354
+ abi: this.escrowAbi,
1355
+ functionName: "createDeposit",
1356
+ args,
1357
+ txOverrides: params.txOverrides
1358
+ });
1359
+ return { depositDetails, hash };
1360
+ }
1361
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
1362
+ // ║ CORE: DEPOSIT MANAGEMENT ║
1363
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
1364
+ /**
1365
+ * Enables or disables a deposit from accepting new intents.
1366
+ *
1367
+ * @param params.depositId - The deposit ID
1368
+ * @param params.accepting - Whether to accept new intents
1369
+ * @param params.txOverrides - Optional viem transaction overrides
1370
+ * @returns Transaction hash
1371
+ */
1372
+ async setAcceptingIntents(params) {
1373
+ return this.simulateAndSendWithAttribution({
1374
+ address: this.escrowAddress,
1375
+ abi: this.escrowAbi,
1376
+ functionName: "setAcceptingIntents",
1377
+ args: [params.depositId, params.accepting],
1378
+ txOverrides: params.txOverrides
1379
+ });
1380
+ }
1381
+ /**
1382
+ * Updates the min/max intent amount range for a deposit.
1383
+ *
1384
+ * @param params.depositId - The deposit ID
1385
+ * @param params.min - Minimum intent amount
1386
+ * @param params.max - Maximum intent amount
1387
+ * @param params.txOverrides - Optional viem transaction overrides
1388
+ * @returns Transaction hash
1389
+ */
1390
+ async setIntentRange(params) {
1391
+ return this.simulateAndSendWithAttribution({
1392
+ address: this.escrowAddress,
1393
+ abi: this.escrowAbi,
1394
+ functionName: "setIntentRange",
1395
+ args: [params.depositId, { min: params.min, max: params.max }],
1396
+ txOverrides: params.txOverrides
1397
+ });
1398
+ }
1399
+ /**
1400
+ * Updates the minimum conversion rate for a specific currency on a payment method.
1401
+ *
1402
+ * @param params.depositId - The deposit ID
1403
+ * @param params.paymentMethod - Payment method hash (bytes32)
1404
+ * @param params.fiatCurrency - Fiat currency hash (bytes32)
1405
+ * @param params.minConversionRate - New minimum conversion rate (18 decimals)
1406
+ * @param params.txOverrides - Optional viem transaction overrides
1407
+ * @returns Transaction hash
1408
+ */
1409
+ async setCurrencyMinRate(params) {
1410
+ return this.simulateAndSendWithAttribution({
1411
+ address: this.escrowAddress,
1412
+ abi: this.escrowAbi,
1413
+ functionName: "setCurrencyMinRate",
1414
+ args: [params.depositId, params.paymentMethod, params.fiatCurrency, params.minConversionRate],
1415
+ txOverrides: params.txOverrides
1416
+ });
1417
+ }
1418
+ /**
1419
+ * Adds additional funds to an existing deposit.
1420
+ * Requires prior approval of the token amount.
1421
+ *
1422
+ * @param params.depositId - The deposit ID to add funds to
1423
+ * @param params.amount - Amount to add (in token units)
1424
+ * @param params.txOverrides - Optional viem transaction overrides
1425
+ * @returns Transaction hash
1426
+ */
1427
+ async addFunds(params) {
1428
+ return this.simulateAndSendWithAttribution({
1429
+ address: this.escrowAddress,
1430
+ abi: this.escrowAbi,
1431
+ functionName: "addFunds",
1432
+ args: [params.depositId, params.amount],
1433
+ txOverrides: params.txOverrides
1434
+ });
1435
+ }
1436
+ /**
1437
+ * Removes funds from a deposit (partial withdrawal).
1438
+ * Can only withdraw available (non-locked) funds.
1439
+ *
1440
+ * @param params.depositId - The deposit ID
1441
+ * @param params.amount - Amount to remove (in token units)
1442
+ * @param params.txOverrides - Optional viem transaction overrides
1443
+ * @returns Transaction hash
1444
+ */
1445
+ async removeFunds(params) {
1446
+ return this.simulateAndSendWithAttribution({
1447
+ address: this.escrowAddress,
1448
+ abi: this.escrowAbi,
1449
+ functionName: "removeFunds",
1450
+ args: [params.depositId, params.amount],
1451
+ txOverrides: params.txOverrides
1452
+ });
1453
+ }
1454
+ /**
1455
+ * Fully withdraws a deposit, returning all available funds to the owner.
1456
+ * The deposit must have no active intents.
1457
+ *
1458
+ * @param params.depositId - The deposit ID to withdraw
1459
+ * @param params.txOverrides - Optional viem transaction overrides
1460
+ * @returns Transaction hash
1461
+ */
1462
+ async withdrawDeposit(params) {
1463
+ return this.simulateAndSendWithAttribution({
1464
+ address: this.escrowAddress,
1465
+ abi: this.escrowAbi,
1466
+ functionName: "withdrawDeposit",
1467
+ args: [params.depositId],
1468
+ txOverrides: params.txOverrides
1469
+ });
1470
+ }
1471
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
1472
+ // ║ CORE: ADVANCED DEPOSIT CONFIGURATION ║
1473
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
1474
+ /**
1475
+ * Sets whether a deposit should remain active when its balance reaches zero.
1476
+ *
1477
+ * @param params.depositId - The deposit ID
1478
+ * @param params.retain - If true, deposit stays active when empty
1479
+ * @param params.txOverrides - Optional viem transaction overrides
1480
+ * @returns Transaction hash
1481
+ */
1482
+ async setRetainOnEmpty(params) {
1483
+ return this.simulateAndSendWithAttribution({
1484
+ address: this.escrowAddress,
1485
+ abi: this.escrowAbi,
1486
+ functionName: "setRetainOnEmpty",
1487
+ args: [params.depositId, params.retain],
1488
+ txOverrides: params.txOverrides
1489
+ });
1490
+ }
1491
+ /**
1492
+ * Assigns a delegate address that can manage the deposit on behalf of the owner.
1493
+ *
1494
+ * @param params.depositId - The deposit ID
1495
+ * @param params.delegate - Address to delegate management to
1496
+ * @param params.txOverrides - Optional viem transaction overrides
1497
+ * @returns Transaction hash
1498
+ */
1499
+ async setDelegate(params) {
1500
+ return this.simulateAndSendWithAttribution({
1501
+ address: this.escrowAddress,
1502
+ abi: this.escrowAbi,
1503
+ functionName: "setDelegate",
1504
+ args: [params.depositId, params.delegate],
1505
+ txOverrides: params.txOverrides
1506
+ });
1507
+ }
1508
+ /**
1509
+ * Removes the delegate from a deposit.
1510
+ *
1511
+ * @param params.depositId - The deposit ID
1512
+ * @param params.txOverrides - Optional viem transaction overrides
1513
+ * @returns Transaction hash
1514
+ */
1515
+ async removeDelegate(params) {
1516
+ return this.simulateAndSendWithAttribution({
1517
+ address: this.escrowAddress,
1518
+ abi: this.escrowAbi,
1519
+ functionName: "removeDelegate",
1520
+ args: [params.depositId],
1521
+ txOverrides: params.txOverrides
1522
+ });
1523
+ }
1524
+ /**
1525
+ * Adds new payment methods to an existing deposit.
1526
+ *
1527
+ * @param params.depositId - The deposit ID
1528
+ * @param params.paymentMethods - Array of payment method hashes to add
1529
+ * @param params.paymentMethodData - Corresponding payment method configuration
1530
+ * @param params.txOverrides - Optional viem transaction overrides
1531
+ * @returns Transaction hash
1532
+ */
1533
+ async addPaymentMethods(params) {
1534
+ return this.simulateAndSendWithAttribution({
1535
+ address: this.escrowAddress,
1536
+ abi: this.escrowAbi,
1537
+ functionName: "addPaymentMethods",
1538
+ args: [params.depositId, params.paymentMethods, params.paymentMethodData],
1539
+ txOverrides: params.txOverrides
1540
+ });
1541
+ }
1542
+ /**
1543
+ * Activates or deactivates a payment method on a deposit.
1544
+ *
1545
+ * @param params.depositId - The deposit ID
1546
+ * @param params.paymentMethod - Payment method hash to modify
1547
+ * @param params.isActive - Whether the payment method should accept intents
1548
+ * @param params.txOverrides - Optional viem transaction overrides
1549
+ * @returns Transaction hash
1550
+ */
1551
+ async setPaymentMethodActive(params) {
1552
+ return this.simulateAndSendWithAttribution({
1553
+ address: this.escrowAddress,
1554
+ abi: this.escrowAbi,
1555
+ functionName: "setPaymentMethodActive",
1556
+ args: [params.depositId, params.paymentMethod, params.isActive],
1557
+ txOverrides: params.txOverrides
1558
+ });
1559
+ }
1560
+ /**
1561
+ * Deactivates a payment method on a deposit (convenience alias for setPaymentMethodActive).
1562
+ *
1563
+ * @param params.depositId - The deposit ID
1564
+ * @param params.paymentMethod - Payment method hash to deactivate
1565
+ * @param params.txOverrides - Optional viem transaction overrides
1566
+ * @returns Transaction hash
1567
+ */
1568
+ async removePaymentMethod(params) {
1569
+ return this.setPaymentMethodActive({ depositId: params.depositId, paymentMethod: params.paymentMethod, isActive: false, txOverrides: params.txOverrides });
1570
+ }
1571
+ /**
1572
+ * Adds new currencies to a payment method on a deposit.
1573
+ *
1574
+ * @param params.depositId - The deposit ID
1575
+ * @param params.paymentMethod - Payment method hash to add currencies to
1576
+ * @param params.currencies - Array of currency configurations with code and min rate
1577
+ * @param params.txOverrides - Optional viem transaction overrides
1578
+ * @returns Transaction hash
1579
+ */
1580
+ async addCurrencies(params) {
1581
+ return this.simulateAndSendWithAttribution({
1582
+ address: this.escrowAddress,
1583
+ abi: this.escrowAbi,
1584
+ functionName: "addCurrencies",
1585
+ args: [params.depositId, params.paymentMethod, params.currencies],
1586
+ txOverrides: params.txOverrides
1587
+ });
1588
+ }
1589
+ /**
1590
+ * Deactivates a currency for a payment method on a deposit.
1591
+ *
1592
+ * @param params.depositId - The deposit ID
1593
+ * @param params.paymentMethod - Payment method hash
1594
+ * @param params.currencyCode - Currency code hash to deactivate
1595
+ * @param params.txOverrides - Optional viem transaction overrides
1596
+ * @returns Transaction hash
1597
+ */
1598
+ async deactivateCurrency(params) {
1599
+ return this.simulateAndSendWithAttribution({
1600
+ address: this.escrowAddress,
1601
+ abi: this.escrowAbi,
1602
+ functionName: "deactivateCurrency",
1603
+ args: [params.depositId, params.paymentMethod, params.currencyCode],
1604
+ txOverrides: params.txOverrides
1605
+ });
1606
+ }
1607
+ /**
1608
+ * Removes (deactivates) a currency from a payment method.
1609
+ * Alias for deactivateCurrency.
1610
+ *
1611
+ * @param params.depositId - The deposit ID
1612
+ * @param params.paymentMethod - Payment method hash
1613
+ * @param params.currencyCode - Currency code hash to remove
1614
+ * @param params.txOverrides - Optional viem transaction overrides
1615
+ * @returns Transaction hash
1616
+ */
1617
+ async removeCurrency(params) {
1618
+ return this.deactivateCurrency(params);
1619
+ }
1620
+ /**
1621
+ * Removes expired intents from a deposit, freeing up locked funds.
1622
+ * Can be called by anyone (permissionless cleanup).
1623
+ *
1624
+ * @param params.depositId - The deposit ID to prune
1625
+ * @param params.txOverrides - Optional viem transaction overrides
1626
+ * @returns Transaction hash
1627
+ */
1628
+ async pruneExpiredIntents(params) {
1629
+ return this.simulateAndSendWithAttribution({
1630
+ address: this.escrowAddress,
1631
+ abi: this.escrowAbi,
1632
+ functionName: "pruneExpiredIntents",
1633
+ args: [params.depositId],
1634
+ txOverrides: params.txOverrides
1635
+ });
1636
+ }
1637
+ // ───────────────────────────────────────────────────────────────────────────
1638
+ // SUPPORTING: INTENT OPERATIONS
1639
+ // (Used by takers/buyers - not primary SDK functionality)
1640
+ // ───────────────────────────────────────────────────────────────────────────
1641
+ /**
1642
+ * **Supporting Method** - Signals intent to use a deposit.
1643
+ *
1644
+ * > **Note**: This method is typically used by takers/buyers who want to
1645
+ * > purchase crypto by paying fiat. Liquidity providers generally don't
1646
+ * > need to call this method directly.
1647
+ *
1648
+ * This reserves funds from a deposit and creates an intent that must be
1649
+ * fulfilled (via `fulfillIntent`) or will expire. The taker commits to
1650
+ * sending fiat payment to the deposit's payee.
1651
+ *
1652
+ * If `gatingServiceSignature` is not provided, the SDK will automatically
1653
+ * fetch one from the API (requires `apiKey` or `authorizationToken`).
1654
+ *
1655
+ * @param params.depositId - The deposit to use
1656
+ * @param params.amount - Amount of tokens to claim (in token units)
1657
+ * @param params.toAddress - Address to receive the tokens when fulfilled
1658
+ * @param params.processorName - Payment platform (e.g., 'wise', 'revolut')
1659
+ * @param params.payeeDetails - Hashed payee details (from deposit)
1660
+ * @param params.fiatCurrencyCode - Fiat currency code (e.g., 'USD', 'EUR')
1661
+ * @param params.conversionRate - Agreed conversion rate (18 decimals)
1662
+ * @param params.referrer - Optional referrer address for fee sharing
1663
+ * @param params.referrerFee - Optional referrer fee amount
1664
+ * @param params.postIntentHook - Optional hook contract to call after signaling
1665
+ * @param params.data - Optional data to pass to the hook
1666
+ * @param params.gatingServiceSignature - Pre-obtained signature (if not auto-fetching)
1667
+ * @param params.signatureExpiration - Signature expiration timestamp
1668
+ * @param params.txOverrides - Optional viem transaction overrides
1669
+ * @returns Transaction hash
1670
+ *
1671
+ * @example
1672
+ * ```typescript
1673
+ * const hash = await client.signalIntent({
1674
+ * depositId: 42n,
1675
+ * amount: 100_000000n, // 100 USDC
1676
+ * toAddress: '0x...',
1677
+ * processorName: 'wise',
1678
+ * payeeDetails: '0x...',
1679
+ * fiatCurrencyCode: 'USD',
1680
+ * conversionRate: 1_020000000000000000n, // 1.02
1681
+ * });
1682
+ * ```
1683
+ */
1684
+ async signalIntent(params) {
1685
+ if (!this.orchestratorAddress || !this.orchestratorAbi) throw new Error("Orchestrator not available");
1686
+ const catalog = getPaymentMethodsCatalog(this.chainId, this.runtimeEnv);
1687
+ const paymentMethod = resolvePaymentMethodHashFromCatalog(params.processorName, catalog);
1688
+ const fiatCurrency = resolveFiatCurrencyBytes32(params.fiatCurrencyCode);
1689
+ const depositId = typeof params.depositId === "bigint" ? params.depositId : BigInt(params.depositId);
1690
+ const amount = typeof params.amount === "bigint" ? params.amount : BigInt(params.amount);
1691
+ const conversionRate = typeof params.conversionRate === "bigint" ? params.conversionRate : BigInt(params.conversionRate);
1692
+ const referrerFee = params.referrerFee === void 0 ? 0n : typeof params.referrerFee === "bigint" ? params.referrerFee : BigInt(params.referrerFee);
1693
+ let { gatingServiceSignature, signatureExpiration } = params;
1694
+ if ((!gatingServiceSignature || !signatureExpiration) && this.baseApiUrl && (this.apiKey || this.authorizationToken)) {
1695
+ const resp = await apiSignIntentV2(
1696
+ {
1697
+ processorName: params.processorName,
1698
+ payeeDetails: params.payeeDetails,
1699
+ depositId: depositId.toString(),
1700
+ amount: amount.toString(),
1701
+ toAddress: params.toAddress,
1702
+ paymentMethod,
1703
+ fiatCurrency,
1704
+ conversionRate: conversionRate.toString(),
1705
+ chainId: this.chainId.toString(),
1706
+ orchestratorAddress: this.orchestratorAddress,
1707
+ escrowAddress: this.escrowAddress
1708
+ },
1709
+ { baseApiUrl: this.baseApiUrl, apiKey: this.apiKey, authorizationToken: this.authorizationToken, timeoutMs: this.apiTimeoutMs }
1710
+ );
1711
+ gatingServiceSignature = resp.signature;
1712
+ signatureExpiration = resp.signatureExpiration;
1713
+ }
1714
+ if (!gatingServiceSignature || !signatureExpiration) throw new Error("Missing gatingServiceSignature/signatureExpiration");
1715
+ const args = [{
1716
+ escrow: this.escrowAddress,
1717
+ depositId,
1718
+ amount,
1719
+ to: params.toAddress,
1720
+ paymentMethod,
1721
+ fiatCurrency,
1722
+ conversionRate,
1723
+ referrer: params.referrer ?? "0x0000000000000000000000000000000000000000",
1724
+ referrerFee,
1725
+ gatingServiceSignature,
1726
+ signatureExpiration: typeof signatureExpiration === "bigint" ? signatureExpiration : BigInt(signatureExpiration),
1727
+ postIntentHook: params.postIntentHook ?? "0x0000000000000000000000000000000000000000",
1728
+ data: params.data ?? "0x"
1729
+ }];
1730
+ return this.simulateAndSendWithAttribution({
1731
+ address: this.orchestratorAddress,
1732
+ abi: this.orchestratorAbi,
1733
+ functionName: "signalIntent",
1734
+ args,
1735
+ txOverrides: params.txOverrides
1736
+ });
1737
+ }
1738
+ /**
1739
+ * **Supporting Method** - Cancels a signaled intent before fulfillment.
1740
+ *
1741
+ * Only the intent owner can cancel. Releases reserved funds back to the deposit.
1742
+ *
1743
+ * @param params.intentHash - The intent hash to cancel (0x-prefixed, 32 bytes)
1744
+ * @param params.txOverrides - Optional viem transaction overrides
1745
+ * @returns Transaction hash
1746
+ */
1747
+ async cancelIntent(params) {
1748
+ if (!this.orchestratorAddress || !this.orchestratorAbi) throw new Error("Orchestrator not available");
1749
+ return this.simulateAndSendWithAttribution({
1750
+ address: this.orchestratorAddress,
1751
+ abi: this.orchestratorAbi,
1752
+ functionName: "cancelIntent",
1753
+ args: [params.intentHash],
1754
+ txOverrides: params.txOverrides
1755
+ });
1756
+ }
1757
+ /**
1758
+ * **Supporting Method** - Releases funds back to the deposit owner.
1759
+ *
1760
+ * Called by the deposit owner when they want to reject an intent
1761
+ * (e.g., payment verification failed or intent expired).
1762
+ *
1763
+ * @param params.intentHash - The intent hash (0x-prefixed, 32 bytes)
1764
+ * @param params.txOverrides - Optional viem transaction overrides
1765
+ * @returns Transaction hash
1766
+ */
1767
+ async releaseFundsToPayer(params) {
1768
+ if (!this.orchestratorAddress || !this.orchestratorAbi) throw new Error("Orchestrator not available");
1769
+ return this.simulateAndSendWithAttribution({
1770
+ address: this.orchestratorAddress,
1771
+ abi: this.orchestratorAbi,
1772
+ functionName: "releaseFundsToPayer",
1773
+ args: [params.intentHash],
1774
+ txOverrides: params.txOverrides
1775
+ });
1776
+ }
1777
+ /**
1778
+ * **Supporting Method** - Fulfills an intent by submitting a payment proof.
1779
+ *
1780
+ * > **Note**: This method is typically used by takers/buyers after they've
1781
+ * > sent fiat payment. Liquidity providers generally don't call this directly.
1782
+ *
1783
+ * This is the final step in the off-ramp flow. After the taker has sent
1784
+ * fiat payment, they generate a proof (via the browser extension) and
1785
+ * submit it here. The SDK handles attestation service calls automatically.
1786
+ *
1787
+ * **Flow:**
1788
+ * 1. Intent parameters are derived from the indexer/ProtocolViewer
1789
+ * 2. Proof is sent to the attestation service for verification
1790
+ * 3. Attestation response is encoded and submitted on-chain
1791
+ * 4. Funds are released to the intent's `toAddress`
1792
+ *
1793
+ * @param params.intentHash - The intent hash to fulfill (0x-prefixed, 32 bytes)
1794
+ * @param params.proof - Payment proof from Reclaim (object or JSON string)
1795
+ * @param params.timestampBufferMs - Allowed timestamp variance (default: 300000ms)
1796
+ * @param params.attestationServiceUrl - Override attestation service URL
1797
+ * @param params.verifyingContract - Override verifier contract address
1798
+ * @param params.postIntentHookData - Data to pass to post-intent hook
1799
+ * @param params.txOverrides - Optional viem transaction overrides
1800
+ * @param params.callbacks - Lifecycle callbacks for UI updates
1801
+ * @returns Transaction hash
1802
+ */
1803
+ async fulfillIntent(params) {
1804
+ if (!this.orchestratorAddress || !this.orchestratorAbi) throw new Error("Orchestrator not available");
1805
+ const intentHash = params.intentHash;
1806
+ const attUrl = params.attestationServiceUrl ?? this.defaultAttestationService();
1807
+ const verifyingContract = params.verifyingContract ?? this.unifiedPaymentVerifier;
1808
+ const inputs = await this.getFulfillIntentInputs(intentHash);
1809
+ const amount = inputs.amount;
1810
+ const fiatCurrency = inputs.fiatCurrency;
1811
+ const conversionRate = inputs.conversionRate;
1812
+ const payeeDetails = inputs.payeeDetails;
1813
+ const timestampMs = inputs.intentTimestampMs;
1814
+ const paymentMethodHash = inputs.paymentMethodHash || "0x";
1815
+ const timestampBufferMs = params.timestampBufferMs ?? "300000";
1816
+ const catalog = getPaymentMethodsCatalog(this.chainId, this.runtimeEnv);
1817
+ const { resolvePaymentMethodNameFromHash: resolvePaymentMethodNameFromHash2 } = await import('./paymentResolution-S6GZR3OY.mjs');
1818
+ const platformName = resolvePaymentMethodNameFromHash2(paymentMethodHash, catalog);
1819
+ if (!platformName) throw new Error("Unknown paymentMethodHash for this network/env; update SDK catalogs.");
1820
+ const { resolvePlatformAttestationConfig } = await import('./constants-DMJE2ALO.mjs');
1821
+ const cfg = resolvePlatformAttestationConfig(platformName);
1822
+ const platform = cfg.actionPlatform;
1823
+ const actionType = cfg.actionType;
1824
+ const zkTlsProof = typeof params.proof === "string" ? params.proof : JSON.stringify(params.proof);
1825
+ const payload = {
1826
+ proofType: "reclaim",
1827
+ proof: zkTlsProof,
1828
+ chainId: this.chainId,
1829
+ verifyingContract,
1830
+ intent: {
1831
+ intentHash,
1832
+ amount,
1833
+ timestampMs,
1834
+ paymentMethod: paymentMethodHash,
1835
+ fiatCurrency,
1836
+ conversionRate,
1837
+ payeeDetails,
1838
+ timestampBufferMs
1839
+ }
1840
+ };
1841
+ params?.callbacks?.onAttestationStart?.();
1842
+ const att = await apiCreatePaymentAttestation(payload, attUrl, platform, actionType);
1843
+ const paymentProof = encodePaymentAttestation(att);
1844
+ const verificationData = encodeVerifyPaymentData({
1845
+ intentHash,
1846
+ paymentProof,
1847
+ data: encodeAddressAsBytes(att.responseObject.signer)
1848
+ });
1849
+ const args = [{
1850
+ paymentProof,
1851
+ intentHash,
1852
+ verificationData,
1853
+ postIntentHookData: params.postIntentHookData ?? "0x"
1854
+ }];
1855
+ const txHash = await this.simulateAndSendWithAttribution({
1856
+ address: this.orchestratorAddress,
1857
+ abi: this.orchestratorAbi,
1858
+ functionName: "fulfillIntent",
1859
+ args,
1860
+ txOverrides: params.txOverrides
1861
+ });
1862
+ params?.callbacks?.onTxSent?.(txHash);
1863
+ return txHash;
1864
+ }
1865
+ defaultAttestationService() {
1866
+ return this.runtimeEnv === "staging" ? "https://attestation-service-staging.zkp2p.xyz" : "https://attestation-service.zkp2p.xyz";
1867
+ }
1868
+ // ───────────────────────────────────────────────────────────────────────────
1869
+ // SUPPORTING: QUOTES API
1870
+ // (Used by frontends to find available liquidity)
1871
+ // ───────────────────────────────────────────────────────────────────────────
1872
+ /**
1873
+ * **Supporting Method** - Fetches quotes for available liquidity.
1874
+ *
1875
+ * > **Note**: This method is typically used by frontend applications to
1876
+ * > display available off-ramp options to users. Liquidity providers can
1877
+ * > use it to see how their deposits appear to takers.
1878
+ *
1879
+ * Returns available quotes from liquidity providers matching the request
1880
+ * criteria. When authenticated, the API returns payee details in each quote.
1881
+ *
1882
+ * @param req - Quote request parameters
1883
+ * @param req.paymentPlatforms - Payment platforms to search (e.g., ['wise', 'revolut'])
1884
+ * @param req.fiatCurrency - Target fiat currency code (e.g., 'USD')
1885
+ * @param req.user - User's address
1886
+ * @param req.recipient - Token recipient address
1887
+ * @param req.destinationChainId - Chain ID for token delivery
1888
+ * @param req.destinationToken - Token address to receive
1889
+ * @param req.amount - Amount (in fiat if isExactFiat, else in tokens)
1890
+ * @param req.isExactFiat - If true, amount is in fiat; quotes return token amounts
1891
+ * @param req.escrowAddresses - Optional filter for specific escrow contracts
1892
+ * @param opts - Optional overrides for API URL and timeout
1893
+ * @returns Quote response with available options
1894
+ *
1895
+ * @example
1896
+ * ```typescript
1897
+ * const quote = await client.getQuote({
1898
+ * paymentPlatforms: ['wise'],
1899
+ * fiatCurrency: 'EUR',
1900
+ * user: '0x...',
1901
+ * recipient: '0x...',
1902
+ * destinationChainId: 8453,
1903
+ * destinationToken: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
1904
+ * amount: '100',
1905
+ * isExactFiat: true,
1906
+ * });
1907
+ *
1908
+ * for (const q of quote.responseObject.quotes) {
1909
+ * console.log(`${q.tokenAmountFormatted} USDC for ${q.fiatAmountFormatted}`);
1910
+ * }
1911
+ * ```
1912
+ */
1913
+ async getQuote(req, opts) {
1914
+ const baseApiUrl = (opts?.baseApiUrl ?? this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(/\/$/, "");
1915
+ const timeoutMs = opts?.timeoutMs ?? this.apiTimeoutMs;
1916
+ const reqWithEscrow = { ...req };
1917
+ if ((!reqWithEscrow.escrowAddresses || reqWithEscrow.escrowAddresses.length === 0) && this.escrowAddress) {
1918
+ reqWithEscrow.escrowAddresses = [this.escrowAddress];
1919
+ }
1920
+ const quote = await apiGetQuote(reqWithEscrow, baseApiUrl, timeoutMs, this.apiKey, this.authorizationToken);
1921
+ const quotes = quote?.responseObject?.quotes ?? [];
1922
+ for (const q of quotes) {
1923
+ const maker = q?.maker;
1924
+ if (maker?.depositData && typeof q === "object") {
1925
+ q.payeeData = maker.depositData;
1926
+ }
1927
+ }
1928
+ return quote;
1929
+ }
1930
+ // ───────────────────────────────────────────────────────────────────────────
1931
+ // SUPPORTING: TAKER TIER
1932
+ // (Used by frontends to display taker limits)
1933
+ // ───────────────────────────────────────────────────────────────────────────
1934
+ /**
1935
+ * **Supporting Method** - Fetches taker tier information for an address.
1936
+ *
1937
+ * > **Note**: Requires `apiKey` or `authorizationToken` to be set.
1938
+ *
1939
+ * @param req - Taker tier request parameters
1940
+ * @param req.owner - Taker address
1941
+ * @param req.chainId - Chain ID
1942
+ * @param opts - Optional overrides for API URL and timeout
1943
+ * @returns Taker tier response
1944
+ */
1945
+ async getTakerTier(req, opts) {
1946
+ const baseApiUrl = (opts?.baseApiUrl ?? this.baseApiUrl ?? "https://api.zkp2p.xyz").replace(/\/$/, "");
1947
+ const timeoutMs = opts?.timeoutMs ?? this.apiTimeoutMs;
1948
+ if (!this.apiKey && !this.authorizationToken) {
1949
+ throw new Error("getTakerTier requires apiKey or authorizationToken");
1950
+ }
1951
+ return apiGetTakerTier(req, this.apiKey, baseApiUrl, this.authorizationToken, timeoutMs);
1952
+ }
1953
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
1954
+ // ║ CORE: ON-CHAIN DEPOSIT VIEWS ║
1955
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
1956
+ requireProtocolViewer() {
1957
+ if (!this.protocolViewerAddress || !this.protocolViewerAbi) {
1958
+ throw new Error("ProtocolViewer not available for this network");
1959
+ }
1960
+ return { address: this.protocolViewerAddress, abi: this.protocolViewerAbi };
1961
+ }
1962
+ /**
1963
+ * Fetches a deposit directly from on-chain ProtocolViewer contract.
1964
+ * Falls back to Escrow.getDeposit if ProtocolViewer is unavailable.
1965
+ *
1966
+ * @param depositId - The deposit ID (string or bigint)
1967
+ * @returns Parsed deposit view with all payment methods and currencies
1968
+ */
1969
+ async getPvDepositById(depositId) {
1970
+ const id = typeof depositId === "bigint" ? depositId : BigInt(depositId);
1971
+ try {
1972
+ const { address, abi } = this.requireProtocolViewer();
1973
+ const raw = await this.publicClient.readContract({ address, abi, functionName: "getDeposit", args: [id] });
1974
+ const { parseDepositView: parseDepositView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
1975
+ return parseDepositView2(raw);
1976
+ } catch (e) {
1977
+ const raw = await this.publicClient.readContract({ address: this.escrowAddress, abi: this.escrowAbi, functionName: "getDeposit", args: [id] });
1978
+ const { parseDepositView: parseDepositView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
1979
+ return parseDepositView2(raw);
1980
+ }
1981
+ }
1982
+ /**
1983
+ * Fetches multiple deposits by ID from on-chain in a batch call.
1984
+ *
1985
+ * @param ids - Array of deposit IDs
1986
+ * @returns Array of parsed deposit views
1987
+ */
1988
+ async getPvDepositsFromIds(ids) {
1989
+ if (!this.protocolViewerAddress || !this.protocolViewerAbi) {
1990
+ const { parseDepositView: parseDepositView3 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
1991
+ const results = [];
1992
+ for (const id of ids) {
1993
+ const raw2 = await this.publicClient.readContract({
1994
+ address: this.escrowAddress,
1995
+ abi: this.escrowAbi,
1996
+ functionName: "getDeposit",
1997
+ args: [typeof id === "bigint" ? id : BigInt(id)]
1998
+ });
1999
+ results.push(parseDepositView3(raw2));
2000
+ }
2001
+ return results;
2002
+ }
2003
+ const bn = ids.map((id) => typeof id === "bigint" ? id : BigInt(id));
2004
+ const raw = await this.publicClient.readContract({
2005
+ address: this.protocolViewerAddress,
2006
+ abi: this.protocolViewerAbi,
2007
+ functionName: "getDepositFromIds",
2008
+ args: [bn]
2009
+ });
2010
+ const { parseDepositView: parseDepositView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
2011
+ return raw.map(parseDepositView2);
2012
+ }
2013
+ /**
2014
+ * Fetches all deposits owned by an address from on-chain.
2015
+ *
2016
+ * @param owner - The owner address
2017
+ * @returns Array of parsed deposit views
2018
+ */
2019
+ async getPvAccountDeposits(owner) {
2020
+ try {
2021
+ const { address, abi } = this.requireProtocolViewer();
2022
+ const raw = await this.publicClient.readContract({ address, abi, functionName: "getAccountDeposits", args: [owner] });
2023
+ const { parseDepositView: parseDepositView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
2024
+ return raw.map(parseDepositView2);
2025
+ } catch (e) {
2026
+ const raw = await this.publicClient.readContract({ address: this.escrowAddress, abi: this.escrowAbi, functionName: "getAccountDeposits", args: [owner] });
2027
+ const { parseDepositView: parseDepositView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
2028
+ return raw.map(parseDepositView2);
2029
+ }
2030
+ }
2031
+ /**
2032
+ * Fetches all intents created by an address from on-chain.
2033
+ * Requires ProtocolViewer to be available.
2034
+ *
2035
+ * @param owner - The owner address
2036
+ * @returns Array of parsed intent views
2037
+ */
2038
+ async getPvAccountIntents(owner) {
2039
+ const { address, abi } = this.requireProtocolViewer();
2040
+ const raw = await this.publicClient.readContract({
2041
+ address,
2042
+ abi,
2043
+ functionName: "getAccountIntents",
2044
+ args: [owner]
2045
+ });
2046
+ const { parseIntentView: parseIntentView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
2047
+ return raw.map(parseIntentView2);
2048
+ }
2049
+ /**
2050
+ * Fetches a single intent by hash from on-chain.
2051
+ *
2052
+ * @param intentHash - The intent hash (0x-prefixed, 32 bytes)
2053
+ * @returns Parsed intent view with deposit context
2054
+ */
2055
+ async getPvIntent(intentHash) {
2056
+ const { address, abi } = this.requireProtocolViewer();
2057
+ const raw = await this.publicClient.readContract({
2058
+ address,
2059
+ abi,
2060
+ functionName: "getIntent",
2061
+ args: [intentHash]
2062
+ });
2063
+ const { parseIntentView: parseIntentView2 } = await import('./protocolViewerParsers-DTJLHUCH.mjs');
2064
+ return parseIntentView2(raw);
2065
+ }
2066
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
2067
+ // ║ CORE: UTILITIES ║
2068
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
2069
+ /**
2070
+ * Returns the USDC token address for the current network (if known).
2071
+ *
2072
+ * @returns USDC address or undefined if not configured
2073
+ */
2074
+ getUsdcAddress() {
2075
+ return this._usdcAddress;
2076
+ }
2077
+ /**
2078
+ * Returns all deployed contract addresses for the current network/environment.
2079
+ *
2080
+ * @returns Object with escrow, orchestrator, protocolViewer, verifier, and USDC addresses
2081
+ */
2082
+ getDeployedAddresses() {
2083
+ return {
2084
+ escrow: this.escrowAddress,
2085
+ orchestrator: this.orchestratorAddress,
2086
+ protocolViewer: this.protocolViewerAddress,
2087
+ unifiedPaymentVerifier: this.unifiedPaymentVerifier,
2088
+ usdc: this._usdcAddress
2089
+ };
2090
+ }
2091
+ /**
2092
+ * Resolves all parameters needed to fulfill an intent.
2093
+ *
2094
+ * Attempts to fetch from ProtocolViewer first (on-chain source of truth),
2095
+ * then falls back to the indexer. This is called internally by `fulfillIntent`
2096
+ * but exposed for advanced use cases.
2097
+ *
2098
+ * @param intentHash - The intent hash to resolve
2099
+ * @returns Intent parameters needed for fulfillment
2100
+ * @throws Error if intent not found or payee details cannot be resolved
2101
+ */
2102
+ async getFulfillIntentInputs(intentHash) {
2103
+ try {
2104
+ if (this.protocolViewerAddress && this.protocolViewerAbi) {
2105
+ const view = await this.getPvIntent(intentHash);
2106
+ const pmHash = view.intent.paymentMethod.toLowerCase();
2107
+ const matched = (view.deposit.paymentMethods || []).find((pm) => pm.paymentMethod?.toLowerCase?.() === pmHash);
2108
+ const payee2 = matched?.verificationData?.payeeDetails;
2109
+ if (payee2) {
2110
+ return {
2111
+ amount: view.intent.amount.toString(),
2112
+ fiatCurrency: view.intent.fiatCurrency,
2113
+ conversionRate: view.intent.conversionRate.toString(),
2114
+ payeeDetails: payee2,
2115
+ intentTimestampMs: (BigInt(view.intent.timestamp) * 1000n).toString(),
2116
+ paymentMethodHash: view.intent.paymentMethod
2117
+ };
2118
+ }
2119
+ }
2120
+ } catch {
2121
+ }
2122
+ const query = (
2123
+ /* GraphQL */
2124
+ `
2125
+ query GetIntentMinimal($hash: String!) {
2126
+ Intent(where: { intentHash: { _eq: $hash } }, limit: 1) {
2127
+ amount
2128
+ fiatCurrency
2129
+ conversionRate
2130
+ paymentMethodHash
2131
+ depositId
2132
+ signalTimestamp
2133
+ }
2134
+ }
2135
+ `
2136
+ );
2137
+ const res = await this._indexerClient.query({
2138
+ query,
2139
+ variables: { hash: intentHash.toLowerCase() }
2140
+ });
2141
+ const rec = res?.Intent?.[0];
2142
+ if (!rec) throw new Error("Intent not found on indexer");
2143
+ if (!rec.signalTimestamp) throw new Error("Intent signal timestamp not found on indexer");
2144
+ const deposit = await this._indexerService.fetchDepositWithRelations(rec.depositId, { includeIntents: false });
2145
+ let payee;
2146
+ const pmHashLower = (rec.paymentMethodHash || "").toLowerCase();
2147
+ for (const pm of deposit?.paymentMethods || []) {
2148
+ if ((pm.paymentMethodHash || "").toLowerCase() === pmHashLower) {
2149
+ payee = pm.payeeDetailsHash;
2150
+ break;
2151
+ }
2152
+ }
2153
+ if (!payee) throw new Error("Payee details not found for intent");
2154
+ return {
2155
+ amount: rec.amount,
2156
+ fiatCurrency: rec.fiatCurrency,
2157
+ conversionRate: rec.conversionRate,
2158
+ payeeDetails: payee,
2159
+ intentTimestampMs: (BigInt(rec.signalTimestamp) * 1000n).toString(),
2160
+ paymentMethodHash: rec.paymentMethodHash || "0x0000000000000000000000000000000000000000000000000000000000000000"
2161
+ };
2162
+ }
2163
+ };
2164
+
2165
+ // src/utils/logger.ts
2166
+ var currentLevel = "info";
2167
+ function setLogLevel(level) {
2168
+ currentLevel = level;
2169
+ }
2170
+ function shouldLog(level) {
2171
+ switch (currentLevel) {
2172
+ case "debug":
2173
+ return true;
2174
+ case "info":
2175
+ return level !== "debug";
2176
+ case "error":
2177
+ return level === "error";
2178
+ default:
2179
+ return true;
2180
+ }
2181
+ }
2182
+ var logger = {
2183
+ debug: (...args) => {
2184
+ if (shouldLog("debug")) {
2185
+ console.log("[DEBUG]", ...args);
2186
+ }
2187
+ },
2188
+ info: (...args) => {
2189
+ if (shouldLog("info")) {
2190
+ console.log("[INFO]", ...args);
2191
+ }
2192
+ },
2193
+ warn: (...args) => {
2194
+ if (shouldLog("info")) {
2195
+ console.warn("[WARN]", ...args);
2196
+ }
2197
+ },
2198
+ error: (...args) => {
2199
+ console.error("[ERROR]", ...args);
2200
+ }
2201
+ };
2202
+
2203
+ export { BASE_BUILDER_CODE, IndexerClient, IndexerDepositService, Zkp2pClient as OfframpClient, ZKP2P_ANDROID_REFERRER, ZKP2P_IOS_REFERRER, Zkp2pClient, apiGetPayeeDetails, apiGetTakerTier, apiPostDepositDetails, apiValidatePayeeDetails, appendAttributionToCalldata, convertDepositsForLiquidity, convertIndexerDepositToEscrowView, convertIndexerIntentsToEscrowViews, createCompositeDepositId, defaultIndexerEndpoint, fetchFulfillmentAndPayment as fetchIndexerFulfillmentAndPayment, getAttributionDataSuffix, logger, sendTransactionWithAttribution, setLogLevel };
2204
+ //# sourceMappingURL=index.mjs.map
2205
+ //# sourceMappingURL=index.mjs.map