@diviswap/sdk 1.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +510 -0
  3. package/bin/create-diviswap-app.js +25 -0
  4. package/bin/diviswap-sdk.js +4 -0
  5. package/dist/cli/index.js +1888 -0
  6. package/dist/cli/templates/nextjs-app/actions.ts.hbs +259 -0
  7. package/dist/cli/templates/nextjs-app/api-hooks.ts.hbs +439 -0
  8. package/dist/cli/templates/nextjs-app/api-route.ts.hbs +502 -0
  9. package/dist/cli/templates/nextjs-app/auth-context.tsx.hbs +59 -0
  10. package/dist/cli/templates/nextjs-app/client.ts.hbs +116 -0
  11. package/dist/cli/templates/nextjs-app/dashboard-hooks.ts.hbs +180 -0
  12. package/dist/cli/templates/nextjs-app/example-page.tsx.hbs +276 -0
  13. package/dist/cli/templates/nextjs-app/hooks.ts.hbs +252 -0
  14. package/dist/cli/templates/nextjs-app/kyc-hooks.ts.hbs +87 -0
  15. package/dist/cli/templates/nextjs-app/kyc-wizard.css.hbs +433 -0
  16. package/dist/cli/templates/nextjs-app/kyc-wizard.tsx.hbs +711 -0
  17. package/dist/cli/templates/nextjs-app/layout-wrapper.tsx.hbs +13 -0
  18. package/dist/cli/templates/nextjs-app/layout.tsx.hbs +13 -0
  19. package/dist/cli/templates/nextjs-app/middleware.ts.hbs +49 -0
  20. package/dist/cli/templates/nextjs-app/provider-wrapper.tsx.hbs +8 -0
  21. package/dist/cli/templates/nextjs-app/provider.tsx.hbs +408 -0
  22. package/dist/cli/templates/nextjs-app/setup-provider.tsx.hbs +25 -0
  23. package/dist/cli/templates/nextjs-app/types.ts.hbs +159 -0
  24. package/dist/cli/templates/react/api-client-wrapper.ts.hbs +89 -0
  25. package/dist/cli/templates/react/example.tsx.hbs +69 -0
  26. package/dist/cli/templates/react/tanstack-hooks.ts.hbs +185 -0
  27. package/dist/cli/templates/webhooks/nextjs.hbs +98 -0
  28. package/dist/index.d.mts +91 -0
  29. package/dist/index.d.ts +91 -0
  30. package/dist/index.js +2339 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/index.mjs +2313 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/dist/react/index.d.mts +192 -0
  35. package/dist/react/index.d.ts +192 -0
  36. package/dist/react/index.js +1083 -0
  37. package/dist/react/index.js.map +1 -0
  38. package/dist/react/index.mjs +1064 -0
  39. package/dist/react/index.mjs.map +1 -0
  40. package/dist/wallet-BEGvzNtB.d.mts +1614 -0
  41. package/dist/wallet-BEGvzNtB.d.ts +1614 -0
  42. package/package.json +102 -0
  43. package/src/cli/templates/index.ts +65 -0
  44. package/src/cli/templates/nextjs-app/actions.ts.hbs +259 -0
  45. package/src/cli/templates/nextjs-app/api-hooks.ts.hbs +439 -0
  46. package/src/cli/templates/nextjs-app/api-route.ts.hbs +502 -0
  47. package/src/cli/templates/nextjs-app/auth-context.tsx.hbs +59 -0
  48. package/src/cli/templates/nextjs-app/client.ts.hbs +116 -0
  49. package/src/cli/templates/nextjs-app/dashboard-hooks.ts.hbs +180 -0
  50. package/src/cli/templates/nextjs-app/example-page.tsx.hbs +276 -0
  51. package/src/cli/templates/nextjs-app/hooks.ts.hbs +252 -0
  52. package/src/cli/templates/nextjs-app/kyc-hooks.ts.hbs +87 -0
  53. package/src/cli/templates/nextjs-app/kyc-wizard.css.hbs +433 -0
  54. package/src/cli/templates/nextjs-app/kyc-wizard.tsx.hbs +711 -0
  55. package/src/cli/templates/nextjs-app/layout-wrapper.tsx.hbs +13 -0
  56. package/src/cli/templates/nextjs-app/layout.tsx.hbs +13 -0
  57. package/src/cli/templates/nextjs-app/middleware.ts.hbs +49 -0
  58. package/src/cli/templates/nextjs-app/provider-wrapper.tsx.hbs +8 -0
  59. package/src/cli/templates/nextjs-app/provider.tsx.hbs +408 -0
  60. package/src/cli/templates/nextjs-app/setup-provider.tsx.hbs +25 -0
  61. package/src/cli/templates/nextjs-app/types.ts.hbs +159 -0
  62. package/src/cli/templates/react/api-client-wrapper.ts.hbs +89 -0
  63. package/src/cli/templates/react/example.tsx.hbs +69 -0
  64. package/src/cli/templates/react/tanstack-hooks.ts.hbs +185 -0
  65. package/src/cli/templates/shared/client.ts +78 -0
  66. package/src/cli/templates/webhooks/nextjs.hbs +98 -0
