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