@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
@@ -0,0 +1,502 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { Diviswap } from '@diviswap/sdk';
3
+ import { cookies } from 'next/headers';
4
+ import type { Diviswap as DiviswapType } from '@diviswap/sdk';
5
+
6
+ // Initialize Diviswap SDK with partner authentication
7
+ function getDiviswap() {
8
+ const config = {
9
+ mode: 'partner' as const,
10
+ keyId: process.env.DIVISWAP_PARTNER_KEY_ID!,
11
+ secretKey: process.env.DIVISWAP_PARTNER_SECRET_KEY!,
12
+ authMethod: 'hmac' as const,
13
+ environment: (process.env.NEXT_PUBLIC_DIVISWAP_ENV as 'production' | 'sandbox') || 'sandbox'
14
+ };
15
+
16
+ return Diviswap.init(config);
17
+ }
18
+
19
+ // Helper function to handle errors
20
+ function handleError(error: unknown) {
21
+ console.error('Diviswap API error:', error);
22
+
23
+ if (error instanceof Error) {
24
+ return NextResponse.json(
25
+ { error: error.message },
26
+ { status: 500 }
27
+ );
28
+ }
29
+
30
+ return NextResponse.json(
31
+ { error: 'Internal server error' },
32
+ { status: 500 }
33
+ );
34
+ }
35
+
36
+ // Type definitions for handlers
37
+ type HandlerContext = {
38
+ diviswap: DiviswapType;
39
+ cookieStore: Awaited<ReturnType<typeof cookies>>;
40
+ };
41
+
42
+ type ActionHandler = (params: any, context: HandlerContext) => Promise<NextResponse>;
43
+ type ResourceHandler = (searchParams: URLSearchParams, context: HandlerContext) => Promise<NextResponse>;
44
+
45
+ // Helper function to set customer context from request
46
+ function setCustomerContext(diviswap: DiviswapType, params: any) {
47
+ // In partner authentication, you need to identify your user from your session/auth
48
+ // For this example, we'll expect customerId and customerEmail in the request
49
+ // In production, you'd get this from your own authentication system
50
+
51
+ const customerId = params.customerId || 'demo-customer-123';
52
+ const customerEmail = params.customerEmail || 'demo@yourapp.com';
53
+
54
+ diviswap.setCustomer(customerId, customerEmail);
55
+ }
56
+
57
+ // POST action handlers
58
+ const postHandlers: Record<string, ActionHandler> = {
59
+ setCustomer: async (params, { diviswap }) => {
60
+ try {
61
+ diviswap.setCustomer(params.customerId, params.customerEmail);
62
+ return NextResponse.json({
63
+ success: true,
64
+ customerId: params.customerId,
65
+ customerEmail: params.customerEmail
66
+ });
67
+ } catch (error: any) {
68
+ console.error('Set customer error:', error);
69
+ throw error;
70
+ }
71
+ },
72
+
73
+ clearCustomer: async (_, { diviswap }) => {
74
+ try {
75
+ diviswap.clearCustomer();
76
+ return NextResponse.json({ success: true });
77
+ } catch (error: any) {
78
+ console.error('Clear customer error:', error);
79
+ throw error;
80
+ }
81
+ },
82
+
83
+ createTransaction: async (params, { diviswap }) => {
84
+ // Set customer context before API calls
85
+ setCustomerContext(diviswap, params);
86
+
87
+ // Use the appropriate method based on transaction type
88
+ let transaction;
89
+ if (params.type === 'onramp') {
90
+ // Note: Onramp is not yet available in v1 API
91
+ return NextResponse.json(
92
+ { error: 'Onramp transactions are not yet available' },
93
+ { status: 400 }
94
+ );
95
+ } else {
96
+ // Validate required txHash for offramp
97
+ // Note: Frontend must send crypto FIRST, get txHash, then call this
98
+ if (!params.txHash) {
99
+ return NextResponse.json(
100
+ { error: 'txHash is required for offramp transactions' },
101
+ { status: 400 }
102
+ );
103
+ }
104
+
105
+ // Extract hash if it's an object (failsafe for different wallet types)
106
+ // Some wallets return {hash: '0x...'} instead of '0x...' directly
107
+ const txHashString = typeof params.txHash === 'string'
108
+ ? params.txHash
109
+ : (params.txHash?.hash || params.txHash);
110
+
111
+ const sdkParams = {
112
+ amount: params.amount,
113
+ currency: params.currency || 'USD',
114
+ payeeId: params.payeeId,
115
+ fromAddress: params.fromAddress,
116
+ toAddress: params.toAddress,
117
+ chain: params.chain || 'ethereum',
118
+ txHash: txHashString
119
+ };
120
+
121
+ // Use environment-appropriate method
122
+ // Production: uses regular offramp (creates completed transaction)
123
+ // Sandbox/Development: uses offrampTest (creates pending transaction)
124
+ const isProduction = process.env.NEXT_PUBLIC_DIVISWAP_ENV === 'production';
125
+ transaction = isProduction
126
+ ? await diviswap.transactions.offramp(sdkParams)
127
+ : await diviswap.transactions.offrampTest(sdkParams);
128
+ }
129
+ return NextResponse.json(transaction);
130
+ },
131
+
132
+ createPayee: async (params, { diviswap }) => {
133
+ // Set customer context before API calls
134
+ setCustomerContext(diviswap, params);
135
+
136
+
137
+ // Check if the SDK is sending structured debit card data
138
+ if (params.debitCard) {
139
+ // New SDK structure - debitCard object is already properly formatted
140
+ const debitCardPayload = {
141
+ nickname: params.nickname,
142
+ accountType: 'debit_card' as const,
143
+ debitCard: params.debitCard,
144
+ setAsDefault: params.setAsDefault || false
145
+ };
146
+
147
+ const payee = await diviswap.payees.create(debitCardPayload);
148
+ return NextResponse.json(payee);
149
+ }
150
+ // Handle legacy flat structure for debit cards
151
+ else if (params.accountType === 'debit_card' || params.payeeType === 'debit') {
152
+ // Parse expiry date if needed
153
+ let expirationMonth = params.expirationMonth;
154
+ let expirationYear = params.expirationYear;
155
+
156
+ // If expiry is in MM/YY format in routingNumber field
157
+ if (params.routingNumber && params.routingNumber.includes('/')) {
158
+ const expiryParts = params.routingNumber.split('/');
159
+ expirationMonth = expiryParts[0];
160
+ expirationYear = expiryParts[1] ? `20${expiryParts[1]}` : '2025';
161
+ }
162
+
163
+ const debitCardPayload = {
164
+ nickname: params.nickname,
165
+ accountType: 'debit_card' as const,
166
+ debitCard: {
167
+ number: params.accountNumber?.replace(/\s+/g, '') || '', // Remove spaces
168
+ expirationMonth: expirationMonth || '12',
169
+ expirationYear: expirationYear || '2025',
170
+ cvv: params.cvv || '123'
171
+ },
172
+ setAsDefault: params.setAsDefault || false
173
+ };
174
+
175
+ const payee = await diviswap.payees.create(debitCardPayload);
176
+ return NextResponse.json(payee);
177
+ } else {
178
+ // Bank account structure
179
+ const payee = await diviswap.payees.create({
180
+ nickname: params.nickname,
181
+ accountNumber: params.accountNumber,
182
+ routingNumber: params.routingNumber,
183
+ accountType: params.accountType || 'checking',
184
+ setAsDefault: params.setAsDefault || false
185
+ });
186
+ return NextResponse.json(payee);
187
+ }
188
+ },
189
+
190
+ {{#if (includes features "fees")}}
191
+ calculateFees: async (params, { diviswap }) => {
192
+ const fees = await diviswap.fees.calculateFees({
193
+ amount: params.amount,
194
+ userId: undefined
195
+ });
196
+ return NextResponse.json(fees);
197
+ },
198
+
199
+ getIntegratorFees: async (_, { diviswap }) => {
200
+ const fees = await diviswap.fees.getFees();
201
+ return NextResponse.json(fees);
202
+ },
203
+ {{/if}}
204
+
205
+ submitKYC: async (params, { diviswap }) => {
206
+ // Set customer context before KYC submission
207
+ setCustomerContext(diviswap, params);
208
+
209
+ try {
210
+
211
+ // Extract data from nested structure
212
+ const personalInfo = params.personalInfo || {};
213
+ const address = params.address || {};
214
+
215
+
216
+ // Validate required address fields
217
+ if (!address.addressLine1 || !address.city || !address.state || !address.postalCode || !address.country) {
218
+ console.error('[API Route] Missing required address fields:', {
219
+ hasAddressLine1: !!address.addressLine1,
220
+ hasCity: !!address.city,
221
+ hasState: !!address.state,
222
+ hasPostalCode: !!address.postalCode,
223
+ hasCountry: !!address.country,
224
+ rawAddress: address
225
+ });
226
+ return NextResponse.json({
227
+ success: false,
228
+ error: 'Missing required address fields'
229
+ }, { status: 400 });
230
+ }
231
+
232
+ // Clean up the payload - remove undefined/null values and empty strings for optional fields
233
+ const street = address.addressLine1 + (address.addressLine2 && address.addressLine2.trim() ? ` ${address.addressLine2.trim()}` : '');
234
+
235
+ const kycPayload = {
236
+ firstName: personalInfo.firstName,
237
+ lastName: personalInfo.lastName,
238
+ dateOfBirth: personalInfo.dateOfBirth,
239
+ ...(personalInfo.ssn && { ssn: personalInfo.ssn }),
240
+ ...(personalInfo.phone && { phone: personalInfo.phone }),
241
+ address: {
242
+ street: street,
243
+ city: address.city,
244
+ state: address.state,
245
+ postalCode: address.postalCode,
246
+ country: address.country
247
+ }
248
+ };
249
+
250
+
251
+ const result = await diviswap.kyc.submitPersonalInfo(kycPayload);
252
+
253
+ return NextResponse.json(result);
254
+ } catch (error: any) {
255
+ console.error('[API Route] KYC submission failed:', error);
256
+
257
+ // Return the error to the client
258
+
259
+ throw error;
260
+ }
261
+ },
262
+
263
+ createAddress: async (params, { diviswap }) => {
264
+ // Set customer context before API call
265
+ setCustomerContext(diviswap, params);
266
+
267
+ try {
268
+ const address = await diviswap.addresses.create({
269
+ chain_id: params.chain_id,
270
+ address: params.address,
271
+ is_default: params.is_default
272
+ });
273
+
274
+ return NextResponse.json(address);
275
+ } catch (error: any) {
276
+ console.error('[API Route] Address creation failed:', error);
277
+ throw error;
278
+ }
279
+ },
280
+
281
+ setDefaultAddress: async (params, { diviswap }) => {
282
+ // Set customer context before API call
283
+ setCustomerContext(diviswap, params);
284
+
285
+ try {
286
+ await diviswap.addresses.setDefault({
287
+ chain_id: params.chain_id,
288
+ address: params.address
289
+ });
290
+
291
+ return NextResponse.json({ success: true });
292
+ } catch (error: any) {
293
+ console.error('[API Route] Set default address failed:', error);
294
+ throw error;
295
+ }
296
+ },
297
+
298
+ deleteAddress: async (params, { diviswap }) => {
299
+ // Set customer context before API call
300
+ setCustomerContext(diviswap, params);
301
+
302
+ try {
303
+ await diviswap.addresses.delete({
304
+ chain_id: params.chain_id,
305
+ address: params.address
306
+ });
307
+
308
+ return NextResponse.json({ success: true });
309
+ } catch (error: any) {
310
+ console.error('[API Route] Address deletion failed:', error);
311
+ throw error;
312
+ }
313
+ }
314
+ };
315
+
316
+ export async function POST(request: NextRequest) {
317
+ try {
318
+ const body = await request.json();
319
+ const { action, ...params } = body;
320
+
321
+ // Get cookies for any cookie-based operations
322
+ const cookieStore = await cookies();
323
+
324
+ // Find and execute handler
325
+ const handler = postHandlers[action];
326
+ if (!handler) {
327
+ return NextResponse.json(
328
+ { error: 'Invalid action' },
329
+ { status: 400 }
330
+ );
331
+ }
332
+
333
+ const diviswap = getDiviswap();
334
+ return await handler(params, { diviswap, cookieStore });
335
+ } catch (error) {
336
+ return handleError(error);
337
+ }
338
+ }
339
+
340
+ // GET resource handlers
341
+ const getHandlers: Record<string, ResourceHandler> = {
342
+ customerStatus: async (searchParams, { diviswap }) => {
343
+ const customerId = searchParams.get('customerId') || 'demo-customer-123';
344
+ const customerEmail = searchParams.get('customerEmail') || 'demo@yourapp.com';
345
+
346
+ // Set customer context
347
+ diviswap.setCustomer(customerId, customerEmail);
348
+
349
+ return NextResponse.json({
350
+ customerId,
351
+ customerEmail,
352
+ authenticated: true,
353
+ mode: 'partner'
354
+ });
355
+ },
356
+
357
+ payees: async (searchParams, { diviswap }) => {
358
+ const customerId = searchParams.get('customerId') || 'demo-customer-123';
359
+ const customerEmail = searchParams.get('customerEmail') || 'demo@yourapp.com';
360
+
361
+ // Set customer context before API call
362
+ diviswap.setCustomer(customerId, customerEmail);
363
+
364
+ const payees = await diviswap.payees.list();
365
+ return NextResponse.json(payees);
366
+ },
367
+
368
+ transactions: async (searchParams, { diviswap }) => {
369
+ const customerId = searchParams.get('customerId') || 'demo-customer-123';
370
+ const customerEmail = searchParams.get('customerEmail') || 'demo@yourapp.com';
371
+
372
+ // Set customer context before API call
373
+ diviswap.setCustomer(customerId, customerEmail);
374
+
375
+ const limit = searchParams.get('limit');
376
+ const offset = searchParams.get('offset');
377
+ const status = searchParams.get('status');
378
+ const type = searchParams.get('type');
379
+
380
+ const transactions = await diviswap.transactions.list({
381
+ limit: limit ? Number(limit) : 10,
382
+ offset: offset ? Number(offset) : 0,
383
+ status: status as 'pending' | 'processing' | 'completed' | 'failed' | undefined,
384
+ type: type as 'onramp' | 'offramp' | undefined
385
+ });
386
+
387
+ return NextResponse.json(transactions);
388
+ },
389
+
390
+ kycStatus: async (searchParams, { diviswap }) => {
391
+ const customerId = searchParams.get('customerId') || 'demo-customer-123';
392
+ const customerEmail = searchParams.get('customerEmail') || 'demo@yourapp.com';
393
+
394
+ // Set customer context before API call
395
+ diviswap.setCustomer(customerId, customerEmail);
396
+
397
+ try {
398
+
399
+ const status = await diviswap.kyc.getComplianceStatus();
400
+ return NextResponse.json(status);
401
+ } catch (error: any) {
402
+ console.error('Failed to get KYC status:', error);
403
+ // Return default status on error
404
+ return NextResponse.json({
405
+ kycStatus: 'NOT_STARTED',
406
+ kybStatus: 'NOT_REQUIRED',
407
+ canTransact: false,
408
+ requiresAction: true,
409
+ verificationLevel: 'none',
410
+ nextStep: 'COMPLETE_KYC'
411
+ });
412
+ }
413
+ },
414
+
415
+ addresses: async (searchParams, { diviswap }) => {
416
+ const customerId = searchParams.get('customerId') || 'demo-customer-123';
417
+ const customerEmail = searchParams.get('customerEmail') || 'demo@yourapp.com';
418
+
419
+ // Set customer context before API call
420
+ diviswap.setCustomer(customerId, customerEmail);
421
+
422
+ const chain_id = searchParams.get('chain_id');
423
+ const is_default = searchParams.get('is_default');
424
+
425
+ const addresses = await diviswap.addresses.list({
426
+ ...(chain_id && { chain_id: Number(chain_id) }),
427
+ ...(is_default !== null && { is_default: is_default === 'true' })
428
+ });
429
+
430
+ return NextResponse.json(addresses);
431
+ },
432
+
433
+ };
434
+
435
+ export async function GET(request: NextRequest) {
436
+ try {
437
+ const { searchParams } = new URL(request.url);
438
+ const resource = searchParams.get('resource');
439
+ const cookieStore = await cookies();
440
+
441
+ // Find and execute handler
442
+ const handler = getHandlers[resource || ''];
443
+ if (!handler) {
444
+ return NextResponse.json(
445
+ { error: 'Invalid resource' },
446
+ { status: 400 }
447
+ );
448
+ }
449
+
450
+ const diviswap = getDiviswap();
451
+ return await handler(searchParams, { diviswap, cookieStore });
452
+ } catch (error) {
453
+ return handleError(error);
454
+ }
455
+ }
456
+
457
+ {{#if (includes features "webhooks")}}
458
+ // DELETE resource handlers
459
+ const deleteHandlers: Record<string, ResourceHandler> = {
460
+ payee: async (searchParams, { diviswap }) => {
461
+ const customerId = searchParams.get('customerId') || 'demo-customer-123';
462
+ const customerEmail = searchParams.get('customerEmail') || 'demo@yourapp.com';
463
+ const id = searchParams.get('id');
464
+
465
+ if (!id) {
466
+ return NextResponse.json(
467
+ { error: 'Payee ID required' },
468
+ { status: 400 }
469
+ );
470
+ }
471
+
472
+ // Set customer context before API call
473
+ diviswap.setCustomer(customerId, customerEmail);
474
+
475
+ await diviswap.payees.delete(id);
476
+ return NextResponse.json({ success: true });
477
+ },
478
+ };
479
+
480
+ // DELETE method for cleanup operations
481
+ export async function DELETE(request: NextRequest) {
482
+ try {
483
+ const { searchParams } = new URL(request.url);
484
+ const resource = searchParams.get('resource');
485
+ const cookieStore = await cookies();
486
+
487
+ // Find and execute handler
488
+ const handler = deleteHandlers[resource || ''];
489
+ if (!handler) {
490
+ return NextResponse.json(
491
+ { error: 'Invalid resource' },
492
+ { status: 400 }
493
+ );
494
+ }
495
+
496
+ const diviswap = getDiviswap();
497
+ return await handler(searchParams, { diviswap, cookieStore });
498
+ } catch (error) {
499
+ return handleError(error);
500
+ }
501
+ }
502
+ {{/if}}
@@ -0,0 +1,59 @@
1
+ "use client";
2
+
3
+ import { createContext, useContext, ReactNode } from 'react';
4
+
5
+ interface {{prefix}}AuthContextType {
6
+ isAuthenticated: boolean;
7
+ isLoading: boolean;
8
+ customerId: string | null;
9
+ customerEmail: string | null;
10
+ clearCustomer: () => Promise<void>;
11
+ }
12
+
13
+ const {{prefix}}AuthContext = createContext<{{prefix}}AuthContextType>({
14
+ isAuthenticated: false,
15
+ isLoading: false,
16
+ customerId: null,
17
+ customerEmail: null,
18
+ clearCustomer: async () => {},
19
+ });
20
+
21
+ interface {{prefix}}AuthProviderProps {
22
+ children: ReactNode;
23
+ customerId: string | null;
24
+ customerEmail: string | null;
25
+ loading: boolean;
26
+ clearCustomer: () => Promise<void>;
27
+ }
28
+
29
+ // This provider receives props instead of using useDiviswap directly
30
+ // to avoid circular dependencies
31
+ export function {{prefix}}AuthProvider({
32
+ children,
33
+ customerId,
34
+ customerEmail,
35
+ loading,
36
+ clearCustomer
37
+ }: {{prefix}}AuthProviderProps) {
38
+ return (
39
+ <{{prefix}}AuthContext.Provider
40
+ value=\{{
41
+ isAuthenticated: !!(customerId && customerEmail),
42
+ isLoading: loading,
43
+ customerId,
44
+ customerEmail,
45
+ clearCustomer
46
+ }}
47
+ >
48
+ {children}
49
+ </{{prefix}}AuthContext.Provider>
50
+ );
51
+ }
52
+
53
+ export const use{{prefix}}Auth = () => {
54
+ const context = useContext({{prefix}}AuthContext);
55
+ if (!context) {
56
+ throw new Error('use{{prefix}}Auth must be used within {{prefix}}AuthProvider');
57
+ }
58
+ return context;
59
+ };
@@ -0,0 +1,116 @@
1
+ // This file is auto-generated by Diviswap SDK CLI
2
+ // It provides a client for communicating with the Diviswap API routes
3
+
4
+ export class DiviswapClient {
5
+ constructor(private baseUrl: string = '/api/diviswap') {}
6
+
7
+ private async request<T = any>(
8
+ endpoint: string,
9
+ options: RequestInit = {}
10
+ ): Promise<T> {
11
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
12
+ ...options,
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ ...options.headers,
16
+ },
17
+ });
18
+
19
+ if (!response.ok) {
20
+ const error = await response.json().catch(() => ({ message: 'Request failed' }));
21
+ throw new Error(error.error || error.message || 'Request failed');
22
+ }
23
+
24
+ return response.json();
25
+ }
26
+
27
+ // Customer context management for partner authentication
28
+ async setCustomer(customerId: string, customerEmail: string) {
29
+ return this.request('', {
30
+ method: 'POST',
31
+ body: JSON.stringify({ action: 'setCustomer', customerId, customerEmail }),
32
+ });
33
+ }
34
+
35
+ async clearCustomer() {
36
+ return this.request('', {
37
+ method: 'POST',
38
+ body: JSON.stringify({ action: 'clearCustomer' }),
39
+ });
40
+ }
41
+
42
+ async getCustomerStatus(customerId: string, customerEmail: string) {
43
+ try {
44
+ return await this.request(`?resource=customerStatus&customerId=${encodeURIComponent(customerId)}&customerEmail=${encodeURIComponent(customerEmail)}`);
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ // Transaction methods
51
+ async createTransaction(data: any) {
52
+ return this.request('', {
53
+ method: 'POST',
54
+ body: JSON.stringify({ action: 'createTransaction', ...data }),
55
+ });
56
+ }
57
+
58
+ async getTransactions(customerId: string, customerEmail: string, params?: {
59
+ limit?: number;
60
+ offset?: number;
61
+ status?: string;
62
+ type?: string;
63
+ }) {
64
+ const searchParams = new URLSearchParams({
65
+ resource: 'transactions',
66
+ customerId,
67
+ customerEmail,
68
+ ...(params && {
69
+ limit: params.limit?.toString() || '10',
70
+ offset: params.offset?.toString() || '0',
71
+ ...(params.status && { status: params.status }),
72
+ ...(params.type && { type: params.type }),
73
+ }),
74
+ });
75
+ return this.request(`?${searchParams}`);
76
+ }
77
+
78
+ async getTransaction(id: string) {
79
+ return this.request(`?resource=transaction&id=${id}`);
80
+ }
81
+
82
+ // Payee methods
83
+ async getPayees(customerId: string, customerEmail: string) {
84
+ return this.request(`?resource=payees&customerId=${encodeURIComponent(customerId)}&customerEmail=${encodeURIComponent(customerEmail)}`);
85
+ }
86
+
87
+ async createPayee(data: any) {
88
+ return this.request('', {
89
+ method: 'POST',
90
+ body: JSON.stringify({ action: 'createPayee', ...data }),
91
+ });
92
+ }
93
+
94
+ async deletePayee(id: string, customerId: string, customerEmail: string) {
95
+ return this.request(`?resource=payee&id=${id}&customerId=${encodeURIComponent(customerId)}&customerEmail=${encodeURIComponent(customerEmail)}`, {
96
+ method: 'DELETE',
97
+ });
98
+ }
99
+
100
+ {{#if (includes features "fees")}}
101
+ // Fee calculation methods
102
+ async calculateFees(data: { amount: number; type: 'onramp' | 'offramp'; currency?: string }) {
103
+ return this.request('', {
104
+ method: 'POST',
105
+ body: JSON.stringify({ action: 'calculateFees', ...data }),
106
+ });
107
+ }
108
+
109
+ async getIntegratorFees() {
110
+ return this.request('', {
111
+ method: 'POST',
112
+ body: JSON.stringify({ action: 'getIntegratorFees' }),
113
+ });
114
+ }
115
+ {{/if}}
116
+ }