@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.
- package/LICENSE +21 -0
- package/README.md +510 -0
- package/bin/create-diviswap-app.js +25 -0
- package/bin/diviswap-sdk.js +4 -0
- package/dist/cli/index.js +1888 -0
- package/dist/cli/templates/nextjs-app/actions.ts.hbs +259 -0
- package/dist/cli/templates/nextjs-app/api-hooks.ts.hbs +439 -0
- package/dist/cli/templates/nextjs-app/api-route.ts.hbs +502 -0
- package/dist/cli/templates/nextjs-app/auth-context.tsx.hbs +59 -0
- package/dist/cli/templates/nextjs-app/client.ts.hbs +116 -0
- package/dist/cli/templates/nextjs-app/dashboard-hooks.ts.hbs +180 -0
- package/dist/cli/templates/nextjs-app/example-page.tsx.hbs +276 -0
- package/dist/cli/templates/nextjs-app/hooks.ts.hbs +252 -0
- package/dist/cli/templates/nextjs-app/kyc-hooks.ts.hbs +87 -0
- package/dist/cli/templates/nextjs-app/kyc-wizard.css.hbs +433 -0
- package/dist/cli/templates/nextjs-app/kyc-wizard.tsx.hbs +711 -0
- package/dist/cli/templates/nextjs-app/layout-wrapper.tsx.hbs +13 -0
- package/dist/cli/templates/nextjs-app/layout.tsx.hbs +13 -0
- package/dist/cli/templates/nextjs-app/middleware.ts.hbs +49 -0
- package/dist/cli/templates/nextjs-app/provider-wrapper.tsx.hbs +8 -0
- package/dist/cli/templates/nextjs-app/provider.tsx.hbs +408 -0
- package/dist/cli/templates/nextjs-app/setup-provider.tsx.hbs +25 -0
- package/dist/cli/templates/nextjs-app/types.ts.hbs +159 -0
- package/dist/cli/templates/react/api-client-wrapper.ts.hbs +89 -0
- package/dist/cli/templates/react/example.tsx.hbs +69 -0
- package/dist/cli/templates/react/tanstack-hooks.ts.hbs +185 -0
- package/dist/cli/templates/webhooks/nextjs.hbs +98 -0
- package/dist/index.d.mts +91 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.js +2339 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2313 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +192 -0
- package/dist/react/index.d.ts +192 -0
- package/dist/react/index.js +1083 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +1064 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/wallet-BEGvzNtB.d.mts +1614 -0
- package/dist/wallet-BEGvzNtB.d.ts +1614 -0
- package/package.json +102 -0
- package/src/cli/templates/index.ts +65 -0
- package/src/cli/templates/nextjs-app/actions.ts.hbs +259 -0
- package/src/cli/templates/nextjs-app/api-hooks.ts.hbs +439 -0
- package/src/cli/templates/nextjs-app/api-route.ts.hbs +502 -0
- package/src/cli/templates/nextjs-app/auth-context.tsx.hbs +59 -0
- package/src/cli/templates/nextjs-app/client.ts.hbs +116 -0
- package/src/cli/templates/nextjs-app/dashboard-hooks.ts.hbs +180 -0
- package/src/cli/templates/nextjs-app/example-page.tsx.hbs +276 -0
- package/src/cli/templates/nextjs-app/hooks.ts.hbs +252 -0
- package/src/cli/templates/nextjs-app/kyc-hooks.ts.hbs +87 -0
- package/src/cli/templates/nextjs-app/kyc-wizard.css.hbs +433 -0
- package/src/cli/templates/nextjs-app/kyc-wizard.tsx.hbs +711 -0
- package/src/cli/templates/nextjs-app/layout-wrapper.tsx.hbs +13 -0
- package/src/cli/templates/nextjs-app/layout.tsx.hbs +13 -0
- package/src/cli/templates/nextjs-app/middleware.ts.hbs +49 -0
- package/src/cli/templates/nextjs-app/provider-wrapper.tsx.hbs +8 -0
- package/src/cli/templates/nextjs-app/provider.tsx.hbs +408 -0
- package/src/cli/templates/nextjs-app/setup-provider.tsx.hbs +25 -0
- package/src/cli/templates/nextjs-app/types.ts.hbs +159 -0
- package/src/cli/templates/react/api-client-wrapper.ts.hbs +89 -0
- package/src/cli/templates/react/example.tsx.hbs +69 -0
- package/src/cli/templates/react/tanstack-hooks.ts.hbs +185 -0
- package/src/cli/templates/shared/client.ts +78 -0
- package/src/cli/templates/webhooks/nextjs.hbs +98 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
|
|
3
|
+
// This middleware adds Diviswap session information to requests
|
|
4
|
+
// Note: In middleware, we use request.cookies (not the async cookies() from next/headers)
|
|
5
|
+
export function diviswapMiddleware(request: NextRequest) {
|
|
6
|
+
// Check for Diviswap session cookie
|
|
7
|
+
const diviswapSession = request.cookies.get('diviswap_session');
|
|
8
|
+
|
|
9
|
+
if (!diviswapSession) {
|
|
10
|
+
// No session, proceed without authentication
|
|
11
|
+
return NextResponse.next();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Add session to headers for API routes
|
|
15
|
+
const requestHeaders = new Headers(request.headers);
|
|
16
|
+
requestHeaders.set('x-diviswap-session', diviswapSession.value);
|
|
17
|
+
|
|
18
|
+
// You can also add other headers or perform additional checks here
|
|
19
|
+
requestHeaders.set('x-diviswap-client-version', '1.0.0');
|
|
20
|
+
|
|
21
|
+
return NextResponse.next({
|
|
22
|
+
request: {
|
|
23
|
+
headers: requestHeaders,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Optional: Add route protection
|
|
29
|
+
export function protectDiviswapRoutes(request: NextRequest) {
|
|
30
|
+
const diviswapSession = request.cookies.get('diviswap_session');
|
|
31
|
+
|
|
32
|
+
// List of protected routes
|
|
33
|
+
const protectedRoutes = [
|
|
34
|
+
'/diviswap/dashboard',
|
|
35
|
+
'/diviswap/transactions',
|
|
36
|
+
'/diviswap/settings'
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const isProtectedRoute = protectedRoutes.some(route =>
|
|
40
|
+
request.nextUrl.pathname.startsWith(route)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (isProtectedRoute && !diviswapSession) {
|
|
44
|
+
// Redirect to login page
|
|
45
|
+
return NextResponse.redirect(new URL('/diviswap', request.url));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return diviswapMiddleware(request);
|
|
49
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { DiviswapProvider } from '@diviswap/sdk/react';
|
|
4
|
+
|
|
5
|
+
// Wrapper to ensure client-side rendering for Diviswap components
|
|
6
|
+
export function DiviswapClientProvider({ children }: { children: React.ReactNode }) {
|
|
7
|
+
return <DiviswapProvider>{children}</DiviswapProvider>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext, useEffect, useState, useCallback } from 'react';
|
|
4
|
+
import type { User, Transaction, Payee, TransactionStatus } from './lbx-types';
|
|
5
|
+
{{#if (includes features "realtime")}}
|
|
6
|
+
import io, { Socket } from 'socket.io-client';
|
|
7
|
+
{{/if}}
|
|
8
|
+
|
|
9
|
+
interface DiviswapContextValue {
|
|
10
|
+
// Customer state (for partner authentication)
|
|
11
|
+
customerId: string | null;
|
|
12
|
+
customerEmail: string | null;
|
|
13
|
+
loading: boolean;
|
|
14
|
+
error: Error | null;
|
|
15
|
+
|
|
16
|
+
// Customer context methods
|
|
17
|
+
setCustomer: (customerId: string, customerEmail: string) => Promise<void>;
|
|
18
|
+
clearCustomer: () => Promise<void>;
|
|
19
|
+
getCustomerStatus: () => Promise<any>;
|
|
20
|
+
|
|
21
|
+
// Transaction methods
|
|
22
|
+
createTransaction: (data: {
|
|
23
|
+
type: 'onramp' | 'offramp';
|
|
24
|
+
amount: number;
|
|
25
|
+
currency?: string;
|
|
26
|
+
payeeId?: string;
|
|
27
|
+
paymentMethodId?: string;
|
|
28
|
+
}) => Promise<Transaction>;
|
|
29
|
+
getTransactions: (filters?: {
|
|
30
|
+
limit?: number;
|
|
31
|
+
offset?: number;
|
|
32
|
+
status?: TransactionStatus;
|
|
33
|
+
type?: 'onramp' | 'offramp';
|
|
34
|
+
}) => Promise<Transaction[]>;
|
|
35
|
+
getTransaction: (id: string) => Promise<Transaction>;
|
|
36
|
+
|
|
37
|
+
// Payee methods
|
|
38
|
+
getPayees: () => Promise<Payee[]>;
|
|
39
|
+
createPayee: (data: {
|
|
40
|
+
nickname: string;
|
|
41
|
+
network: string;
|
|
42
|
+
address: string;
|
|
43
|
+
type: 'crypto' | 'bank';
|
|
44
|
+
}) => Promise<Payee>;
|
|
45
|
+
deletePayee: (id: string) => Promise<void>;
|
|
46
|
+
|
|
47
|
+
{{#if (includes features "fees")}}
|
|
48
|
+
// Fee calculation
|
|
49
|
+
calculateFees: (amount: number, type: 'onramp' | 'offramp', currency?: string) => Promise<{
|
|
50
|
+
baseFee: number;
|
|
51
|
+
networkFee: number;
|
|
52
|
+
integratorFee?: number;
|
|
53
|
+
totalFee: number;
|
|
54
|
+
finalAmount: number;
|
|
55
|
+
}>;
|
|
56
|
+
{{/if}}
|
|
57
|
+
|
|
58
|
+
{{#if (includes features "realtime")}}
|
|
59
|
+
// Real-time updates
|
|
60
|
+
socket: Socket | null;
|
|
61
|
+
subscribeToTransaction: (transactionId: string) => void;
|
|
62
|
+
unsubscribeFromTransaction: (transactionId: string) => void;
|
|
63
|
+
{{/if}}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const DiviswapContext = createContext<DiviswapContextValue | null>(null);
|
|
67
|
+
|
|
68
|
+
// API client class
|
|
69
|
+
class DiviswapClient {
|
|
70
|
+
constructor(private baseUrl: string = '/api/diviswap') {}
|
|
71
|
+
|
|
72
|
+
private async request<T = any>(
|
|
73
|
+
endpoint: string,
|
|
74
|
+
options: RequestInit = {}
|
|
75
|
+
): Promise<T> {
|
|
76
|
+
const response = await fetch(`${this.baseUrl}${endpoint}`, {
|
|
77
|
+
...options,
|
|
78
|
+
headers: {
|
|
79
|
+
'Content-Type': 'application/json',
|
|
80
|
+
...options.headers,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
const error = await response.json().catch(() => ({ message: 'Request failed' }));
|
|
86
|
+
throw new Error(error.error || error.message || 'Request failed');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return response.json();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Customer context methods
|
|
93
|
+
async setCustomer(customerId: string, customerEmail: string) {
|
|
94
|
+
return this.request('', {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
body: JSON.stringify({ action: 'setCustomer', customerId, customerEmail }),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async clearCustomer() {
|
|
101
|
+
return this.request('', {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
body: JSON.stringify({ action: 'clearCustomer' }),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async getCustomerStatus(customerId: string, customerEmail: string) {
|
|
108
|
+
try {
|
|
109
|
+
return await this.request(`?resource=customerStatus&customerId=${encodeURIComponent(customerId)}&customerEmail=${encodeURIComponent(customerEmail)}`);
|
|
110
|
+
} catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Transaction methods
|
|
116
|
+
async createTransaction(data: any) {
|
|
117
|
+
return this.request('', {
|
|
118
|
+
method: 'POST',
|
|
119
|
+
body: JSON.stringify({ action: 'createTransaction', ...data }),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async getTransactions(customerId: string, customerEmail: string, params?: any) {
|
|
124
|
+
const searchParams = new URLSearchParams({
|
|
125
|
+
resource: 'transactions',
|
|
126
|
+
customerId,
|
|
127
|
+
customerEmail,
|
|
128
|
+
...(params && {
|
|
129
|
+
limit: params.limit?.toString() || '10',
|
|
130
|
+
offset: params.offset?.toString() || '0',
|
|
131
|
+
...(params.status && { status: params.status }),
|
|
132
|
+
...(params.type && { type: params.type }),
|
|
133
|
+
}),
|
|
134
|
+
});
|
|
135
|
+
return this.request(`?${searchParams}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async getTransaction(id: string) {
|
|
139
|
+
return this.request(`?resource=transaction&id=${id}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Payee methods
|
|
143
|
+
async getPayees(customerId: string, customerEmail: string) {
|
|
144
|
+
return this.request(`?resource=payees&customerId=${encodeURIComponent(customerId)}&customerEmail=${encodeURIComponent(customerEmail)}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async createPayee(data: any) {
|
|
148
|
+
return this.request('', {
|
|
149
|
+
method: 'POST',
|
|
150
|
+
body: JSON.stringify({ action: 'createPayee', ...data }),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async deletePayee(id: string, customerId: string, customerEmail: string) {
|
|
155
|
+
return this.request(`?resource=payee&id=${id}&customerId=${encodeURIComponent(customerId)}&customerEmail=${encodeURIComponent(customerEmail)}`, {
|
|
156
|
+
method: 'DELETE',
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
{{#if (includes features "fees")}}
|
|
161
|
+
// Fee methods
|
|
162
|
+
async calculateFees(data: { amount: number; type: 'onramp' | 'offramp'; currency?: string }) {
|
|
163
|
+
return this.request('', {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
body: JSON.stringify({ action: 'calculateFees', ...data }),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
{{/if}}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function DiviswapProvider({ children }: { children: React.ReactNode }) {
|
|
172
|
+
const [customerId, setCustomerId] = useState<string | null>(null);
|
|
173
|
+
const [customerEmail, setCustomerEmail] = useState<string | null>(null);
|
|
174
|
+
const [loading, setLoading] = useState(false);
|
|
175
|
+
const [error, setError] = useState<Error | null>(null);
|
|
176
|
+
{{#if (includes features "realtime")}}
|
|
177
|
+
const [socket, setSocket] = useState<Socket | null>(null);
|
|
178
|
+
{{/if}}
|
|
179
|
+
|
|
180
|
+
const client = new DiviswapClient('/api/diviswap');
|
|
181
|
+
|
|
182
|
+
// Initialize with demo customer for development
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
// In production, you would get customer context from your authentication system
|
|
185
|
+
// For demo purposes, we'll use placeholder values
|
|
186
|
+
setCustomerId('demo-customer-123');
|
|
187
|
+
setCustomerEmail('demo@yourapp.com');
|
|
188
|
+
}, []);
|
|
189
|
+
|
|
190
|
+
{{#if (includes features "realtime")}}
|
|
191
|
+
// Initialize WebSocket connection when customer is set
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
if (customerId && customerEmail) {
|
|
194
|
+
const socketInstance = io(
|
|
195
|
+
process.env.NEXT_PUBLIC_DIVISWAP_WS_URL || 'wss://ws.diviswap.io',
|
|
196
|
+
{
|
|
197
|
+
auth: {
|
|
198
|
+
customerId,
|
|
199
|
+
customerEmail
|
|
200
|
+
},
|
|
201
|
+
reconnection: true,
|
|
202
|
+
reconnectionAttempts: 5,
|
|
203
|
+
reconnectionDelay: 1000,
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
socketInstance.on('connect', () => {
|
|
208
|
+
console.log('Connected to Diviswap WebSocket');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
socketInstance.on('disconnect', () => {
|
|
212
|
+
console.log('Disconnected from Diviswap WebSocket');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
socketInstance.on('transaction:update', (data) => {
|
|
216
|
+
console.log('Transaction update:', data);
|
|
217
|
+
// You can emit custom events or update local state here
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
setSocket(socketInstance);
|
|
221
|
+
|
|
222
|
+
return () => {
|
|
223
|
+
socketInstance.disconnect();
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}, [customerId, customerEmail]);
|
|
227
|
+
{{/if}}
|
|
228
|
+
|
|
229
|
+
const setCustomer = useCallback(async (newCustomerId: string, newCustomerEmail: string) => {
|
|
230
|
+
try {
|
|
231
|
+
setError(null);
|
|
232
|
+
setLoading(true);
|
|
233
|
+
await client.setCustomer(newCustomerId, newCustomerEmail);
|
|
234
|
+
setCustomerId(newCustomerId);
|
|
235
|
+
setCustomerEmail(newCustomerEmail);
|
|
236
|
+
} catch (err) {
|
|
237
|
+
setError(err as Error);
|
|
238
|
+
throw err;
|
|
239
|
+
} finally {
|
|
240
|
+
setLoading(false);
|
|
241
|
+
}
|
|
242
|
+
}, []);
|
|
243
|
+
|
|
244
|
+
const clearCustomer = useCallback(async () => {
|
|
245
|
+
try {
|
|
246
|
+
setError(null);
|
|
247
|
+
setLoading(true);
|
|
248
|
+
await client.clearCustomer();
|
|
249
|
+
setCustomerId(null);
|
|
250
|
+
setCustomerEmail(null);
|
|
251
|
+
{{#if (includes features "realtime")}}
|
|
252
|
+
socket?.disconnect();
|
|
253
|
+
setSocket(null);
|
|
254
|
+
{{/if}}
|
|
255
|
+
} catch (err) {
|
|
256
|
+
setError(err as Error);
|
|
257
|
+
throw err;
|
|
258
|
+
} finally {
|
|
259
|
+
setLoading(false);
|
|
260
|
+
}
|
|
261
|
+
}, [{{#if (includes features "realtime")}}socket{{/if}}]);
|
|
262
|
+
|
|
263
|
+
const getCustomerStatus = useCallback(async () => {
|
|
264
|
+
if (!customerId || !customerEmail) {
|
|
265
|
+
throw new Error('Customer context not set');
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
setError(null);
|
|
269
|
+
return await client.getCustomerStatus(customerId, customerEmail);
|
|
270
|
+
} catch (err) {
|
|
271
|
+
setError(err as Error);
|
|
272
|
+
throw err;
|
|
273
|
+
}
|
|
274
|
+
}, [customerId, customerEmail]);
|
|
275
|
+
|
|
276
|
+
const createTransaction = useCallback(async (data: any) => {
|
|
277
|
+
try {
|
|
278
|
+
setError(null);
|
|
279
|
+
return await client.createTransaction(data);
|
|
280
|
+
} catch (err) {
|
|
281
|
+
setError(err as Error);
|
|
282
|
+
throw err;
|
|
283
|
+
}
|
|
284
|
+
}, []);
|
|
285
|
+
|
|
286
|
+
const getTransactions = useCallback(async (filters?: any) => {
|
|
287
|
+
if (!customerId || !customerEmail) {
|
|
288
|
+
throw new Error('Customer context not set');
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
setError(null);
|
|
292
|
+
return await client.getTransactions(customerId, customerEmail, filters);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
setError(err as Error);
|
|
295
|
+
throw err;
|
|
296
|
+
}
|
|
297
|
+
}, [customerId, customerEmail]);
|
|
298
|
+
|
|
299
|
+
const getTransaction = useCallback(async (id: string) => {
|
|
300
|
+
try {
|
|
301
|
+
setError(null);
|
|
302
|
+
return await client.getTransaction(id);
|
|
303
|
+
} catch (err) {
|
|
304
|
+
setError(err as Error);
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
}, []);
|
|
308
|
+
|
|
309
|
+
const getPayees = useCallback(async () => {
|
|
310
|
+
if (!customerId || !customerEmail) {
|
|
311
|
+
throw new Error('Customer context not set');
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
setError(null);
|
|
315
|
+
return await client.getPayees(customerId, customerEmail);
|
|
316
|
+
} catch (err) {
|
|
317
|
+
setError(err as Error);
|
|
318
|
+
throw err;
|
|
319
|
+
}
|
|
320
|
+
}, [customerId, customerEmail]);
|
|
321
|
+
|
|
322
|
+
const createPayee = useCallback(async (data: any) => {
|
|
323
|
+
try {
|
|
324
|
+
setError(null);
|
|
325
|
+
return await client.createPayee(data);
|
|
326
|
+
} catch (err) {
|
|
327
|
+
setError(err as Error);
|
|
328
|
+
throw err;
|
|
329
|
+
}
|
|
330
|
+
}, []);
|
|
331
|
+
|
|
332
|
+
const deletePayee = useCallback(async (id: string) => {
|
|
333
|
+
if (!customerId || !customerEmail) {
|
|
334
|
+
throw new Error('Customer context not set');
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
setError(null);
|
|
338
|
+
await client.deletePayee(id, customerId, customerEmail);
|
|
339
|
+
} catch (err) {
|
|
340
|
+
setError(err as Error);
|
|
341
|
+
throw err;
|
|
342
|
+
}
|
|
343
|
+
}, [customerId, customerEmail]);
|
|
344
|
+
|
|
345
|
+
{{#if (includes features "fees")}}
|
|
346
|
+
const calculateFees = useCallback(async (
|
|
347
|
+
amount: number,
|
|
348
|
+
type: 'onramp' | 'offramp',
|
|
349
|
+
currency: string = 'USD'
|
|
350
|
+
) => {
|
|
351
|
+
try {
|
|
352
|
+
setError(null);
|
|
353
|
+
return await client.calculateFees({ amount, type, currency });
|
|
354
|
+
} catch (err) {
|
|
355
|
+
setError(err as Error);
|
|
356
|
+
throw err;
|
|
357
|
+
}
|
|
358
|
+
}, []);
|
|
359
|
+
{{/if}}
|
|
360
|
+
|
|
361
|
+
{{#if (includes features "realtime")}}
|
|
362
|
+
const subscribeToTransaction = useCallback((transactionId: string) => {
|
|
363
|
+
socket?.emit('subscribe:transaction', transactionId);
|
|
364
|
+
}, [socket]);
|
|
365
|
+
|
|
366
|
+
const unsubscribeFromTransaction = useCallback((transactionId: string) => {
|
|
367
|
+
socket?.emit('unsubscribe:transaction', transactionId);
|
|
368
|
+
}, [socket]);
|
|
369
|
+
{{/if}}
|
|
370
|
+
|
|
371
|
+
const value: DiviswapContextValue = {
|
|
372
|
+
customerId,
|
|
373
|
+
customerEmail,
|
|
374
|
+
loading,
|
|
375
|
+
error,
|
|
376
|
+
setCustomer,
|
|
377
|
+
clearCustomer,
|
|
378
|
+
getCustomerStatus,
|
|
379
|
+
createTransaction,
|
|
380
|
+
getTransactions,
|
|
381
|
+
getTransaction,
|
|
382
|
+
getPayees,
|
|
383
|
+
createPayee,
|
|
384
|
+
deletePayee,
|
|
385
|
+
{{#if (includes features "fees")}}
|
|
386
|
+
calculateFees,
|
|
387
|
+
{{/if}}
|
|
388
|
+
{{#if (includes features "realtime")}}
|
|
389
|
+
socket,
|
|
390
|
+
subscribeToTransaction,
|
|
391
|
+
unsubscribeFromTransaction,
|
|
392
|
+
{{/if}}
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
return (
|
|
396
|
+
<DiviswapContext.Provider value={value}>
|
|
397
|
+
{children}
|
|
398
|
+
</DiviswapContext.Provider>
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function useDiviswap() {
|
|
403
|
+
const context = useContext(DiviswapContext);
|
|
404
|
+
if (!context) {
|
|
405
|
+
throw new Error('useDiviswap must be used within a DiviswapProvider');
|
|
406
|
+
}
|
|
407
|
+
return context;
|
|
408
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add this to your root layout.tsx to enable Diviswap functionality
|
|
3
|
+
*
|
|
4
|
+
* Example:
|
|
5
|
+
*
|
|
6
|
+
* import { DiviswapProvider } from '@diviswap/sdk/react';
|
|
7
|
+
*
|
|
8
|
+
* export default function RootLayout({
|
|
9
|
+
* children,
|
|
10
|
+
* }: {
|
|
11
|
+
* children: React.ReactNode;
|
|
12
|
+
* }) {
|
|
13
|
+
* return (
|
|
14
|
+
* <html lang="en">
|
|
15
|
+
* <body>
|
|
16
|
+
* <DiviswapProvider>
|
|
17
|
+
* {children}
|
|
18
|
+
* </DiviswapProvider>
|
|
19
|
+
* </body>
|
|
20
|
+
* </html>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// This file is for reference only - please add the provider to your root layout
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
export interface User {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
firstName?: string;
|
|
5
|
+
lastName?: string;
|
|
6
|
+
accessToken?: string;
|
|
7
|
+
createdAt?: string;
|
|
8
|
+
updatedAt?: string;
|
|
9
|
+
kycStatus?: 'pending' | 'approved' | 'rejected';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Payee {
|
|
13
|
+
id: string;
|
|
14
|
+
nickname: string;
|
|
15
|
+
network: string;
|
|
16
|
+
address: string;
|
|
17
|
+
type: 'crypto' | 'bank';
|
|
18
|
+
isDefault?: boolean;
|
|
19
|
+
createdAt?: string;
|
|
20
|
+
updatedAt?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type TransactionStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled';
|
|
24
|
+
export type TransactionType = 'onramp' | 'offramp';
|
|
25
|
+
|
|
26
|
+
export interface Transaction {
|
|
27
|
+
id: string;
|
|
28
|
+
type: TransactionType;
|
|
29
|
+
status: TransactionStatus;
|
|
30
|
+
amount: number;
|
|
31
|
+
currency: string;
|
|
32
|
+
payeeId?: string;
|
|
33
|
+
paymentMethodId?: string;
|
|
34
|
+
fees?: TransactionFees;
|
|
35
|
+
metadata?: Record<string, any>;
|
|
36
|
+
createdAt: string;
|
|
37
|
+
updatedAt: string;
|
|
38
|
+
completedAt?: string;
|
|
39
|
+
failureReason?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface TransactionFees {
|
|
43
|
+
baseFee: number;
|
|
44
|
+
networkFee: number;
|
|
45
|
+
integratorFee?: number;
|
|
46
|
+
totalFee: number;
|
|
47
|
+
currency: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface PaymentMethod {
|
|
51
|
+
id: string;
|
|
52
|
+
type: 'bank_account' | 'debit_card' | 'credit_card' | 'wire_transfer';
|
|
53
|
+
last4?: string;
|
|
54
|
+
bankName?: string;
|
|
55
|
+
isDefault?: boolean;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
{{#if (includes features "fees")}}
|
|
60
|
+
export interface IntegratorFee {
|
|
61
|
+
id: string;
|
|
62
|
+
type: 'percentage' | 'flat';
|
|
63
|
+
value: number;
|
|
64
|
+
transactionType: TransactionType;
|
|
65
|
+
minAmount?: number;
|
|
66
|
+
maxAmount?: number;
|
|
67
|
+
currency?: string;
|
|
68
|
+
isActive: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface FeeCalculation {
|
|
72
|
+
baseFee: number;
|
|
73
|
+
networkFee: number;
|
|
74
|
+
integratorFee?: number;
|
|
75
|
+
totalFee: number;
|
|
76
|
+
finalAmount: number;
|
|
77
|
+
exchangeRate?: number;
|
|
78
|
+
currency: string;
|
|
79
|
+
}
|
|
80
|
+
{{/if}}
|
|
81
|
+
|
|
82
|
+
{{#if (includes features "webhooks")}}
|
|
83
|
+
export interface WebhookEvent {
|
|
84
|
+
id: string;
|
|
85
|
+
type: 'transaction.created' | 'transaction.updated' | 'transaction.completed' | 'transaction.failed' | 'payee.created' | 'payee.deleted';
|
|
86
|
+
data: any;
|
|
87
|
+
timestamp: string;
|
|
88
|
+
}
|
|
89
|
+
{{/if}}
|
|
90
|
+
|
|
91
|
+
{{#if (includes features "realtime")}}
|
|
92
|
+
export interface RealtimeEvent {
|
|
93
|
+
type: 'transaction:update' | 'transaction:status' | 'fee:update';
|
|
94
|
+
transactionId?: string;
|
|
95
|
+
data: any;
|
|
96
|
+
timestamp: string;
|
|
97
|
+
}
|
|
98
|
+
{{/if}}
|
|
99
|
+
|
|
100
|
+
// API Response Types
|
|
101
|
+
export interface ApiResponse<T = any> {
|
|
102
|
+
success: boolean;
|
|
103
|
+
data?: T;
|
|
104
|
+
error?: string;
|
|
105
|
+
message?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface PaginatedResponse<T> {
|
|
109
|
+
items: T[];
|
|
110
|
+
total: number;
|
|
111
|
+
limit: number;
|
|
112
|
+
offset: number;
|
|
113
|
+
hasMore: boolean;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Form Input Types
|
|
117
|
+
export interface LoginCredentials {
|
|
118
|
+
email: string;
|
|
119
|
+
password: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface RegistrationData {
|
|
123
|
+
email: string;
|
|
124
|
+
password: string;
|
|
125
|
+
firstName: string;
|
|
126
|
+
lastName: string;
|
|
127
|
+
individual: {
|
|
128
|
+
firstName: string;
|
|
129
|
+
lastName: string;
|
|
130
|
+
dateOfBirth: string;
|
|
131
|
+
address: {
|
|
132
|
+
street1: string;
|
|
133
|
+
street2?: string;
|
|
134
|
+
city: string;
|
|
135
|
+
state: string;
|
|
136
|
+
postalCode: string;
|
|
137
|
+
country: string;
|
|
138
|
+
};
|
|
139
|
+
ssn?: string;
|
|
140
|
+
phone?: string;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface CreatePayeeData {
|
|
145
|
+
nickname: string;
|
|
146
|
+
network: string;
|
|
147
|
+
address: string;
|
|
148
|
+
type: 'crypto' | 'bank';
|
|
149
|
+
metadata?: Record<string, any>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface CreateTransactionData {
|
|
153
|
+
type: TransactionType;
|
|
154
|
+
amount: number;
|
|
155
|
+
currency?: string;
|
|
156
|
+
payeeId?: string;
|
|
157
|
+
paymentMethodId?: string;
|
|
158
|
+
metadata?: Record<string, any>;
|
|
159
|
+
}
|