package/dist/index.js ADDED
@@ -0,0 +1,2339 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var crypto__default = /*#__PURE__*/_interopDefault(crypto);
8
+
9
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
10
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
11
+ }) : x)(function(x) {
12
+ if (typeof require !== "undefined") return require.apply(this, arguments);
13
+ throw Error('Dynamic require of "' + x + '" is not supported');
14
+ });
15
+
16
+ // src/errors.ts
17
+ var DiviswapError = class _DiviswapError extends Error {
18
+ constructor(message, code, statusCode, details) {
19
+ super(message);
20
+ this.code = code;
21
+ this.statusCode = statusCode;
22
+ this.details = details;
23
+ this.name = "DiviswapError";
24
+ Object.setPrototypeOf(this, _DiviswapError.prototype);
25
+ }
26
+ };
27
+ var AuthenticationError = class extends DiviswapError {
28
+ constructor(message, details) {
29
+ super(message, "AUTHENTICATION_ERROR", 401, details);
30
+ this.name = "AuthenticationError";
31
+ }
32
+ };
33
+ var ValidationError = class extends DiviswapError {
34
+ constructor(message, details) {
35
+ super(message, "VALIDATION_ERROR", 400, details);
36
+ this.name = "ValidationError";
37
+ }
38
+ };
39
+ var NetworkError = class extends DiviswapError {
40
+ constructor(message, details) {
41
+ super(message, "NETWORK_ERROR", void 0, details);
42
+ this.name = "NetworkError";
43
+ }
44
+ };
45
+ var ConfigurationError = class extends DiviswapError {
46
+ constructor(message, details) {
47
+ super(message, "CONFIGURATION_ERROR", void 0, details);
48
+ this.name = "ConfigurationError";
49
+ }
50
+ };
51
+ var LiberExError = DiviswapError;
52
+
53
+ // src/modules/auth.ts
54
+ var AuthModule = class {
55
+ constructor(client) {
56
+ this.client = client;
57
+ this.client.setRefreshCallback(this.refreshToken.bind(this));
58
+ }
59
+ /**
60
+ * Register a new user
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const { user, accessToken } = await diviswap.auth.register({
65
+ * email: 'user@example.com',
66
+ * password: 'secure-password',
67
+ * firstName: 'John',
68
+ * lastName: 'Doe'
69
+ * });
70
+ * ```
71
+ */
72
+ async register(data) {
73
+ const requestData = {
74
+ email: data.email,
75
+ password: data.password,
76
+ first_name: data.firstName || "Test",
77
+ last_name: data.lastName || "User",
78
+ // Individual object is REQUIRED by the backend
79
+ individual: {
80
+ // Use 'USA' (3-letter code) as seen in working lbx-landing implementation
81
+ residential_country_code: "USA",
82
+ residential_address_line_one: "123 Main Street",
83
+ residential_address_line_two: "",
84
+ residential_city: "Anytown",
85
+ residential_state: "CA",
86
+ residential_postal_code: "12345",
87
+ id_type: "ssn",
88
+ // Add id_type field as seen in lbx-landing
89
+ id_country_code: "USA",
90
+ dob: "1990-01-01",
91
+ id_number: "123456789"
92
+ // Remove dashes from SSN like lbx-landing does
93
+ }
94
+ };
95
+ if (data.individual) {
96
+ requestData.individual = data.individual;
97
+ }
98
+ if (data.phone) requestData.phone = data.phone;
99
+ if (data.referralCode) requestData.referral_code = data.referralCode;
100
+ const response = await this.client.post(
101
+ "/api/v1/register",
102
+ requestData,
103
+ { useApiKey: true }
104
+ );
105
+ const authResponse = {
106
+ accessToken: response.access_token || response.accessToken,
107
+ refreshToken: response.refresh_token || response.refreshToken,
108
+ user: response.user || { id: response.user_id || response.id, email: data.email }
109
+ };
110
+ if (authResponse.accessToken) {
111
+ this.client.setTokens(authResponse.accessToken, authResponse.refreshToken);
112
+ }
113
+ return authResponse;
114
+ }
115
+ /**
116
+ * Login an existing user
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const { user, accessToken } = await diviswap.auth.login({
121
+ * email: 'user@example.com',
122
+ * password: 'secure-password'
123
+ * });
124
+ * ```
125
+ */
126
+ async login(credentials) {
127
+ const response = await this.client.post(
128
+ "/api/v1/login",
129
+ credentials,
130
+ { useApiKey: true }
131
+ // useApiKey: true means use API key auth, not JWT
132
+ );
133
+ const authResponse = {
134
+ accessToken: response.access_token || response.accessToken,
135
+ refreshToken: response.refresh_token || response.refreshToken,
136
+ user: response.user || { id: response.user_id || response.id, email: credentials.email }
137
+ };
138
+ if (authResponse.accessToken) {
139
+ this.client.setTokens(authResponse.accessToken, authResponse.refreshToken);
140
+ }
141
+ return authResponse;
142
+ }
143
+ /**
144
+ * Get current user profile
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const user = await diviswap.auth.getProfile();
149
+ * console.log(user.email, user.kycStatus);
150
+ * ```
151
+ *
152
+ * Note: This endpoint is not yet available in the v1 API
153
+ */
154
+ async getProfile() {
155
+ throw new Error("User profile endpoint not available in v1 API yet");
156
+ }
157
+ /**
158
+ * Update user profile
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * const updatedUser = await diviswap.auth.updateProfile({
163
+ * firstName: 'Jane',
164
+ * lastName: 'Smith'
165
+ * });
166
+ * ```
167
+ *
168
+ * Note: This endpoint is not yet available in the v1 API
169
+ */
170
+ async updateProfile(_data) {
171
+ throw new Error("Update profile endpoint not available in v1 API yet");
172
+ }
173
+ /**
174
+ * Request password reset
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * await diviswap.auth.requestPasswordReset('user@example.com');
179
+ * ```
180
+ *
181
+ * Note: This endpoint is not yet available in the v1 API
182
+ */
183
+ async requestPasswordReset(_email) {
184
+ throw new Error("Password reset endpoint not available in v1 API yet");
185
+ }
186
+ /**
187
+ * Set new password with reset token
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * await diviswap.auth.setPassword('reset-token', 'new-secure-password');
192
+ * ```
193
+ *
194
+ * Note: This endpoint is not yet available in the v1 API
195
+ */
196
+ async setPassword(_token, _password) {
197
+ throw new Error("Set password endpoint not available in v1 API yet");
198
+ }
199
+ /**
200
+ * Logout current user
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * await diviswap.auth.logout();
205
+ * ```
206
+ */
207
+ async logout() {
208
+ this.client.clearTokens();
209
+ }
210
+ /**
211
+ * Get compliance status
212
+ * @deprecated Use diviswap.kyc.getComplianceStatus() instead
213
+ */
214
+ async getComplianceStatus() {
215
+ console.warn("auth.getComplianceStatus() is deprecated. Use kyc.getComplianceStatus() instead.");
216
+ throw new Error("Compliance status endpoint not available in v1 API yet");
217
+ }
218
+ /**
219
+ * Check if user is authenticated
220
+ */
221
+ isAuthenticated() {
222
+ return !!this.client.tokenManager.getAccessToken();
223
+ }
224
+ /**
225
+ * Refresh access token (internal)
226
+ *
227
+ * Note: This endpoint is not yet available in the v1 API
228
+ */
229
+ async refreshToken(_refreshToken) {
230
+ throw new Error("Token refresh endpoint not available in v1 API yet");
231
+ }
232
+ };
233
+
234
+ // src/modules/payees.ts
235
+ var PayeesModule = class {
236
+ constructor(client) {
237
+ this.client = client;
238
+ }
239
+ /**
240
+ * Create a new payee (bank account)
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * // Bank account
245
+ * const bankAccount = await diviswap.payees.create({
246
+ * nickname: 'My Checking',
247
+ * accountNumber: '123456789',
248
+ * routingNumber: '021000021',
249
+ * accountType: 'checking',
250
+ * setAsDefault: true
251
+ * });
252
+ *
253
+ * // Debit card
254
+ * const debitCard = await diviswap.payees.create({
255
+ * nickname: 'My Debit Card',
256
+ * accountType: 'debit_card',
257
+ * debitCard: {
258
+ * number: '4111111111111111',
259
+ * expirationMonth: '12',
260
+ * expirationYear: '2025',
261
+ * cvv: '123'
262
+ * },
263
+ * setAsDefault: false
264
+ * });
265
+ * ```
266
+ */
267
+ async create(data) {
268
+ try {
269
+ if (data.accountType === "debit_card") {
270
+ if (!data.debitCard) {
271
+ throw new Error("Debit card information is required for debit_card account type");
272
+ }
273
+ return await this.client.post("/api/v1/payees", {
274
+ name: data.nickname,
275
+ debit_card: {
276
+ number: data.debitCard.number,
277
+ expiration_month: data.debitCard.expirationMonth,
278
+ expiration_year: data.debitCard.expirationYear,
279
+ cvv: data.debitCard.cvv
280
+ },
281
+ set_as_default: data.setAsDefault || false
282
+ });
283
+ } else {
284
+ if (!data.accountNumber || !data.routingNumber) {
285
+ throw new Error("Account number and routing number are required for bank accounts");
286
+ }
287
+ return await this.client.post("/api/v1/payees", {
288
+ name: data.nickname,
289
+ account_number: data.accountNumber,
290
+ routing_number: data.routingNumber,
291
+ type: (data.accountType || "checking").toUpperCase(),
292
+ set_as_default: data.setAsDefault || false
293
+ });
294
+ }
295
+ } catch (error) {
296
+ throw new Error(`Failed to create payee: ${error.message}`);
297
+ }
298
+ }
299
+ /**
300
+ * List all payees
301
+ *
302
+ * @example
303
+ * ```typescript
304
+ * const payees = await diviswap.payees.list();
305
+ * const defaultPayee = payees.find(p => p.isDefault);
306
+ * ```
307
+ */
308
+ async list() {
309
+ const response = await this.client.get("/api/v1/users/payees", { useApiKey: false });
310
+ return this.parsePayeesResponse(response);
311
+ }
312
+ parsePayeesResponse(response) {
313
+ if (Array.isArray(response)) {
314
+ return response;
315
+ }
316
+ if (response && typeof response === "object") {
317
+ if (response.data && Array.isArray(response.data)) {
318
+ return response.data;
319
+ }
320
+ if (response.payees && Array.isArray(response.payees)) {
321
+ return response.payees;
322
+ }
323
+ if (response.results && Array.isArray(response.results)) {
324
+ return response.results;
325
+ }
326
+ }
327
+ return [];
328
+ }
329
+ /**
330
+ * Get a specific payee
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * const payee = await diviswap.payees.get('payee-id');
335
+ * ```
336
+ */
337
+ async get(payeeId) {
338
+ const payees = await this.list();
339
+ const payee = payees.find((p) => p.id === payeeId);
340
+ if (!payee) {
341
+ throw new Error(`Payee ${payeeId} not found`);
342
+ }
343
+ return payee;
344
+ }
345
+ /**
346
+ * Set a payee as default
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * await diviswap.payees.setDefault('payee-id');
351
+ * ```
352
+ */
353
+ async setDefault(payeeId) {
354
+ return this.client.put("/api/v1/users/payees", {
355
+ payeeId,
356
+ setAsDefault: true
357
+ }, { useApiKey: false });
358
+ }
359
+ /**
360
+ * Delete a payee
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * await diviswap.payees.delete('payee-id');
365
+ * ```
366
+ */
367
+ async delete(payeeId) {
368
+ return this.client.delete(
369
+ `/api/v1/users/payees/${payeeId}`,
370
+ { useApiKey: false }
371
+ );
372
+ }
373
+ /**
374
+ * Get verification status of a payee
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * const status = await diviswap.payees.getVerificationStatus('payee-id');
379
+ * console.log(status.verified, status.microDepositsStatus);
380
+ * ```
381
+ */
382
+ async getVerificationStatus(_payeeId) {
383
+ throw new Error("Payee verification status endpoint not available in v1 API yet");
384
+ }
385
+ /**
386
+ * Verify a payee with micro-deposit amounts
387
+ *
388
+ * @example
389
+ * ```typescript
390
+ * const result = await diviswap.payees.verify('payee-id', {
391
+ * amount1: 0.32,
392
+ * amount2: 0.45
393
+ * });
394
+ * ```
395
+ */
396
+ async verify(_payeeId, _data) {
397
+ throw new Error("Payee verification endpoint not available in v1 API yet");
398
+ }
399
+ /**
400
+ * Get the default payee
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * const defaultPayee = await diviswap.payees.getDefault();
405
+ * if (!defaultPayee) {
406
+ * console.log('No default payee set');
407
+ * }
408
+ * ```
409
+ */
410
+ async getDefault() {
411
+ const payees = await this.list();
412
+ return payees.find((p) => p.isDefault) || null;
413
+ }
414
+ };
415
+
416
+ // src/constants/addresses.ts
417
+ var PRODUCTION_DEPOSIT_ADDRESSES = {
418
+ ethereum: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
419
+ base: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
420
+ polygon: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
421
+ solana: "EokHeEoZpGtBNeuJKRPvtxzXqaXz6bM5zsVB5TVPtNee"
422
+ };
423
+ var SANDBOX_DEPOSIT_ADDRESSES = {
424
+ ethereum: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
425
+ // Same address for all environments
426
+ base: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
427
+ polygon: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
428
+ solana: "EokHeEoZpGtBNeuJKRPvtxzXqaXz6bM5zsVB5TVPtNee"
429
+ };
430
+ var DEVELOPMENT_DEPOSIT_ADDRESSES = {
431
+ ethereum: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
432
+ // Same unified address
433
+ base: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
434
+ polygon: "0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651",
435
+ solana: "EokHeEoZpGtBNeuJKRPvtxzXqaXz6bM5zsVB5TVPtNee"
436
+ };
437
+ function getDepositAddresses(environment) {
438
+ switch (environment) {
439
+ case "production":
440
+ return PRODUCTION_DEPOSIT_ADDRESSES;
441
+ case "sandbox":
442
+ return SANDBOX_DEPOSIT_ADDRESSES;
443
+ case "development":
444
+ return DEVELOPMENT_DEPOSIT_ADDRESSES;
445
+ default:
446
+ return SANDBOX_DEPOSIT_ADDRESSES;
447
+ }
448
+ }
449
+ var CHAIN_ID_TO_NAME = {
450
+ 1: "ethereum",
451
+ 5: "goerli",
452
+ 11155111: "sepolia",
453
+ 137: "polygon",
454
+ 80001: "mumbai",
455
+ 8453: "base",
456
+ 84531: "base-goerli",
457
+ 84532: "base-sepolia"
458
+ };
459
+ var CHAIN_NAME_TO_ID = {
460
+ "ethereum": 1,
461
+ "eth": 1,
462
+ "goerli": 5,
463
+ "sepolia": 11155111,
464
+ "polygon": 137,
465
+ "matic": 137,
466
+ "mumbai": 80001,
467
+ "base": 8453,
468
+ "base-goerli": 84531,
469
+ "base-sepolia": 84532,
470
+ "solana": 999999,
471
+ // Solana mainnet (custom ID for database compatibility)
472
+ "sol": 999999
473
+ };
474
+ var STABLECOIN_ADDRESSES = {
475
+ ethereum: {
476
+ USDT: "0xdac17f958d2ee523a2206206994597c13d831ec7",
477
+ USDC: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
478
+ DAI: "0x6b175474e89094c44da98b954eedeac495271d0f"
479
+ },
480
+ base: {
481
+ USDC: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
482
+ USDbC: "0xd9aaec86b65d86f6a7b5b1b0c42ffa531710b6ca"
483
+ // Bridged USDC
484
+ },
485
+ polygon: {
486
+ USDT: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
487
+ USDC: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
488
+ DAI: "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063"
489
+ },
490
+ solana: {
491
+ USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
492
+ // USDC SPL token
493
+ USDT: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
494
+ // USDT SPL token
495
+ SOL: "So11111111111111111111111111111111111111112"
496
+ // Wrapped SOL
497
+ }
498
+ };
499
+
500
+ // src/modules/transactions.ts
501
+ var TransactionsModule = class {
502
+ constructor(client, environment = "sandbox") {
503
+ this.client = client;
504
+ this.depositAddresses = getDepositAddresses(environment);
505
+ }
506
+ /**
507
+ * Map chain name to chain ID
508
+ * @private
509
+ */
510
+ getChainId(chain) {
511
+ const chainId = CHAIN_NAME_TO_ID[chain.toLowerCase()];
512
+ return chainId ? chainId.toString() : chain;
513
+ }
514
+ /**
515
+ * Get deposit address for a given chain
516
+ * @private
517
+ */
518
+ getDepositAddress(chain) {
519
+ const normalizedChain = chain.toLowerCase();
520
+ const chainName = normalizedChain === "eth" ? "ethereum" : normalizedChain === "matic" ? "polygon" : normalizedChain;
521
+ const address = this.depositAddresses[chainName];
522
+ if (!address || address === "0x..." || address.includes("TODO")) {
523
+ throw new Error(`Deposit address not configured for chain: ${chain}. Please contact support.`);
524
+ }
525
+ return address;
526
+ }
527
+ /**
528
+ * Get all configured deposit addresses
529
+ * @returns Object mapping chain names to deposit addresses
530
+ */
531
+ getDepositAddresses() {
532
+ return { ...this.depositAddresses };
533
+ }
534
+ /**
535
+ * Get deposit address for a specific chain
536
+ * @param chain - Chain name (e.g., 'ethereum', 'base', 'polygon')
537
+ * @returns The deposit address for the specified chain
538
+ * @throws Error if chain is not supported
539
+ */
540
+ getDepositAddressForChain(chain) {
541
+ return this.getDepositAddress(chain);
542
+ }
543
+ /**
544
+ * Create an onramp transaction (fiat to crypto)
545
+ *
546
+ * @example
547
+ * ```typescript
548
+ * const transaction = await diviswap.transactions.onramp({
549
+ * amount: 100,
550
+ * currency: 'USD',
551
+ * payeeId: 'payee-id',
552
+ * toAddress: '0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651',
553
+ * chain: 'ethereum'
554
+ * });
555
+ * ```
556
+ *
557
+ * @throws {Error} If user is not KYC approved
558
+ */
559
+ async onramp(_data) {
560
+ throw new Error("Onramp endpoint not available in v1 API yet");
561
+ }
562
+ /**
563
+ * Create an offramp transaction (crypto to fiat)
564
+ *
565
+ * ⚠️ IMPORTANT: Follow the production pattern:
566
+ * 1. Send crypto transaction on blockchain FIRST
567
+ * 2. Get the transaction hash
568
+ * 3. Call this method with the hash
569
+ *
570
+ * @example
571
+ * ```typescript
572
+ * import { extractTransactionHash } from '@diviswap/sdk';
573
+ *
574
+ * // 1. Send crypto transaction first and get tx hash
575
+ * const txResult = await sendTransactionAsync({
576
+ * to: depositAddress,
577
+ * value: parseEther('0.5')
578
+ * });
579
+ *
580
+ * // 2. Extract hash (handles different wallet return types)
581
+ * const txHash = extractTransactionHash(txResult);
582
+ *
583
+ * // 3. Record the transaction
584
+ * const transaction = await diviswap.transactions.offramp({
585
+ * amount: 0.5,
586
+ * currency: 'ETH',
587
+ * fromAddress: '0xa3da8ffC1D131F917f9D0Ac078D82914e75d9651',
588
+ * payeeId: 'payee-id',
589
+ * chain: 'ethereum',
590
+ * txHash: txHash
591
+ * });
592
+ * ```
593
+ *
594
+ * @throws {Error} If user is not KYC approved
595
+ */
596
+ async offramp(data) {
597
+ if (!data.txHash || data.txHash.trim() === "") {
598
+ throw new Error(
599
+ "txHash is required for offramp transactions."
600
+ );
601
+ }
602
+ const payload = {
603
+ payee_id: data.payeeId,
604
+ tx_hash: data.txHash,
605
+ // Required: must send crypto first
606
+ from_address: data.fromAddress,
607
+ to_address: data.toAddress || this.getDepositAddress(data.chain || "ethereum"),
608
+ amount: data.amount,
609
+ currency: data.currency,
610
+ chain_id: this.getChainId(data.chain || "ethereum")
611
+ };
612
+ if (data.memo) {
613
+ payload.memo = data.memo;
614
+ }
615
+ return this.client.post(
616
+ `/api/v1/transactions/offramp`,
617
+ payload,
618
+ { useApiKey: false }
619
+ );
620
+ }
621
+ /**
622
+ * Create a test offramp transaction using the same production flow.
623
+ * Requires a transaction hash - send crypto first, then call this method.
624
+ *
625
+ * ⚠️ IMPORTANT: Follow the production pattern:
626
+ * 1. Send crypto transaction on blockchain FIRST
627
+ * 2. Get the transaction hash
628
+ * 3. Call this method with the hash
629
+ *
630
+ * @example
631
+ * ```typescript
632
+ * // 1. Send crypto transaction first and get tx hash
633
+ * const txHash = await sendCryptoTransaction({...});
634
+ *
635
+ * // 2. Record the transaction using production endpoint
636
+ * const transaction = await diviswap.transactions.offrampTest({
637
+ * amount: 0.1,
638
+ * currency: 'USDC',
639
+ * fromAddress: '0x...',
640
+ * toAddress: '0x...',
641
+ * payeeId: 'payee-id',
642
+ * chain: 'base',
643
+ * txHash: txHash
644
+ * });
645
+ * ```
646
+ */
647
+ async offrampTest(data) {
648
+ if (!data.txHash || data.txHash.trim() === "") {
649
+ throw new Error(
650
+ "txHash is required for offramp transactions."
651
+ );
652
+ }
653
+ const payload = {
654
+ payee_id: data.payeeId,
655
+ tx_hash: data.txHash,
656
+ from_address: data.fromAddress,
657
+ to_address: data.toAddress || this.getDepositAddress(data.chain || "ethereum"),
658
+ amount: data.amount,
659
+ currency: data.currency,
660
+ chain_id: this.getChainId(data.chain || "ethereum")
661
+ };
662
+ if (data.memo) {
663
+ payload.memo = data.memo;
664
+ }
665
+ return this.client.post(
666
+ `/api/v1/transactions/offramp`,
667
+ payload,
668
+ { useApiKey: false }
669
+ );
670
+ }
671
+ /**
672
+ * List transactions with optional filters
673
+ *
674
+ * @example
675
+ * ```typescript
676
+ * // Get all transactions
677
+ * const allTransactions = await diviswap.transactions.list();
678
+ *
679
+ * // Get only completed onramp transactions
680
+ * const completedOnramps = await diviswap.transactions.list({
681
+ * type: 'onramp',
682
+ * status: 'completed'
683
+ * });
684
+ * ```
685
+ */
686
+ async list(filters) {
687
+ const params = new URLSearchParams();
688
+ if (filters) {
689
+ Object.entries(filters).forEach(([key, value]) => {
690
+ if (value !== void 0 && value !== null) {
691
+ params.append(key, value.toString());
692
+ }
693
+ });
694
+ }
695
+ const queryString = params.toString();
696
+ const path = `/api/v1/users/transactions${queryString ? `?${queryString}` : ""}`;
697
+ const response = await this.client.get(path, { useApiKey: false });
698
+ if (Array.isArray(response)) {
699
+ return response;
700
+ }
701
+ if (response && typeof response === "object") {
702
+ if (response.data && Array.isArray(response.data)) {
703
+ return response.data;
704
+ }
705
+ if (response.transactions && Array.isArray(response.transactions)) {
706
+ return response.transactions;
707
+ }
708
+ if (response.results && Array.isArray(response.results)) {
709
+ return response.results;
710
+ }
711
+ }
712
+ return [];
713
+ }
714
+ /**
715
+ * Get a specific transaction by ID
716
+ *
717
+ * @example
718
+ * ```typescript
719
+ * const transaction = await diviswap.transactions.get('transaction-id');
720
+ * console.log(transaction.status, transaction.amount);
721
+ * ```
722
+ */
723
+ async get(transactionId) {
724
+ const transactions = await this.list();
725
+ const transaction = transactions.find((t) => t.id === transactionId);
726
+ if (!transaction) {
727
+ throw new Error(`Transaction ${transactionId} not found`);
728
+ }
729
+ return transaction;
730
+ }
731
+ /**
732
+ * Get fee estimate for a transaction
733
+ *
734
+ * @example
735
+ * ```typescript
736
+ * const estimate = await diviswap.transactions.estimateFees({
737
+ * amount: 100,
738
+ * currency: 'USD',
739
+ * type: 'onramp'
740
+ * });
741
+ * console.log(`Fee: $${estimate.fee}, Total: $${estimate.total}`);
742
+ * ```
743
+ */
744
+ async estimateFees(params) {
745
+ return this.client.post("/api/v1/fees", params);
746
+ }
747
+ /**
748
+ * Get recent transactions (convenience method)
749
+ *
750
+ * @example
751
+ * ```typescript
752
+ * const recentTransactions = await diviswap.transactions.getRecent(10);
753
+ * ```
754
+ */
755
+ async getRecent(limit = 10) {
756
+ return this.list({ limit });
757
+ }
758
+ /**
759
+ * Get transaction statistics
760
+ *
761
+ * @example
762
+ * ```typescript
763
+ * const stats = await diviswap.transactions.getStats();
764
+ * console.log(`Total volume: $${stats.totalVolume}`);
765
+ * ```
766
+ */
767
+ async getStats() {
768
+ const transactions = await this.list();
769
+ const stats = transactions.reduce((acc, tx) => {
770
+ acc.totalTransactions++;
771
+ acc.totalVolume += tx.amount || 0;
772
+ if (tx.status === "pending" || tx.status === "processing") {
773
+ acc.pendingTransactions++;
774
+ } else if (tx.status === "completed") {
775
+ acc.completedTransactions++;
776
+ }
777
+ return acc;
778
+ }, {
779
+ totalTransactions: 0,
780
+ totalVolume: 0,
781
+ pendingTransactions: 0,
782
+ completedTransactions: 0
783
+ });
784
+ return stats;
785
+ }
786
+ /**
787
+ * Get stablecoin addresses for a specific chain
788
+ * @param chain - Chain name (e.g., 'ethereum', 'base', 'polygon')
789
+ * @returns Object mapping stablecoin symbols to contract addresses
790
+ */
791
+ getStablecoinAddresses(chain) {
792
+ const normalizedChain = chain.toLowerCase();
793
+ const chainName = normalizedChain === "eth" ? "ethereum" : normalizedChain === "matic" ? "polygon" : normalizedChain;
794
+ return STABLECOIN_ADDRESSES[chainName] || {};
795
+ }
796
+ };
797
+
798
+ // src/modules/kyc.ts
799
+ var KycModule = class {
800
+ constructor(client) {
801
+ this.client = client;
802
+ }
803
+ /**
804
+ * Get current compliance status including KYC and KYB
805
+ *
806
+ * @example
807
+ * ```typescript
808
+ * const status = await diviswap.kyc.getComplianceStatus();
809
+ *
810
+ * if (!status.canTransact) {
811
+ * if (status.nextStep === 'COMPLETE_KYC') {
812
+ * // Redirect to KYC flow
813
+ * }
814
+ * }
815
+ * ```
816
+ */
817
+ async getComplianceStatus() {
818
+ try {
819
+ const profile = await this.client.get("/api/v1/users/profile");
820
+ const kycData = profile.kyc;
821
+ const kycStatus = kycData?.status || (profile.is_verified ? "APPROVED" : "PENDING");
822
+ const canTransact = kycData?.onramp_verified || profile.onramp_verified || false;
823
+ const isVerified = kycData?.is_verified || profile.is_verified || false;
824
+ return {
825
+ kycStatus: kycStatus.toUpperCase(),
826
+ kybStatus: "NOT_REQUIRED",
827
+ canTransact,
828
+ requiresAction: !canTransact,
829
+ verificationLevel: canTransact ? "full" : isVerified ? "basic" : "none",
830
+ nextStep: !canTransact ? "COMPLETE_KYC" : void 0,
831
+ kycMetadata: kycData?.metadata
832
+ };
833
+ } catch (error) {
834
+ throw new Error(`Failed to get compliance status: ${error.message}`);
835
+ }
836
+ }
837
+ /**
838
+ * Start KYC verification session (opens Sumsub widget)
839
+ *
840
+ * @example
841
+ * ```typescript
842
+ * const session = await diviswap.kyc.startKycSession();
843
+ *
844
+ * // Redirect user to session URL
845
+ * window.location.href = session.sessionUrl;
846
+ *
847
+ * // Or embed in iframe
848
+ * const iframe = document.createElement('iframe');
849
+ * iframe.src = session.sessionUrl;
850
+ * ```
851
+ */
852
+ async startKycSession() {
853
+ throw new Error("KYC session endpoint not available in v1 API yet");
854
+ }
855
+ /**
856
+ * Submit KYC documents programmatically
857
+ *
858
+ * @example
859
+ * ```typescript
860
+ * // Convert file to base64
861
+ * const toBase64 = (file: File) => new Promise<string>((resolve, reject) => {
862
+ * const reader = new FileReader();
863
+ * reader.readAsDataURL(file);
864
+ * reader.onload = () => resolve(reader.result as string);
865
+ * reader.onerror = reject;
866
+ * });
867
+ *
868
+ * const frontImage = await toBase64(frontFile);
869
+ * const backImage = await toBase64(backFile);
870
+ *
871
+ * await diviswap.kyc.submitDocuments({
872
+ * type: 'DRIVERS_LICENSE',
873
+ * frontImage,
874
+ * backImage
875
+ * });
876
+ * ```
877
+ */
878
+ async submitDocuments(documents) {
879
+ if (!documents.frontImage) {
880
+ throw new ValidationError("Front image is required");
881
+ }
882
+ if (["DRIVERS_LICENSE", "ID_CARD"].includes(documents.type) && !documents.backImage) {
883
+ throw new ValidationError(`Back image is required for ${documents.type}`);
884
+ }
885
+ throw new Error("KYC documents endpoint not available in v1 API yet");
886
+ }
887
+ /**
888
+ * Submit personal information for KYC
889
+ *
890
+ * @example
891
+ * ```typescript
892
+ * await diviswap.kyc.submitPersonalInfo({
893
+ * firstName: 'John',
894
+ * lastName: 'Doe',
895
+ * dateOfBirth: '1990-01-01',
896
+ * ssn: '123-45-6789',
897
+ * address: {
898
+ * street: '123 Main St',
899
+ * city: 'New York',
900
+ * state: 'NY',
901
+ * postalCode: '10001',
902
+ * country: 'US'
903
+ * }
904
+ * });
905
+ * ```
906
+ */
907
+ async submitPersonalInfo(info) {
908
+ const requiredFields = ["firstName", "lastName", "dateOfBirth"];
909
+ for (const field of requiredFields) {
910
+ if (!info[field]) {
911
+ throw new ValidationError(`${field} is required`);
912
+ }
913
+ }
914
+ if (!info.address || !info.address.street || !info.address.city || !info.address.state || !info.address.postalCode || !info.address.country) {
915
+ throw new ValidationError("Complete address is required");
916
+ }
917
+ try {
918
+ const response = await this.client.post("/api/v1/kyc/personal-info", {
919
+ first_name: info.firstName,
920
+ last_name: info.lastName,
921
+ dob: info.dateOfBirth,
922
+ country: info.address.country,
923
+ ...info.phone && { phone: info.phone },
924
+ ...info.address.street && { address: info.address.street },
925
+ ...info.address.city && { city: info.address.city },
926
+ ...info.address.state && { state: info.address.state },
927
+ ...info.address.postalCode && { postal_code: info.address.postalCode },
928
+ ...info.ssn && { ssn: info.ssn }
929
+ });
930
+ return response;
931
+ } catch (error) {
932
+ throw new Error(`Failed to submit KYC info: ${error.message}`);
933
+ }
934
+ }
935
+ /**
936
+ * Check if user can transact (convenience method)
937
+ *
938
+ * @example
939
+ * ```typescript
940
+ * const canTransact = await diviswap.kyc.canTransact();
941
+ * if (!canTransact) {
942
+ * // Show KYC prompt
943
+ * }
944
+ * ```
945
+ */
946
+ async canTransact() {
947
+ const status = await this.getComplianceStatus();
948
+ return status.canTransact;
949
+ }
950
+ /**
951
+ * Check if KYC is approved
952
+ *
953
+ * @example
954
+ * ```typescript
955
+ * const isApproved = await diviswap.kyc.isKycApproved();
956
+ * ```
957
+ */
958
+ async isKycApproved() {
959
+ const status = await this.getComplianceStatus();
960
+ return status.kycStatus === "APPROVED";
961
+ }
962
+ /**
963
+ * Check if KYB is approved (for business accounts)
964
+ *
965
+ * @example
966
+ * ```typescript
967
+ * const isBusinessApproved = await diviswap.kyc.isKybApproved();
968
+ * ```
969
+ */
970
+ async isKybApproved() {
971
+ const status = await this.getComplianceStatus();
972
+ return status.kybStatus === "APPROVED";
973
+ }
974
+ /**
975
+ * Get rejection reasons if KYC/KYB was rejected
976
+ *
977
+ * @example
978
+ * ```typescript
979
+ * const reasons = await diviswap.kyc.getRejectionReasons();
980
+ * if (reasons.length > 0) {
981
+ * console.log('Rejected because:', reasons.join(', '));
982
+ * }
983
+ * ```
984
+ */
985
+ async getRejectionReasons() {
986
+ const status = await this.getComplianceStatus();
987
+ const reasons = [];
988
+ if (status.kycStatus === "REJECTED" && status.kycMetadata?.rejectLabels) {
989
+ reasons.push(...status.kycMetadata.rejectLabels);
990
+ }
991
+ return reasons;
992
+ }
993
+ /**
994
+ * Wait for KYC approval (polling)
995
+ *
996
+ * @example
997
+ * ```typescript
998
+ * // Start KYC session
999
+ * const session = await diviswap.kyc.startKycSession();
1000
+ * window.open(session.sessionUrl);
1001
+ *
1002
+ * // Wait for approval (polls every 5 seconds for up to 10 minutes)
1003
+ * try {
1004
+ * await diviswap.kyc.waitForApproval();
1005
+ * console.log('KYC approved!');
1006
+ * } catch (error) {
1007
+ * console.log('KYC not approved:', error.message);
1008
+ * }
1009
+ * ```
1010
+ */
1011
+ async waitForApproval(options) {
1012
+ const pollInterval = options?.pollInterval || 5e3;
1013
+ const maxAttempts = options?.maxAttempts || 120;
1014
+ let attempts = 0;
1015
+ while (attempts < maxAttempts) {
1016
+ const status = await this.getComplianceStatus();
1017
+ if (status.kycStatus === "APPROVED") {
1018
+ return status;
1019
+ }
1020
+ if (status.kycStatus === "REJECTED") {
1021
+ throw new Error(`KYC rejected: ${status.kycMetadata?.rejectLabels?.join(", ") || "Unknown reason"}`);
1022
+ }
1023
+ attempts++;
1024
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
1025
+ }
1026
+ throw new Error("KYC approval timeout");
1027
+ }
1028
+ };
1029
+
1030
+ // src/modules/fees.ts
1031
+ var FeesModule = class {
1032
+ constructor(client) {
1033
+ this.client = client;
1034
+ }
1035
+ /**
1036
+ * Set integrator fee percentage
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * // Set global integrator fee to 0.75% (applies to all your users)
1041
+ * await diviswap.fees.setFee({ percentage: 0.75 });
1042
+ *
1043
+ * // Set fee for specific user (overrides global)
1044
+ * await diviswap.fees.setFee({
1045
+ * percentage: 1.0,
1046
+ * userId: 123
1047
+ * });
1048
+ * ```
1049
+ */
1050
+ async setFee(data) {
1051
+ if (data.userId) {
1052
+ await this.client.put(`/api/v1/partner/users/${data.userId}/fee`, {
1053
+ percentage: data.percentage
1054
+ });
1055
+ return {
1056
+ integratorFeePercentage: data.percentage,
1057
+ baseFeePercentage: 1.5,
1058
+ totalFeePercentage: 1.5 + data.percentage,
1059
+ userId: data.userId.toString()
1060
+ };
1061
+ }
1062
+ const response = await this.client.put("/api/v1/partner/fee", {
1063
+ percentage: data.percentage
1064
+ });
1065
+ return {
1066
+ integratorFeePercentage: response.integrator_fee_percentage,
1067
+ baseFeePercentage: response.base_fee_percentage,
1068
+ totalFeePercentage: response.total_fee_percentage
1069
+ };
1070
+ }
1071
+ /**
1072
+ * Get current fee settings
1073
+ *
1074
+ * @example
1075
+ * ```typescript
1076
+ * // Get global fee settings (your default)
1077
+ * const fees = await diviswap.fees.getFees();
1078
+ * console.log(`Total fee: ${fees.totalFeePercentage}%`);
1079
+ * ```
1080
+ */
1081
+ async getFees() {
1082
+ const response = await this.client.get("/api/v1/partner/fee");
1083
+ return {
1084
+ integratorFeePercentage: response.integrator_fee_percentage,
1085
+ baseFeePercentage: response.base_fee_percentage,
1086
+ totalFeePercentage: response.total_fee_percentage
1087
+ };
1088
+ }
1089
+ /**
1090
+ * Calculate fees for a transaction amount
1091
+ *
1092
+ * @example
1093
+ * ```typescript
1094
+ * const calc = await diviswap.fees.calculateFees({
1095
+ * amount: 100,
1096
+ * userId: 123 // Optional: checks for user-specific override
1097
+ * });
1098
+ *
1099
+ * console.log(`Base fee: $${calc.baseFee}`);
1100
+ * console.log(`Your fee: $${calc.integratorFee}`);
1101
+ * console.log(`Total fee: $${calc.totalFee}`);
1102
+ * console.log(`User receives: $${calc.netAmount}`);
1103
+ * ```
1104
+ */
1105
+ async calculateFees(params) {
1106
+ const response = await this.client.post("/api/v1/partner/fees/calculate", {
1107
+ amount: params.amount,
1108
+ user_id: params.userId
1109
+ });
1110
+ return {
1111
+ amount: response.amount,
1112
+ baseFee: response.base_fee,
1113
+ integratorFee: response.integrator_fee,
1114
+ totalFee: response.total_fee,
1115
+ netAmount: response.net_amount
1116
+ };
1117
+ }
1118
+ /**
1119
+ * Remove custom fee for a user (reverts to partner default)
1120
+ *
1121
+ * @example
1122
+ * ```typescript
1123
+ * // Remove VIP user's custom fee, they'll use your default fee again
1124
+ * await diviswap.fees.removeFee(123);
1125
+ * ```
1126
+ */
1127
+ async removeFee(userId) {
1128
+ await this.client.delete(`/api/v1/partner/users/${userId}/fee`);
1129
+ }
1130
+ };
1131
+
1132
+ // src/types/addresses.ts
1133
+ var CHAIN_IDS = {
1134
+ // Mainnets
1135
+ ethereum: 1,
1136
+ optimism: 10,
1137
+ base: 8453,
1138
+ polygon: 137,
1139
+ arbitrum: 42161,
1140
+ // Testnets
1141
+ sepolia: 11155111,
1142
+ optimism_sepolia: 11155420,
1143
+ base_sepolia: 84532,
1144
+ polygon_mumbai: 80001,
1145
+ arbitrum_sepolia: 421614
1146
+ };
1147
+
1148
+ // src/modules/addresses.ts
1149
+ var AddressesModule = class {
1150
+ constructor(client) {
1151
+ this.client = client;
1152
+ }
1153
+ /**
1154
+ * Get all addresses for the authenticated user
1155
+ *
1156
+ * @example
1157
+ * ```typescript
1158
+ * const addresses = await diviswap.addresses.list();
1159
+ * console.log('User addresses:', addresses);
1160
+ * ```
1161
+ */
1162
+ async list() {
1163
+ const response = await this.client.get("/api/v1/addresses");
1164
+ return Array.isArray(response) ? response : [];
1165
+ }
1166
+ /**
1167
+ * Create a new crypto address for the user
1168
+ *
1169
+ * @example
1170
+ * ```typescript
1171
+ * const address = await diviswap.addresses.create({
1172
+ * chain_id: 1, // Ethereum mainnet
1173
+ * address: '0x742d35Cc6647C9532c9fc77C68076aFb1e5AAc05',
1174
+ * is_default: true
1175
+ * });
1176
+ * ```
1177
+ */
1178
+ async create(data) {
1179
+ const response = await this.client.post("/api/v1/addresses", data);
1180
+ const addresses = await this.list();
1181
+ const newAddress = addresses.find((addr) => addr.id === response.id);
1182
+ if (!newAddress) {
1183
+ throw new Error("Failed to retrieve created address");
1184
+ }
1185
+ return newAddress;
1186
+ }
1187
+ /**
1188
+ * Set a specific address as the default for its chain
1189
+ *
1190
+ * @example
1191
+ * ```typescript
1192
+ * await diviswap.addresses.setDefault({
1193
+ * chain_id: 1,
1194
+ * address: '0x742d35Cc6647C9532c9fc77C68076aFb1e5AAc05'
1195
+ * });
1196
+ * ```
1197
+ */
1198
+ async setDefault(data) {
1199
+ await this.client.put("/api/v1/addresses/default", data);
1200
+ }
1201
+ /**
1202
+ * Delete a crypto address
1203
+ *
1204
+ * @example
1205
+ * ```typescript
1206
+ * await diviswap.addresses.delete({
1207
+ * chain_id: 1,
1208
+ * address: '0x742d35Cc6647C9532c9fc77C68076aFb1e5AAc05'
1209
+ * });
1210
+ * ```
1211
+ */
1212
+ async delete(data) {
1213
+ await this.client.delete("/api/v1/addresses", { body: data });
1214
+ }
1215
+ /**
1216
+ * Get addresses for a specific chain
1217
+ *
1218
+ * @example
1219
+ * ```typescript
1220
+ * const ethAddresses = await diviswap.addresses.getByChain(1);
1221
+ * const baseAddresses = await diviswap.addresses.getByChain('base');
1222
+ * ```
1223
+ */
1224
+ async getByChain(chainIdOrName) {
1225
+ const chainId = typeof chainIdOrName === "string" ? CHAIN_IDS[chainIdOrName] : chainIdOrName;
1226
+ const addresses = await this.list();
1227
+ return addresses.filter((addr) => addr.chain_id === chainId);
1228
+ }
1229
+ /**
1230
+ * Get the default address for a specific chain
1231
+ *
1232
+ * @example
1233
+ * ```typescript
1234
+ * const defaultEthAddress = await diviswap.addresses.getDefault(1);
1235
+ * const defaultBaseAddress = await diviswap.addresses.getDefault('base');
1236
+ * ```
1237
+ */
1238
+ async getDefault(chainIdOrName) {
1239
+ const chainId = typeof chainIdOrName === "string" ? CHAIN_IDS[chainIdOrName] : chainIdOrName;
1240
+ const addresses = await this.list();
1241
+ return addresses.find((addr) => addr.chain_id === chainId && addr.is_default) || null;
1242
+ }
1243
+ /**
1244
+ * Check if an address exists for the user
1245
+ *
1246
+ * @example
1247
+ * ```typescript
1248
+ * const exists = await diviswap.addresses.exists({
1249
+ * chain_id: 1,
1250
+ * address: '0x742d35Cc6647C9532c9fc77C68076aFb1e5AAc05'
1251
+ * });
1252
+ * ```
1253
+ */
1254
+ async exists(data) {
1255
+ const addresses = await this.list();
1256
+ return addresses.some(
1257
+ (addr) => addr.chain_id === data.chain_id && addr.address.toLowerCase() === data.address.toLowerCase()
1258
+ );
1259
+ }
1260
+ /**
1261
+ * Automatically track a wallet connection
1262
+ * This is the main method for automatic address tracking
1263
+ *
1264
+ * @example
1265
+ * ```typescript
1266
+ * // When user connects wallet
1267
+ * const connection = await diviswap.addresses.trackWallet({
1268
+ * address: account,
1269
+ * chainId: chainId,
1270
+ * chainName: 'ethereum' // optional
1271
+ * });
1272
+ * ```
1273
+ */
1274
+ async trackWallet(connection) {
1275
+ const existsAlready = await this.exists({
1276
+ chain_id: connection.chainId,
1277
+ address: connection.address
1278
+ });
1279
+ if (existsAlready) {
1280
+ const addresses = await this.list();
1281
+ const existingAddress = addresses.find(
1282
+ (addr) => addr.chain_id === connection.chainId && addr.address.toLowerCase() === connection.address.toLowerCase()
1283
+ );
1284
+ if (!existingAddress) {
1285
+ throw new Error("Address exists but could not be retrieved");
1286
+ }
1287
+ return existingAddress;
1288
+ }
1289
+ const existingOnChain = await this.getByChain(connection.chainId);
1290
+ const isDefault = existingOnChain.length === 0;
1291
+ return await this.create({
1292
+ chain_id: connection.chainId,
1293
+ address: connection.address,
1294
+ is_default: isDefault
1295
+ });
1296
+ }
1297
+ /**
1298
+ * Auto-track multiple wallet connections (useful for multi-chain wallets)
1299
+ *
1300
+ * @example
1301
+ * ```typescript
1302
+ * // When user connects a multi-chain wallet
1303
+ * const addresses = await diviswap.addresses.trackMultipleWallets([
1304
+ * { address: account, chainId: 1 }, // Ethereum
1305
+ * { address: account, chainId: 8453 }, // Base
1306
+ * { address: account, chainId: 10 } // Optimism
1307
+ * ]);
1308
+ * ```
1309
+ */
1310
+ async trackMultipleWallets(connections) {
1311
+ const results = [];
1312
+ for (const connection of connections) {
1313
+ try {
1314
+ const address = await this.trackWallet(connection);
1315
+ results.push(address);
1316
+ } catch (error) {
1317
+ console.error(`Failed to track wallet for chain ${connection.chainId}:`, error);
1318
+ }
1319
+ }
1320
+ return results;
1321
+ }
1322
+ /**
1323
+ * Helper to get chain name from chain ID
1324
+ */
1325
+ getChainName(chainId) {
1326
+ return Object.entries(CHAIN_IDS).find(([_, id]) => id === chainId)?.[0];
1327
+ }
1328
+ /**
1329
+ * Helper to get chain ID from chain name
1330
+ */
1331
+ getChainId(chainName) {
1332
+ return CHAIN_IDS[chainName];
1333
+ }
1334
+ /**
1335
+ * Get all supported chains
1336
+ */
1337
+ getSupportedChains() {
1338
+ return { ...CHAIN_IDS };
1339
+ }
1340
+ };
1341
+
1342
+ // src/modules/webhooks.ts
1343
+ var WebhooksModule = class {
1344
+ constructor(client) {
1345
+ this.client = client;
1346
+ }
1347
+ /**
1348
+ * Set webhook URL and secret for your partner account
1349
+ *
1350
+ * @example
1351
+ * ```typescript
1352
+ * await diviswap.webhooks.setConfig({
1353
+ * webhook_url: 'https://myapp.com/api/webhooks/diviswap',
1354
+ * webhook_secret: 'whsec_...' // Optional, auto-generated if not provided
1355
+ * });
1356
+ * ```
1357
+ */
1358
+ async setConfig(data) {
1359
+ const response = await this.client.put("/api/v1/partner/webhook", {
1360
+ webhook_url: data.webhook_url,
1361
+ webhook_secret: data.webhook_secret
1362
+ });
1363
+ return response;
1364
+ }
1365
+ /**
1366
+ * Set webhook for a specific partner (user-owned partner)
1367
+ *
1368
+ * @example
1369
+ * ```typescript
1370
+ * await diviswap.webhooks.setConfigForPartner(4, {
1371
+ * webhook_url: 'https://myapp.com/webhooks'
1372
+ * });
1373
+ * ```
1374
+ */
1375
+ async setConfigForPartner(partnerId, data) {
1376
+ const response = await this.client.put(`/api/v1/partners/${partnerId}/webhook`, {
1377
+ webhook_url: data.webhook_url,
1378
+ webhook_secret: data.webhook_secret
1379
+ });
1380
+ return response;
1381
+ }
1382
+ /**
1383
+ * Get current webhook configuration
1384
+ *
1385
+ * @example
1386
+ * ```typescript
1387
+ * const config = await diviswap.webhooks.getConfig();
1388
+ * console.log(`Webhook enabled: ${config.enabled}`);
1389
+ * console.log(`URL: ${config.webhook_url}`);
1390
+ * ```
1391
+ */
1392
+ async getConfig() {
1393
+ const response = await this.client.get("/api/v1/partner/webhook");
1394
+ return response;
1395
+ }
1396
+ /**
1397
+ * Get webhook config for a specific partner (user-owned)
1398
+ */
1399
+ async getConfigForPartner(partnerId) {
1400
+ const response = await this.client.get(`/api/v1/partners/${partnerId}/webhook`);
1401
+ return response;
1402
+ }
1403
+ /**
1404
+ * List webhook delivery events
1405
+ *
1406
+ * @example
1407
+ * ```typescript
1408
+ * const events = await diviswap.webhooks.listEvents({
1409
+ * limit: 100,
1410
+ * status: 'failed'
1411
+ * });
1412
+ *
1413
+ * events.forEach(event => {
1414
+ * console.log(`${event.event_type}: ${event.status}`);
1415
+ * });
1416
+ * ```
1417
+ */
1418
+ async listEvents(options) {
1419
+ const params = new URLSearchParams();
1420
+ if (options?.limit) params.append("limit", options.limit.toString());
1421
+ if (options?.status) params.append("status", options.status);
1422
+ const path = options?.partnerId ? `/api/v1/partners/${options.partnerId}/webhook/events?${params}` : `/api/v1/partner/webhook/events?${params}`;
1423
+ const response = await this.client.get(path);
1424
+ return response;
1425
+ }
1426
+ /**
1427
+ * Send a test webhook to verify your endpoint is working
1428
+ *
1429
+ * @example
1430
+ * ```typescript
1431
+ * const result = await diviswap.webhooks.test();
1432
+ * if (result.success) {
1433
+ * console.log('Webhook endpoint is working!');
1434
+ * }
1435
+ * ```
1436
+ */
1437
+ async test(partnerId) {
1438
+ const path = partnerId ? `/api/v1/partners/${partnerId}/webhook/test` : "/api/v1/partner/webhook/test";
1439
+ return await this.client.post(path);
1440
+ }
1441
+ /**
1442
+ * Verify a webhook signature (static helper for your webhook endpoint)
1443
+ *
1444
+ * @example
1445
+ * ```typescript
1446
+ * import crypto from 'crypto';
1447
+ *
1448
+ * const isValid = WebhooksModule.verifySignature(
1449
+ * rawBody,
1450
+ * request.headers['x-signature'],
1451
+ * process.env.WEBHOOK_SECRET
1452
+ * );
1453
+ * ```
1454
+ */
1455
+ static verifySignature(payload, signature, secret) {
1456
+ const crypto2 = __require("crypto");
1457
+ const expectedSignature = crypto2.createHmac("sha256", secret).update(payload).digest("hex");
1458
+ return crypto2.timingSafeEqual(
1459
+ Buffer.from(signature),
1460
+ Buffer.from(expectedSignature)
1461
+ );
1462
+ }
1463
+ };
1464
+
1465
+ // src/api/token-manager.ts
1466
+ var MemoryTokenStorage = class {
1467
+ constructor() {
1468
+ this.data = null;
1469
+ }
1470
+ get() {
1471
+ return this.data;
1472
+ }
1473
+ set(data) {
1474
+ this.data = data;
1475
+ }
1476
+ clear() {
1477
+ this.data = null;
1478
+ }
1479
+ };
1480
+ var LocalStorageTokenStorage = class {
1481
+ constructor() {
1482
+ this.key = "liberex_tokens";
1483
+ }
1484
+ get() {
1485
+ if (typeof globalThis.window === "undefined") return null;
1486
+ const data = globalThis.localStorage.getItem(this.key);
1487
+ if (!data) return null;
1488
+ try {
1489
+ return JSON.parse(data);
1490
+ } catch {
1491
+ return null;
1492
+ }
1493
+ }
1494
+ set(data) {
1495
+ if (typeof globalThis.window === "undefined") return;
1496
+ globalThis.localStorage.setItem(this.key, JSON.stringify(data));
1497
+ }
1498
+ clear() {
1499
+ if (typeof globalThis.window === "undefined") return;
1500
+ globalThis.localStorage.removeItem(this.key);
1501
+ }
1502
+ };
1503
+ var TokenManager = class {
1504
+ constructor(useLocalStorage = false) {
1505
+ this.refreshPromise = null;
1506
+ this.storage = useLocalStorage && typeof globalThis.window !== "undefined" ? new LocalStorageTokenStorage() : new MemoryTokenStorage();
1507
+ }
1508
+ /**
1509
+ * Parse JWT token to extract expiration
1510
+ */
1511
+ parseToken(token) {
1512
+ try {
1513
+ const payload = token.split(".")[1];
1514
+ const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
1515
+ return JSON.parse(decoded);
1516
+ } catch {
1517
+ return {};
1518
+ }
1519
+ }
1520
+ /**
1521
+ * Store tokens
1522
+ */
1523
+ setTokens(accessToken, refreshToken) {
1524
+ const parsed = this.parseToken(accessToken);
1525
+ const expiresAt = parsed.exp ? parsed.exp * 1e3 : void 0;
1526
+ this.storage.set({
1527
+ accessToken,
1528
+ refreshToken,
1529
+ expiresAt
1530
+ });
1531
+ }
1532
+ /**
1533
+ * Get current access token
1534
+ */
1535
+ getAccessToken() {
1536
+ const data = this.storage.get();
1537
+ return data?.accessToken || null;
1538
+ }
1539
+ /**
1540
+ * Get refresh token
1541
+ */
1542
+ getRefreshToken() {
1543
+ const data = this.storage.get();
1544
+ return data?.refreshToken || null;
1545
+ }
1546
+ /**
1547
+ * Check if token is expired or about to expire (5 min buffer)
1548
+ */
1549
+ isTokenExpired() {
1550
+ const data = this.storage.get();
1551
+ if (!data?.expiresAt) return true;
1552
+ const bufferTime = 5 * 60 * 1e3;
1553
+ return Date.now() >= data.expiresAt - bufferTime;
1554
+ }
1555
+ /**
1556
+ * Clear all tokens
1557
+ */
1558
+ clearTokens() {
1559
+ this.storage.clear();
1560
+ this.refreshPromise = null;
1561
+ }
1562
+ /**
1563
+ * Refresh access token
1564
+ */
1565
+ async refreshAccessToken(refreshCallback) {
1566
+ if (this.refreshPromise) {
1567
+ const result = await this.refreshPromise;
1568
+ return result.accessToken;
1569
+ }
1570
+ const refreshToken = this.getRefreshToken();
1571
+ if (!refreshToken) {
1572
+ throw new Error("No refresh token available");
1573
+ }
1574
+ this.refreshPromise = refreshCallback(refreshToken);
1575
+ try {
1576
+ const newTokenData = await this.refreshPromise;
1577
+ this.setTokens(newTokenData.accessToken, newTokenData.refreshToken || refreshToken);
1578
+ return newTokenData.accessToken;
1579
+ } finally {
1580
+ this.refreshPromise = null;
1581
+ }
1582
+ }
1583
+ /**
1584
+ * Get valid access token (refresh if needed)
1585
+ */
1586
+ async getValidAccessToken(refreshCallback) {
1587
+ const token = this.getAccessToken();
1588
+ if (!token) return null;
1589
+ if (this.isTokenExpired() && refreshCallback) {
1590
+ try {
1591
+ return await this.refreshAccessToken(refreshCallback);
1592
+ } catch {
1593
+ this.clearTokens();
1594
+ return null;
1595
+ }
1596
+ }
1597
+ return token;
1598
+ }
1599
+ };
1600
+ var PartnerAuth = class {
1601
+ constructor(credentials) {
1602
+ this.credentials = credentials;
1603
+ }
1604
+ /**
1605
+ * Generate HMAC authentication headers for a request
1606
+ */
1607
+ generateHMACHeaders(method, path, queryString = "", body = "") {
1608
+ const timestamp = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
1609
+ const nonce = this.generateNonce();
1610
+ const bodyHash = crypto__default.default.createHash("sha256").update(body).digest("hex");
1611
+ const canonical = [
1612
+ method,
1613
+ path,
1614
+ queryString,
1615
+ bodyHash,
1616
+ timestamp,
1617
+ nonce
1618
+ ].join("\n");
1619
+ const signature = crypto__default.default.createHmac("sha256", this.credentials.secretKey).update(canonical).digest("base64");
1620
+ const headers = {
1621
+ "Authorization": `HMAC ${this.credentials.keyId}:${signature}:${timestamp}:${nonce}`,
1622
+ "X-Client-Id": this.credentials.keyId
1623
+ };
1624
+ if (this.credentials.customerId) {
1625
+ headers["X-Customer-Id"] = this.credentials.customerId;
1626
+ }
1627
+ if (this.credentials.customerEmail) {
1628
+ headers["X-Customer-Email"] = this.credentials.customerEmail;
1629
+ }
1630
+ return headers;
1631
+ }
1632
+ /**
1633
+ * Generate a unique nonce for replay protection
1634
+ */
1635
+ generateNonce() {
1636
+ return crypto__default.default.randomBytes(32).toString("base64url");
1637
+ }
1638
+ /**
1639
+ * Generate a JWT token for partner authentication
1640
+ */
1641
+ generateJWT(options = {}) {
1642
+ const {
1643
+ audience = "api.diviswap.io",
1644
+ expiresIn = 300,
1645
+ // 5 minutes max
1646
+ scopes = []
1647
+ } = options;
1648
+ const now = Math.floor(Date.now() / 1e3);
1649
+ const payload = {
1650
+ iss: this.credentials.keyId,
1651
+ // Issuer: partner key ID
1652
+ aud: audience,
1653
+ // Audience: API domain
1654
+ exp: now + Math.min(expiresIn, 300),
1655
+ // Expiration (max 5 minutes)
1656
+ iat: now,
1657
+ // Issued at
1658
+ ...this.credentials.customerId && { sub: this.credentials.customerId },
1659
+ ...this.credentials.customerEmail && { email: this.credentials.customerEmail },
1660
+ ...scopes.length > 0 && { scope: scopes }
1661
+ };
1662
+ const header = { alg: "HS256", typ: "JWT" };
1663
+ const encodedHeader = Buffer.from(JSON.stringify(header)).toString("base64url");
1664
+ const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url");
1665
+ const signature = crypto__default.default.createHmac("sha256", this.credentials.secretKey).update(`${encodedHeader}.${encodedPayload}`).digest("base64url");
1666
+ return `${encodedHeader}.${encodedPayload}.${signature}`;
1667
+ }
1668
+ /**
1669
+ * Set customer context for shadow user linking
1670
+ */
1671
+ setCustomer(customerId, customerEmail) {
1672
+ this.credentials.customerId = customerId;
1673
+ this.credentials.customerEmail = customerEmail;
1674
+ }
1675
+ /**
1676
+ * Clear customer context
1677
+ */
1678
+ clearCustomer() {
1679
+ delete this.credentials.customerId;
1680
+ delete this.credentials.customerEmail;
1681
+ }
1682
+ };
1683
+
1684
+ // src/api/unified-client.ts
1685
+ var UnifiedApiClient = class _UnifiedApiClient {
1686
+ constructor(config, useLocalStorage = true) {
1687
+ this.config = config;
1688
+ this.tokenManager = new TokenManager(useLocalStorage);
1689
+ if (config.mode === "partner" && config.keyId && config.secretKey) {
1690
+ this.partnerAuth = new PartnerAuth({
1691
+ keyId: config.keyId,
1692
+ secretKey: config.secretKey,
1693
+ customerId: config.customerId,
1694
+ customerEmail: config.customerEmail
1695
+ });
1696
+ }
1697
+ }
1698
+ /**
1699
+ * Create client from legacy user config (backward compatibility)
1700
+ */
1701
+ static fromUserConfig(config, useLocalStorage = true) {
1702
+ const baseUrl = config.apiUrl || this.getDefaultApiUrl(config.environment || "production");
1703
+ return new _UnifiedApiClient({
1704
+ baseUrl,
1705
+ timeout: config.timeout || 3e4,
1706
+ debug: config.debug || false,
1707
+ mode: "user",
1708
+ apiKey: config.apiKey,
1709
+ clientId: config.clientId
1710
+ }, useLocalStorage);
1711
+ }
1712
+ /**
1713
+ * Create client from partner config
1714
+ */
1715
+ static fromPartnerConfig(config, useLocalStorage = true) {
1716
+ const baseUrl = config.apiUrl || this.getDefaultApiUrl(config.environment || "production");
1717
+ return new _UnifiedApiClient({
1718
+ baseUrl,
1719
+ timeout: config.timeout || 3e4,
1720
+ debug: config.debug || false,
1721
+ mode: "partner",
1722
+ keyId: config.keyId,
1723
+ secretKey: config.secretKey,
1724
+ authMethod: config.authMethod || "hmac",
1725
+ customerId: config.customerId,
1726
+ customerEmail: config.customerEmail
1727
+ }, useLocalStorage);
1728
+ }
1729
+ /**
1730
+ * Create client from any config (auto-detect mode)
1731
+ */
1732
+ static fromConfig(config, useLocalStorage = true) {
1733
+ if ("mode" in config && config.mode === "partner" || "keyId" in config && "secretKey" in config) {
1734
+ return this.fromPartnerConfig(config, useLocalStorage);
1735
+ } else {
1736
+ return this.fromUserConfig(config, useLocalStorage);
1737
+ }
1738
+ }
1739
+ static getDefaultApiUrl(environment) {
1740
+ switch (environment) {
1741
+ case "production":
1742
+ return "https://api.diviswap.io";
1743
+ case "sandbox":
1744
+ return "https://dev-api.diviswap.io";
1745
+ default:
1746
+ return "https://dev-api.diviswap.io";
1747
+ }
1748
+ }
1749
+ /**
1750
+ * Update customer context for partner auth
1751
+ */
1752
+ setCustomer(customerId, customerEmail) {
1753
+ if (this.partnerAuth) {
1754
+ this.partnerAuth.setCustomer(customerId, customerEmail);
1755
+ }
1756
+ this.config.customerId = customerId;
1757
+ this.config.customerEmail = customerEmail;
1758
+ }
1759
+ /**
1760
+ * Clear customer context
1761
+ */
1762
+ clearCustomer() {
1763
+ if (this.partnerAuth) {
1764
+ this.partnerAuth.clearCustomer();
1765
+ }
1766
+ delete this.config.customerId;
1767
+ delete this.config.customerEmail;
1768
+ }
1769
+ /**
1770
+ * Get authentication mode
1771
+ */
1772
+ getAuthMode() {
1773
+ return this.config.mode || "user";
1774
+ }
1775
+ /**
1776
+ * Get current customer ID (partner mode only)
1777
+ */
1778
+ getCustomerId() {
1779
+ return this.config.customerId;
1780
+ }
1781
+ /**
1782
+ * Set refresh callback for automatic token refresh (user mode only)
1783
+ */
1784
+ setRefreshCallback(callback) {
1785
+ this.refreshCallback = callback;
1786
+ }
1787
+ /**
1788
+ * Set access token directly (user mode only)
1789
+ */
1790
+ setTokens(accessToken, refreshToken) {
1791
+ this.tokenManager.setTokens(accessToken, refreshToken);
1792
+ }
1793
+ /**
1794
+ * Get current access token (user mode only)
1795
+ */
1796
+ async getAccessToken() {
1797
+ if (this.config.mode === "partner") {
1798
+ return null;
1799
+ }
1800
+ return this.tokenManager.getValidAccessToken(this.refreshCallback);
1801
+ }
1802
+ /**
1803
+ * Clear stored tokens (user mode only)
1804
+ */
1805
+ clearTokens() {
1806
+ this.tokenManager.clearTokens();
1807
+ }
1808
+ /**
1809
+ * Make authenticated API request
1810
+ */
1811
+ async request(options) {
1812
+ const { method, path, body, headers = {}, useApiKey = false, skipAuth = false } = options;
1813
+ const url = `${this.config.baseUrl}${path}`;
1814
+ const requestHeaders = {
1815
+ "Content-Type": "application/json",
1816
+ "User-Agent": "Diviswap-SDK/2.0",
1817
+ ...headers
1818
+ };
1819
+ if (!skipAuth) {
1820
+ if (this.config.mode === "partner") {
1821
+ await this.addPartnerAuth(method, path, body, requestHeaders);
1822
+ } else {
1823
+ await this.addUserAuth(useApiKey, requestHeaders);
1824
+ }
1825
+ }
1826
+ try {
1827
+ const controller = new AbortController();
1828
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
1829
+ const response = await fetch(url, {
1830
+ method,
1831
+ headers: requestHeaders,
1832
+ body: body ? JSON.stringify(body) : void 0,
1833
+ signal: controller.signal
1834
+ });
1835
+ clearTimeout(timeoutId);
1836
+ const responseText = await response.text();
1837
+ let responseData;
1838
+ try {
1839
+ responseData = responseText ? JSON.parse(responseText) : null;
1840
+ } catch {
1841
+ responseData = responseText;
1842
+ }
1843
+ if (!response.ok) {
1844
+ await this.handleErrorResponse(response, responseData);
1845
+ }
1846
+ return responseData;
1847
+ } catch (error) {
1848
+ if (error instanceof Error && error.name === "AbortError") {
1849
+ throw new NetworkError("Request timeout");
1850
+ }
1851
+ if (error instanceof DiviswapError) {
1852
+ throw error;
1853
+ }
1854
+ throw new NetworkError(`Network request failed: ${error}`);
1855
+ }
1856
+ }
1857
+ /**
1858
+ * Add partner authentication headers
1859
+ */
1860
+ async addPartnerAuth(method, path, body, headers) {
1861
+ if (!this.partnerAuth) {
1862
+ throw new AuthenticationError("Partner authentication not configured");
1863
+ }
1864
+ const bodyString = body ? JSON.stringify(body) : "";
1865
+ const urlParts = path.split("?");
1866
+ const pathOnly = urlParts[0];
1867
+ const queryString = urlParts.length > 1 ? urlParts[1] : "";
1868
+ if (this.config.authMethod === "jwt") {
1869
+ const jwt = this.partnerAuth.generateJWT({
1870
+ audience: "api.diviswap.io",
1871
+ expiresIn: 300
1872
+ });
1873
+ headers["Authorization"] = `Bearer ${jwt}`;
1874
+ } else {
1875
+ const hmacHeaders = this.partnerAuth.generateHMACHeaders(
1876
+ method,
1877
+ pathOnly,
1878
+ queryString,
1879
+ bodyString
1880
+ );
1881
+ Object.assign(headers, hmacHeaders);
1882
+ }
1883
+ }
1884
+ /**
1885
+ * Add user authentication headers (legacy)
1886
+ */
1887
+ async addUserAuth(useApiKey, headers) {
1888
+ if (!this.config.apiKey || !this.config.clientId) {
1889
+ throw new AuthenticationError("User authentication not configured");
1890
+ }
1891
+ headers["X-CLIENT-ID"] = this.config.clientId;
1892
+ headers["X-TIMESTAMP"] = Math.floor(Date.now() / 1e3).toString();
1893
+ headers["X-API-Key"] = this.config.apiKey;
1894
+ if (!useApiKey) {
1895
+ const accessToken = await this.tokenManager.getValidAccessToken(this.refreshCallback);
1896
+ if (accessToken) {
1897
+ headers["Authorization"] = `Bearer ${accessToken}`;
1898
+ }
1899
+ }
1900
+ }
1901
+ async handleErrorResponse(response, data) {
1902
+ const status = response.status;
1903
+ const message = data?.error || data?.message || `HTTP ${status}`;
1904
+ if (status === 403 && data?.kyc_uri) {
1905
+ const error = new AuthenticationError(message);
1906
+ error.kycUri = data.kyc_uri;
1907
+ error.requiredLevel = data.required_level;
1908
+ throw error;
1909
+ }
1910
+ switch (status) {
1911
+ case 400:
1912
+ throw new ValidationError(message);
1913
+ case 401:
1914
+ case 403:
1915
+ throw new AuthenticationError(message);
1916
+ case 404:
1917
+ throw new DiviswapError(`Resource not found: ${message}`);
1918
+ case 429:
1919
+ throw new DiviswapError(`Rate limit exceeded: ${message}`);
1920
+ case 500:
1921
+ case 502:
1922
+ case 503:
1923
+ case 504:
1924
+ throw new NetworkError(`Server error: ${message}`);
1925
+ default:
1926
+ throw new DiviswapError(`API error: ${message}`);
1927
+ }
1928
+ }
1929
+ // Convenience methods
1930
+ async get(path, options = {}) {
1931
+ return this.request({ method: "GET", path, ...options });
1932
+ }
1933
+ async post(path, body, options = {}) {
1934
+ return this.request({ method: "POST", path, body, ...options });
1935
+ }
1936
+ async put(path, body, options = {}) {
1937
+ return this.request({ method: "PUT", path, body, ...options });
1938
+ }
1939
+ async delete(path, options = {}) {
1940
+ return this.request({ method: "DELETE", path, ...options });
1941
+ }
1942
+ };
1943
+
1944
+ // src/client.ts
1945
+ var _Diviswap = class _Diviswap {
1946
+ constructor(config) {
1947
+ this.config = config;
1948
+ this.validateConfig(config);
1949
+ const useLocalStorage = config.tokenStorage === "localStorage" || !config.tokenStorage;
1950
+ this.apiClient = UnifiedApiClient.fromConfig(config, useLocalStorage);
1951
+ this.auth = new AuthModule(this.apiClient);
1952
+ this.payees = new PayeesModule(this.apiClient);
1953
+ this.transactions = new TransactionsModule(this.apiClient, config.environment || "sandbox");
1954
+ this.kyc = new KycModule(this.apiClient);
1955
+ this.fees = new FeesModule(this.apiClient);
1956
+ this.addresses = new AddressesModule(this.apiClient);
1957
+ this.webhooks = new WebhooksModule(this.apiClient);
1958
+ }
1959
+ /**
1960
+ * Initialize the Diviswap SDK
1961
+ *
1962
+ * @param config - SDK configuration
1963
+ * @returns Diviswap SDK instance
1964
+ *
1965
+ * @example
1966
+ * ```typescript
1967
+ * const diviswap = Diviswap.init({
1968
+ * apiKey: 'your-api-key',
1969
+ * clientId: 'your-client-id'
1970
+ * });
1971
+ * ```
1972
+ */
1973
+ static init(config) {
1974
+ if (!_Diviswap.instance) {
1975
+ _Diviswap.instance = new _Diviswap(config);
1976
+ }
1977
+ return _Diviswap.instance;
1978
+ }
1979
+ /**
1980
+ * Get the current SDK instance
1981
+ * @throws {ConfigurationError} If SDK hasn't been initialized
1982
+ */
1983
+ static getInstance() {
1984
+ if (!_Diviswap.instance) {
1985
+ throw new ConfigurationError("Diviswap SDK not initialized. Call Diviswap.init() first.");
1986
+ }
1987
+ return _Diviswap.instance;
1988
+ }
1989
+ /**
1990
+ * Reset the SDK instance (useful for testing)
1991
+ */
1992
+ static reset() {
1993
+ _Diviswap.instance = null;
1994
+ }
1995
+ /**
1996
+ * Update SDK configuration
1997
+ * @deprecated Configuration updates require re-initialization. Call Diviswap.reset() then Diviswap.init() with new config.
1998
+ */
1999
+ updateConfig(_config) {
2000
+ throw new ConfigurationError("Configuration updates require re-initialization. Call Diviswap.reset() then Diviswap.init() with new config.");
2001
+ }
2002
+ /**
2003
+ * Get current configuration (excluding sensitive data)
2004
+ */
2005
+ getConfig() {
2006
+ return {
2007
+ environment: this.config.environment,
2008
+ apiUrl: this.config.apiUrl,
2009
+ debug: this.config.debug,
2010
+ timeout: this.config.timeout
2011
+ };
2012
+ }
2013
+ /**
2014
+ * Get current access token (for developers who need it for custom API calls)
2015
+ * Only available in user authentication mode.
2016
+ *
2017
+ * @example
2018
+ * ```typescript
2019
+ * const token = await diviswap.getAccessToken();
2020
+ * if (token) {
2021
+ * // Use token for custom API calls
2022
+ * fetch('https://api.diviswap.io/custom-endpoint', {
2023
+ * headers: { 'Authorization': `Bearer ${token}` }
2024
+ * });
2025
+ * }
2026
+ * ```
2027
+ */
2028
+ async getAccessToken() {
2029
+ return this.apiClient.getAccessToken();
2030
+ }
2031
+ /**
2032
+ * Set access token (for server-side usage where tokens are stored externally)
2033
+ * Only available in user authentication mode.
2034
+ *
2035
+ * @example
2036
+ * ```typescript
2037
+ * // In a Next.js API route where token is stored in cookies
2038
+ * const token = cookies().get('diviswap_session')?.value;
2039
+ * if (token) {
2040
+ * diviswap.setAccessToken(token);
2041
+ * }
2042
+ * ```
2043
+ */
2044
+ setAccessToken(accessToken, refreshToken) {
2045
+ this.apiClient.setTokens(accessToken, refreshToken);
2046
+ }
2047
+ /**
2048
+ * Set customer context for partner authentication mode
2049
+ *
2050
+ * @example
2051
+ * ```typescript
2052
+ * // For partner auth mode - link requests to a specific customer
2053
+ * diviswap.setCustomer('user-123', 'user@example.com');
2054
+ *
2055
+ * // Now all API calls will be made on behalf of this customer
2056
+ * const payees = await diviswap.payees.getAll();
2057
+ * ```
2058
+ */
2059
+ setCustomer(customerId, customerEmail) {
2060
+ this.apiClient.setCustomer(customerId, customerEmail);
2061
+ }
2062
+ /**
2063
+ * Clear customer context for partner authentication mode
2064
+ */
2065
+ clearCustomer() {
2066
+ this.apiClient.clearCustomer();
2067
+ }
2068
+ validateConfig(config) {
2069
+ const isPartnerMode = "mode" in config && config.mode === "partner" || "keyId" in config && "secretKey" in config;
2070
+ if (isPartnerMode) {
2071
+ const partnerConfig = config;
2072
+ if (!partnerConfig.keyId) {
2073
+ throw new ConfigurationError("Partner keyId is required for partner authentication");
2074
+ }
2075
+ if (!partnerConfig.secretKey) {
2076
+ throw new ConfigurationError("Partner secretKey is required for partner authentication");
2077
+ }
2078
+ if (partnerConfig.authMethod && !["hmac", "jwt"].includes(partnerConfig.authMethod)) {
2079
+ throw new ConfigurationError('Invalid authMethod. Must be either "hmac" or "jwt"');
2080
+ }
2081
+ } else {
2082
+ const userConfig = config;
2083
+ if (!userConfig.apiKey) {
2084
+ throw new ConfigurationError("API Key is required for user authentication");
2085
+ }
2086
+ if (!userConfig.clientId) {
2087
+ throw new ConfigurationError("Client ID is required for user authentication");
2088
+ }
2089
+ }
2090
+ if (config.environment && !["production", "sandbox", "development"].includes(config.environment)) {
2091
+ throw new ConfigurationError("Invalid environment. Must be one of: production, sandbox, development");
2092
+ }
2093
+ }
2094
+ };
2095
+ _Diviswap.instance = null;
2096
+ var Diviswap = _Diviswap;
2097
+
2098
+ // src/integrations/wallet.ts
2099
+ var _WalletTracker = class _WalletTracker {
2100
+ constructor(config = {}) {
2101
+ this.wallet = null;
2102
+ this.diviswap = null;
2103
+ this.listeners = /* @__PURE__ */ new Map();
2104
+ this.config = {
2105
+ trackAccountChanges: true,
2106
+ trackChainChanges: true,
2107
+ setAsDefault: true,
2108
+ ...config
2109
+ };
2110
+ }
2111
+ /**
2112
+ * Get or create the wallet tracker instance
2113
+ */
2114
+ static getInstance(config) {
2115
+ if (!_WalletTracker.instance) {
2116
+ _WalletTracker.instance = new _WalletTracker(config);
2117
+ }
2118
+ return _WalletTracker.instance;
2119
+ }
2120
+ /**
2121
+ * Initialize wallet tracking with Diviswap SDK instance
2122
+ */
2123
+ init(diviswap, wallet) {
2124
+ this.diviswap = diviswap;
2125
+ if (wallet) {
2126
+ this.wallet = wallet;
2127
+ } else if (typeof window !== "undefined" && window.ethereum) {
2128
+ this.wallet = window.ethereum;
2129
+ }
2130
+ if (this.wallet && this.config.trackAccountChanges) {
2131
+ this.setupAccountChangeListener();
2132
+ }
2133
+ if (this.wallet && this.config.trackChainChanges) {
2134
+ this.setupChainChangeListener();
2135
+ }
2136
+ }
2137
+ /**
2138
+ * Connect and track a wallet
2139
+ */
2140
+ async connect() {
2141
+ if (!this.wallet) {
2142
+ throw new Error("No wallet provider available");
2143
+ }
2144
+ if (!this.diviswap) {
2145
+ throw new Error("Diviswap SDK not initialized. Call init() first.");
2146
+ }
2147
+ try {
2148
+ const accounts = await this.wallet.request({
2149
+ method: "eth_requestAccounts"
2150
+ });
2151
+ const chainId = await this.wallet.request({
2152
+ method: "eth_chainId"
2153
+ });
2154
+ const numericChainId = parseInt(chainId, 16);
2155
+ const connections = [];
2156
+ for (const account of accounts) {
2157
+ const connection = {
2158
+ address: account,
2159
+ chainId: numericChainId,
2160
+ chainName: this.getChainName(numericChainId)
2161
+ };
2162
+ await this.diviswap.addresses.trackWallet(connection);
2163
+ connections.push(connection);
2164
+ }
2165
+ return connections;
2166
+ } catch (error) {
2167
+ console.error("Failed to connect wallet:", error);
2168
+ throw error;
2169
+ }
2170
+ }
2171
+ /**
2172
+ * Track current wallet state without requesting connection
2173
+ */
2174
+ async trackCurrent() {
2175
+ if (!this.wallet) {
2176
+ throw new Error("No wallet provider available");
2177
+ }
2178
+ if (!this.diviswap) {
2179
+ throw new Error("Diviswap SDK not initialized. Call init() first.");
2180
+ }
2181
+ try {
2182
+ const accounts = await this.wallet.request({
2183
+ method: "eth_accounts"
2184
+ });
2185
+ if (accounts.length === 0) {
2186
+ return [];
2187
+ }
2188
+ const chainId = await this.wallet.request({
2189
+ method: "eth_chainId"
2190
+ });
2191
+ const numericChainId = parseInt(chainId, 16);
2192
+ const connections = [];
2193
+ for (const account of accounts) {
2194
+ const connection = {
2195
+ address: account,
2196
+ chainId: numericChainId,
2197
+ chainName: this.getChainName(numericChainId)
2198
+ };
2199
+ await this.diviswap.addresses.trackWallet(connection);
2200
+ connections.push(connection);
2201
+ }
2202
+ return connections;
2203
+ } catch (error) {
2204
+ console.error("Failed to track current wallet state:", error);
2205
+ throw error;
2206
+ }
2207
+ }
2208
+ /**
2209
+ * Setup listener for account changes
2210
+ */
2211
+ setupAccountChangeListener() {
2212
+ if (!this.wallet?.on) return;
2213
+ const handler = async (accounts) => {
2214
+ if (!this.diviswap) return;
2215
+ try {
2216
+ const chainId = await this.wallet.request({
2217
+ method: "eth_chainId"
2218
+ });
2219
+ const numericChainId = parseInt(chainId, 16);
2220
+ for (const account of accounts) {
2221
+ const connection = {
2222
+ address: account,
2223
+ chainId: numericChainId,
2224
+ chainName: this.getChainName(numericChainId)
2225
+ };
2226
+ await this.diviswap.addresses.trackWallet(connection);
2227
+ }
2228
+ } catch (error) {
2229
+ console.error("Failed to handle account change:", error);
2230
+ }
2231
+ };
2232
+ this.wallet.on("accountsChanged", handler);
2233
+ this.listeners.set("accountsChanged", handler);
2234
+ }
2235
+ /**
2236
+ * Setup listener for chain changes
2237
+ */
2238
+ setupChainChangeListener() {
2239
+ if (!this.wallet?.on) return;
2240
+ const handler = async (chainId) => {
2241
+ if (!this.diviswap) return;
2242
+ try {
2243
+ const accounts = await this.wallet.request({
2244
+ method: "eth_accounts"
2245
+ });
2246
+ const numericChainId = parseInt(chainId, 16);
2247
+ for (const account of accounts) {
2248
+ const connection = {
2249
+ address: account,
2250
+ chainId: numericChainId,
2251
+ chainName: this.getChainName(numericChainId)
2252
+ };
2253
+ await this.diviswap.addresses.trackWallet(connection);
2254
+ }
2255
+ } catch (error) {
2256
+ console.error("Failed to handle chain change:", error);
2257
+ }
2258
+ };
2259
+ this.wallet.on("chainChanged", handler);
2260
+ this.listeners.set("chainChanged", handler);
2261
+ }
2262
+ /**
2263
+ * Get chain name from chain ID
2264
+ */
2265
+ getChainName(chainId) {
2266
+ const builtInChain = Object.entries(CHAIN_IDS).find(([_, id]) => id === chainId)?.[0];
2267
+ if (builtInChain) return builtInChain;
2268
+ return this.config.customChains?.[chainId];
2269
+ }
2270
+ /**
2271
+ * Cleanup listeners
2272
+ */
2273
+ cleanup() {
2274
+ if (this.wallet?.removeListener) {
2275
+ for (const [event, handler] of this.listeners) {
2276
+ this.wallet.removeListener(event, handler);
2277
+ }
2278
+ }
2279
+ this.listeners.clear();
2280
+ }
2281
+ /**
2282
+ * Update configuration
2283
+ */
2284
+ updateConfig(config) {
2285
+ this.config = { ...this.config, ...config };
2286
+ }
2287
+ };
2288
+ _WalletTracker.instance = null;
2289
+ var WalletTracker = _WalletTracker;
2290
+ async function connectWallet(diviswap, wallet, config) {
2291
+ const tracker = WalletTracker.getInstance(config);
2292
+ tracker.init(diviswap, wallet);
2293
+ return tracker.connect();
2294
+ }
2295
+ async function trackCurrentWallet(diviswap, wallet, config) {
2296
+ const tracker = WalletTracker.getInstance(config);
2297
+ tracker.init(diviswap, wallet);
2298
+ return tracker.trackCurrent();
2299
+ }
2300
+ function setupWalletTracking(diviswap, wallet, config) {
2301
+ const tracker = WalletTracker.getInstance(config);
2302
+ tracker.init(diviswap, wallet);
2303
+ return tracker;
2304
+ }
2305
+
2306
+ // src/utils/web3.ts
2307
+ function extractTransactionHash(result) {
2308
+ if (typeof result === "string") {
2309
+ return result;
2310
+ }
2311
+ if (typeof result === "object" && result !== null && "hash" in result) {
2312
+ return result.hash;
2313
+ }
2314
+ return result;
2315
+ }
2316
+
2317
+ exports.AuthenticationError = AuthenticationError;
2318
+ exports.CHAIN_IDS = CHAIN_IDS;
2319
+ exports.CHAIN_ID_TO_NAME = CHAIN_ID_TO_NAME;
2320
+ exports.CHAIN_NAME_TO_ID = CHAIN_NAME_TO_ID;
2321
+ exports.ConfigurationError = ConfigurationError;
2322
+ exports.DEVELOPMENT_DEPOSIT_ADDRESSES = DEVELOPMENT_DEPOSIT_ADDRESSES;
2323
+ exports.Diviswap = Diviswap;
2324
+ exports.DiviswapError = DiviswapError;
2325
+ exports.LiberEx = Diviswap;
2326
+ exports.LiberExError = LiberExError;
2327
+ exports.NetworkError = NetworkError;
2328
+ exports.PRODUCTION_DEPOSIT_ADDRESSES = PRODUCTION_DEPOSIT_ADDRESSES;
2329
+ exports.SANDBOX_DEPOSIT_ADDRESSES = SANDBOX_DEPOSIT_ADDRESSES;
2330
+ exports.STABLECOIN_ADDRESSES = STABLECOIN_ADDRESSES;
2331
+ exports.ValidationError = ValidationError;
2332
+ exports.WalletTracker = WalletTracker;
2333
+ exports.connectWallet = connectWallet;
2334
+ exports.extractTransactionHash = extractTransactionHash;
2335
+ exports.getDepositAddresses = getDepositAddresses;
2336
+ exports.setupWalletTracking = setupWalletTracking;
2337
+ exports.trackCurrentWallet = trackCurrentWallet;
2338
+ //# sourceMappingURL=index.js.map
2339
+ //# sourceMappingURL=index.js.map