@one_deploy/sdk 1.0.0

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 (83) hide show
  1. package/.turbo/turbo-build.log +0 -0
  2. package/.turbo/turbo-type-check.log +0 -0
  3. package/dist/config/index.d.mts +74 -0
  4. package/dist/config/index.d.ts +74 -0
  5. package/dist/config/index.js +242 -0
  6. package/dist/config/index.js.map +1 -0
  7. package/dist/config/index.mjs +224 -0
  8. package/dist/config/index.mjs.map +1 -0
  9. package/dist/engine-5ndtBaCr.d.ts +1039 -0
  10. package/dist/engine-CrlhH0nw.d.mts +1039 -0
  11. package/dist/hooks/index.d.mts +56 -0
  12. package/dist/hooks/index.d.ts +56 -0
  13. package/dist/hooks/index.js +1360 -0
  14. package/dist/hooks/index.js.map +1 -0
  15. package/dist/hooks/index.mjs +1356 -0
  16. package/dist/hooks/index.mjs.map +1 -0
  17. package/dist/index.d.mts +356 -0
  18. package/dist/index.d.ts +356 -0
  19. package/dist/index.js +5068 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/index.mjs +4949 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/price-CgqXPnT3.d.ts +13 -0
  24. package/dist/price-ClbLHHjv.d.mts +13 -0
  25. package/dist/providers/index.d.mts +121 -0
  26. package/dist/providers/index.d.ts +121 -0
  27. package/dist/providers/index.js +1642 -0
  28. package/dist/providers/index.js.map +1 -0
  29. package/dist/providers/index.mjs +1600 -0
  30. package/dist/providers/index.mjs.map +1 -0
  31. package/dist/react-native.d.mts +120 -0
  32. package/dist/react-native.d.ts +120 -0
  33. package/dist/react-native.js +1792 -0
  34. package/dist/react-native.js.map +1 -0
  35. package/dist/react-native.mjs +1755 -0
  36. package/dist/react-native.mjs.map +1 -0
  37. package/dist/services/index.d.mts +85 -0
  38. package/dist/services/index.d.ts +85 -0
  39. package/dist/services/index.js +1466 -0
  40. package/dist/services/index.js.map +1 -0
  41. package/dist/services/index.mjs +1458 -0
  42. package/dist/services/index.mjs.map +1 -0
  43. package/dist/types/index.d.mts +759 -0
  44. package/dist/types/index.d.ts +759 -0
  45. package/dist/types/index.js +4 -0
  46. package/dist/types/index.js.map +1 -0
  47. package/dist/types/index.mjs +3 -0
  48. package/dist/types/index.mjs.map +1 -0
  49. package/dist/utils/index.d.mts +36 -0
  50. package/dist/utils/index.d.ts +36 -0
  51. package/dist/utils/index.js +164 -0
  52. package/dist/utils/index.js.map +1 -0
  53. package/dist/utils/index.mjs +142 -0
  54. package/dist/utils/index.mjs.map +1 -0
  55. package/package.json +101 -0
  56. package/src/components/OneConnectButton.tsx +143 -0
  57. package/src/components/OneNFTGallery.tsx +324 -0
  58. package/src/components/OneOfframpWidget.tsx +660 -0
  59. package/src/components/OneOnrampWidget.tsx +596 -0
  60. package/src/components/OnePayWidget.tsx +160 -0
  61. package/src/components/OneReceiveWidget.tsx +272 -0
  62. package/src/components/OneSendWidget.tsx +248 -0
  63. package/src/components/OneSwapWidget.tsx +715 -0
  64. package/src/components/OneTransactionButton.tsx +150 -0
  65. package/src/components/OneWalletBalance.tsx +354 -0
  66. package/src/components/index.ts +24 -0
  67. package/src/config/index.ts +299 -0
  68. package/src/hooks/index.ts +2 -0
  69. package/src/hooks/useTokenPrice.ts +162 -0
  70. package/src/hooks/useWalletBalance.ts +98 -0
  71. package/src/index.ts +193 -0
  72. package/src/providers/OneProvider.tsx +452 -0
  73. package/src/providers/ThirdwebProvider.tsx +203 -0
  74. package/src/providers/index.ts +26 -0
  75. package/src/react-native.ts +378 -0
  76. package/src/services/engine.ts +1854 -0
  77. package/src/services/index.ts +30 -0
  78. package/src/services/price.ts +164 -0
  79. package/src/services/supabase.ts +180 -0
  80. package/src/types/index.ts +887 -0
  81. package/src/utils/index.ts +200 -0
  82. package/tsconfig.json +22 -0
  83. package/tsup.config.ts +25 -0
@@ -0,0 +1,1854 @@
1
+ /**
2
+ * ONE Engine Client - The unified API gateway for all ONE Ecosystem services
3
+ *
4
+ * All wallet operations, onramp, swap, trading go through ONE Engine.
5
+ * Thirdweb/Onramper/etc are internal to ONE Engine and hidden from clients.
6
+ */
7
+
8
+ import { getConfig } from '../config';
9
+ import type {
10
+ ApiResponse,
11
+ User,
12
+ Token,
13
+ WalletBalance,
14
+ Transaction,
15
+ AIStrategy,
16
+ AIOrder,
17
+ AIOrderStatus,
18
+ AITradeExecution,
19
+ AITradeAllocation,
20
+ AINavSnapshot,
21
+ AIPortfolioSummary,
22
+ AIRedemptionResult,
23
+ AIMarketData,
24
+ CreateAIOrderRequest,
25
+ StrategyCategory,
26
+ NFT,
27
+ NFTCollection,
28
+ Contract,
29
+ ContractReadParams,
30
+ ContractWriteParams,
31
+ ContractDeployParams,
32
+ BillProvider,
33
+ BillPayment,
34
+ OfframpQuote,
35
+ OfframpRequest,
36
+ OfframpTransaction,
37
+ StakingPool,
38
+ StakingPosition,
39
+ ReferralInfo,
40
+ Referral,
41
+ UserProfile,
42
+ UserSettings,
43
+ Notification,
44
+ BridgeQuote,
45
+ BridgeTransaction,
46
+ GasEstimate,
47
+ GasPrice,
48
+ WalletImportRequest,
49
+ PortfolioAnalytics,
50
+ LimitOrder,
51
+ TradingCondition,
52
+ Webhook,
53
+ WebhookDelivery,
54
+ CreateWebhookInput,
55
+ UpdateWebhookInput,
56
+ AdminUser,
57
+ AdminProject,
58
+ SystemStats,
59
+ PaginatedResult,
60
+ AdminListOptions,
61
+ SystemLog,
62
+ RateLimitInfo,
63
+ } from '../types';
64
+
65
+ // ===== Auth Types =====
66
+ export interface EngineAuthResponse {
67
+ user: User;
68
+ accessToken: string;
69
+ refreshToken?: string;
70
+ expiresIn: number;
71
+ }
72
+
73
+ // ===== Wallet Types =====
74
+ export interface EngineWalletBalance {
75
+ address: string;
76
+ totalUsd: number;
77
+ change24h: number;
78
+ changePercent24h: number;
79
+ tokens: Token[];
80
+ }
81
+
82
+ export interface EngineTransactionRequest {
83
+ to: string;
84
+ amount: string;
85
+ tokenSymbol: string;
86
+ chainId: number;
87
+ memo?: string;
88
+ }
89
+
90
+ export interface EngineTransactionResponse {
91
+ txId: string;
92
+ status: 'queued' | 'pending' | 'confirmed' | 'failed';
93
+ txHash?: string;
94
+ explorerUrl?: string;
95
+ }
96
+
97
+ // ===== Onramp Types =====
98
+ export interface OnrampSessionRequest {
99
+ walletAddress: string;
100
+ fiatCurrency?: string;
101
+ fiatAmount?: number;
102
+ cryptoCurrency?: string;
103
+ cryptoNetwork?: string;
104
+ paymentMethod?: string;
105
+ redirectUrl?: string;
106
+ }
107
+
108
+ export interface OnrampSession {
109
+ sessionId: string;
110
+ widgetUrl: string;
111
+ expiresAt: string;
112
+ }
113
+
114
+ export interface OnrampQuote {
115
+ provider: string;
116
+ fiatCurrency: string;
117
+ fiatAmount: number;
118
+ cryptoCurrency: string;
119
+ cryptoAmount: number;
120
+ rate: number;
121
+ fees: {
122
+ network: number;
123
+ provider: number;
124
+ total: number;
125
+ };
126
+ paymentMethod: string;
127
+ estimatedTime: string;
128
+ }
129
+
130
+ export interface OnrampTransaction {
131
+ id: string;
132
+ sessionId: string;
133
+ status: 'pending' | 'processing' | 'completed' | 'failed' | 'expired';
134
+ fiatAmount: number;
135
+ fiatCurrency: string;
136
+ cryptoAmount?: number;
137
+ cryptoCurrency: string;
138
+ walletAddress: string;
139
+ txHash?: string;
140
+ createdAt: string;
141
+ completedAt?: string;
142
+ }
143
+
144
+ // ===== Swap Types =====
145
+ export interface SwapQuoteRequest {
146
+ fromToken: string;
147
+ fromAmount: string;
148
+ fromChainId: number;
149
+ toToken: string;
150
+ toChainId: number;
151
+ walletAddress: string;
152
+ slippage?: number;
153
+ }
154
+
155
+ export interface SwapQuote {
156
+ quoteId: string;
157
+ fromToken: string;
158
+ fromAmount: string;
159
+ fromChainId: number;
160
+ toToken: string;
161
+ toAmount: string;
162
+ toChainId: number;
163
+ rate: number;
164
+ priceImpact: number;
165
+ estimatedGas: string;
166
+ estimatedTime: string;
167
+ fees: {
168
+ gas: number;
169
+ protocol: number;
170
+ total: number;
171
+ };
172
+ expiresAt: string;
173
+ }
174
+
175
+ export interface SwapExecuteRequest {
176
+ quoteId: string;
177
+ walletAddress: string;
178
+ signature?: string; // For backend wallets
179
+ }
180
+
181
+ export interface SwapResult {
182
+ swapId: string;
183
+ status: 'pending' | 'confirming' | 'completed' | 'failed';
184
+ txHash?: string;
185
+ fromAmount: string;
186
+ toAmount?: string;
187
+ }
188
+
189
+ // ===== Main Client =====
190
+ export class OneEngineClient {
191
+ private baseUrl: string;
192
+ private clientId: string;
193
+ private secretKey?: string;
194
+ private accessToken?: string;
195
+
196
+ constructor(options?: {
197
+ baseUrl?: string;
198
+ clientId?: string;
199
+ secretKey?: string;
200
+ }) {
201
+ const config = getConfig();
202
+ this.baseUrl = options?.baseUrl || config.oneEngineUrl;
203
+ this.clientId = options?.clientId || config.oneClientId || '';
204
+ this.secretKey = options?.secretKey || config.oneSecretKey;
205
+ }
206
+
207
+ /**
208
+ * Set access token for authenticated requests
209
+ */
210
+ setAccessToken(token: string) {
211
+ this.accessToken = token;
212
+ }
213
+
214
+ /**
215
+ * Clear access token
216
+ */
217
+ clearAccessToken() {
218
+ this.accessToken = undefined;
219
+ }
220
+
221
+ private getHeaders(includeSecret = false): Record<string, string> {
222
+ const headers: Record<string, string> = {
223
+ 'Content-Type': 'application/json',
224
+ 'x-client-id': this.clientId,
225
+ };
226
+
227
+ if (this.accessToken) {
228
+ headers['Authorization'] = `Bearer ${this.accessToken}`;
229
+ }
230
+
231
+ if (includeSecret && this.secretKey) {
232
+ headers['x-secret-key'] = this.secretKey;
233
+ }
234
+
235
+ return headers;
236
+ }
237
+
238
+ private async request<T>(
239
+ endpoint: string,
240
+ options: RequestInit = {},
241
+ includeSecret = false
242
+ ): Promise<ApiResponse<T>> {
243
+ try {
244
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
245
+ ...options,
246
+ headers: {
247
+ ...this.getHeaders(includeSecret),
248
+ ...options.headers,
249
+ },
250
+ });
251
+
252
+ const data = await response.json();
253
+
254
+ if (!response.ok) {
255
+ return {
256
+ success: false,
257
+ error: {
258
+ code: data.error?.code || `HTTP_${response.status}`,
259
+ message: data.error?.message || 'Request failed',
260
+ },
261
+ };
262
+ }
263
+
264
+ return {
265
+ success: true,
266
+ data: data.data || data,
267
+ };
268
+ } catch (error) {
269
+ return {
270
+ success: false,
271
+ error: {
272
+ code: 'NETWORK_ERROR',
273
+ message: error instanceof Error ? error.message : 'Network request failed',
274
+ },
275
+ };
276
+ }
277
+ }
278
+
279
+ // ===============================
280
+ // AUTH ENDPOINTS
281
+ // ===============================
282
+
283
+ /**
284
+ * Send OTP to email for authentication
285
+ */
286
+ async sendEmailOtp(email: string): Promise<ApiResponse<{ message: string }>> {
287
+ return this.request('/api/v1/auth/otp', {
288
+ method: 'POST',
289
+ body: JSON.stringify({ email }),
290
+ });
291
+ }
292
+
293
+ /**
294
+ * Verify OTP and get access token
295
+ */
296
+ async verifyEmailOtp(email: string, otp: string): Promise<ApiResponse<EngineAuthResponse>> {
297
+ return this.request('/api/v1/auth/otp/verify', {
298
+ method: 'POST',
299
+ body: JSON.stringify({ email, otp }),
300
+ });
301
+ }
302
+
303
+ /**
304
+ * Authenticate with wallet signature
305
+ */
306
+ async authWithWallet(
307
+ walletAddress: string,
308
+ signature: string,
309
+ message: string
310
+ ): Promise<ApiResponse<EngineAuthResponse>> {
311
+ return this.request('/api/v1/auth/wallet', {
312
+ method: 'POST',
313
+ body: JSON.stringify({ walletAddress, signature, message }),
314
+ });
315
+ }
316
+
317
+ /**
318
+ * Refresh access token
319
+ */
320
+ async refreshToken(refreshToken: string): Promise<ApiResponse<EngineAuthResponse>> {
321
+ return this.request('/api/v1/auth/refresh', {
322
+ method: 'POST',
323
+ body: JSON.stringify({ refreshToken }),
324
+ });
325
+ }
326
+
327
+ /**
328
+ * Get current user
329
+ */
330
+ async getCurrentUser(): Promise<ApiResponse<User>> {
331
+ return this.request('/api/v1/auth/me', { method: 'GET' });
332
+ }
333
+
334
+ /**
335
+ * Sign out
336
+ */
337
+ async signOut(): Promise<ApiResponse<{ success: boolean }>> {
338
+ return this.request('/api/v1/auth/logout', { method: 'POST' });
339
+ }
340
+
341
+ // ===============================
342
+ // WALLET/ASSETS ENDPOINTS
343
+ // ===============================
344
+
345
+ /**
346
+ * Get wallet balance across all chains
347
+ */
348
+ async getWalletBalance(
349
+ walletAddress: string,
350
+ chains?: number[]
351
+ ): Promise<ApiResponse<EngineWalletBalance>> {
352
+ const params = new URLSearchParams({ address: walletAddress });
353
+ if (chains?.length && chains.length > 0) {
354
+ params.set('chainId', chains[0].toString()); // Engine expects single chainId
355
+ }
356
+ return this.request(`/api/v1/assets?${params}`, { method: 'GET' });
357
+ }
358
+
359
+ /**
360
+ * Get portfolio summary
361
+ */
362
+ async getPortfolioSummary(
363
+ walletAddress: string
364
+ ): Promise<ApiResponse<{ totalValue: number; change24h: number; tokens: Token[] }>> {
365
+ const params = new URLSearchParams({ address: walletAddress });
366
+ return this.request(`/api/v1/assets/portfolio?${params}`, { method: 'GET' });
367
+ }
368
+
369
+ /**
370
+ * Get user's wallets
371
+ */
372
+ async getUserWallets(
373
+ chainId?: number
374
+ ): Promise<ApiResponse<{ wallets: any[]; total: number }>> {
375
+ const params = chainId ? `?chainId=${chainId}` : '';
376
+ return this.request(`/api/v1/wallet${params}`, { method: 'GET' });
377
+ }
378
+
379
+ /**
380
+ * Create a new wallet
381
+ */
382
+ async createWallet(
383
+ chainId: number = 8453,
384
+ type: 'smart' | 'eoa' | 'multisig' = 'smart'
385
+ ): Promise<ApiResponse<{ wallet: any; smartAccountAddress: string; personalAddress: string }>> {
386
+ return this.request('/api/v1/wallet', {
387
+ method: 'POST',
388
+ body: JSON.stringify({ chainId, type }),
389
+ });
390
+ }
391
+
392
+ /**
393
+ * Get wallet transactions (placeholder - needs endpoint)
394
+ */
395
+ async getWalletTransactions(
396
+ walletAddress: string,
397
+ options?: { limit?: number; offset?: number; chainId?: number }
398
+ ): Promise<ApiResponse<{ transactions: Transaction[]; total: number }>> {
399
+ const params = new URLSearchParams({ address: walletAddress });
400
+ if (options?.limit) params.set('limit', options.limit.toString());
401
+ if (options?.offset) params.set('offset', options.offset.toString());
402
+ if (options?.chainId) params.set('chainId', options.chainId.toString());
403
+ return this.request(`/api/v1/assets/transactions?${params}`, { method: 'GET' });
404
+ }
405
+
406
+ /**
407
+ * Send native token or ERC20
408
+ */
409
+ async sendTransaction(
410
+ request: EngineTransactionRequest
411
+ ): Promise<ApiResponse<EngineTransactionResponse>> {
412
+ return this.request('/api/v1/wallet/send', {
413
+ method: 'POST',
414
+ body: JSON.stringify(request),
415
+ });
416
+ }
417
+
418
+ /**
419
+ * Get transaction status
420
+ */
421
+ async getTransactionStatus(txId: string): Promise<ApiResponse<EngineTransactionResponse>> {
422
+ return this.request(`/api/v1/wallet/transaction/${txId}`, { method: 'GET' });
423
+ }
424
+
425
+ // ===============================
426
+ // ONRAMP ENDPOINTS (Fiat-to-Crypto)
427
+ // ===============================
428
+
429
+ /**
430
+ * Get onramp quote
431
+ */
432
+ async getOnrampQuote(
433
+ fiatCurrency: string,
434
+ fiatAmount: number,
435
+ cryptoCurrency: string,
436
+ paymentMethod?: string
437
+ ): Promise<ApiResponse<OnrampQuote[]>> {
438
+ const params = new URLSearchParams({
439
+ fiatCurrency,
440
+ fiatAmount: fiatAmount.toString(),
441
+ cryptoCurrency,
442
+ });
443
+ if (paymentMethod) params.set('paymentMethod', paymentMethod);
444
+ return this.request(`/api/v1/fiat/onramp/quote?${params}`, { method: 'GET' });
445
+ }
446
+
447
+ /**
448
+ * Create onramp session (returns widget URL)
449
+ */
450
+ async createOnrampSession(
451
+ request: OnrampSessionRequest
452
+ ): Promise<ApiResponse<OnrampSession>> {
453
+ return this.request('/api/v1/fiat/onramp', {
454
+ method: 'POST',
455
+ body: JSON.stringify({
456
+ fiatCurrency: request.fiatCurrency || 'USD',
457
+ fiatAmount: request.fiatAmount || 100,
458
+ cryptoCurrency: request.cryptoCurrency || 'ETH',
459
+ walletAddress: request.walletAddress,
460
+ chainId: 8453, // Default to Base
461
+ }),
462
+ });
463
+ }
464
+
465
+ /**
466
+ * Get onramp session status
467
+ */
468
+ async getOnrampStatus(sessionId: string): Promise<ApiResponse<OnrampTransaction>> {
469
+ return this.request(`/api/v1/fiat/onramp/${sessionId}`, { method: 'GET' });
470
+ }
471
+
472
+ /**
473
+ * Get supported currencies (fiat + crypto)
474
+ */
475
+ async getSupportedCurrencies(): Promise<ApiResponse<{ fiatCurrencies: string[]; cryptoCurrencies: string[] }>> {
476
+ return this.request('/api/v1/fiat/onramp', { method: 'GET' });
477
+ }
478
+
479
+ /**
480
+ * Get supported fiat currencies
481
+ */
482
+ async getSupportedFiatCurrencies(): Promise<ApiResponse<string[]>> {
483
+ const result = await this.getSupportedCurrencies();
484
+ if (result.success && result.data) {
485
+ return { success: true, data: result.data.fiatCurrencies };
486
+ }
487
+ return { success: false, error: result.error };
488
+ }
489
+
490
+ /**
491
+ * Get supported payment methods
492
+ */
493
+ async getSupportedPaymentMethods(country?: string): Promise<ApiResponse<string[]>> {
494
+ // Placeholder - engine doesn't have this endpoint yet
495
+ return { success: true, data: ['card', 'bank_transfer', 'apple_pay', 'google_pay'] };
496
+ }
497
+
498
+ // ===============================
499
+ // SWAP ENDPOINTS
500
+ // ===============================
501
+
502
+ /**
503
+ * Get swap quote
504
+ */
505
+ async getSwapQuote(request: SwapQuoteRequest): Promise<ApiResponse<SwapQuote>> {
506
+ return this.request('/api/v1/swap/quote', {
507
+ method: 'POST',
508
+ body: JSON.stringify(request),
509
+ });
510
+ }
511
+
512
+ /**
513
+ * Execute swap
514
+ */
515
+ async executeSwap(request: SwapExecuteRequest): Promise<ApiResponse<SwapResult>> {
516
+ return this.request('/api/v1/swap/execute', {
517
+ method: 'POST',
518
+ body: JSON.stringify(request),
519
+ });
520
+ }
521
+
522
+ /**
523
+ * Get swap status
524
+ */
525
+ async getSwapStatus(swapId: string): Promise<ApiResponse<SwapResult>> {
526
+ return this.request(`/api/v1/swap/${swapId}`, { method: 'GET' });
527
+ }
528
+
529
+ /**
530
+ * Get supported tokens for swap
531
+ */
532
+ async getSupportedSwapTokens(chainId?: number): Promise<ApiResponse<{ tokens: Token[] }>> {
533
+ const params = chainId ? `?chainId=${chainId}` : '';
534
+ return this.request(`/api/v1/swap/tokens${params}`, { method: 'GET' });
535
+ }
536
+
537
+ /**
538
+ * Get supported chains for swap
539
+ */
540
+ async getSupportedSwapChains(): Promise<ApiResponse<{ chains: { id: number; name: string }[] }>> {
541
+ return this.request('/api/v1/swap/chains', { method: 'GET' });
542
+ }
543
+
544
+ // ===============================
545
+ // AI TRADING/QUANT ENDPOINTS
546
+ // ===============================
547
+
548
+ /**
549
+ * Get available AI trading strategies
550
+ */
551
+ async getStrategies(): Promise<ApiResponse<AIStrategy[]>> {
552
+ return this.request('/api/v1/quant/strategies', { method: 'GET' });
553
+ }
554
+
555
+ /**
556
+ * Get strategy details
557
+ */
558
+ async getStrategy(strategyId: string): Promise<ApiResponse<AIStrategy>> {
559
+ return this.request(`/api/v1/quant/strategies/${strategyId}`, { method: 'GET' });
560
+ }
561
+
562
+ /**
563
+ * Get user's positions
564
+ */
565
+ async getPositions(): Promise<ApiResponse<any[]>> {
566
+ return this.request('/api/v1/quant/positions', { method: 'GET' });
567
+ }
568
+
569
+ /**
570
+ * Create investment order
571
+ */
572
+ async createOrder(
573
+ strategyId: string,
574
+ amount: number,
575
+ currency: string
576
+ ): Promise<ApiResponse<AIOrder>> {
577
+ return this.request('/api/v1/trading/orders', {
578
+ method: 'POST',
579
+ body: JSON.stringify({ strategyId, amount, currency }),
580
+ });
581
+ }
582
+
583
+ /**
584
+ * Get user's orders
585
+ */
586
+ async getUserOrders(): Promise<ApiResponse<AIOrder[]>> {
587
+ return this.request('/api/v1/trading/orders', { method: 'GET' });
588
+ }
589
+
590
+ /**
591
+ * Get user's portfolio stats from positions
592
+ */
593
+ async getPortfolioStats(): Promise<ApiResponse<{
594
+ totalInvested: number;
595
+ totalValue: number;
596
+ totalPnl: number;
597
+ totalPnlPercent: number;
598
+ activePositions: number;
599
+ }>> {
600
+ // Derive from positions
601
+ const positionsResult = await this.getPositions();
602
+ if (positionsResult.success && positionsResult.data) {
603
+ const positions = positionsResult.data;
604
+ const totalInvested = positions.reduce((sum, p) => sum + (p.investedAmount || 0), 0);
605
+ const totalValue = positions.reduce((sum, p) => sum + (p.currentValue || 0), 0);
606
+ const totalPnl = totalValue - totalInvested;
607
+ const totalPnlPercent = totalInvested > 0 ? (totalPnl / totalInvested) * 100 : 0;
608
+ return {
609
+ success: true,
610
+ data: {
611
+ totalInvested,
612
+ totalValue,
613
+ totalPnl,
614
+ totalPnlPercent,
615
+ activePositions: positions.filter((p: any) => p.status === 'active').length,
616
+ },
617
+ };
618
+ }
619
+ return {
620
+ success: true,
621
+ data: { totalInvested: 0, totalValue: 0, totalPnl: 0, totalPnlPercent: 0, activePositions: 0 },
622
+ };
623
+ }
624
+
625
+ // ===============================
626
+ // MARKET/PRICE ENDPOINTS
627
+ // ===============================
628
+
629
+ /**
630
+ * Get token prices
631
+ */
632
+ async getTokenPrices(symbols: string[]): Promise<ApiResponse<Record<string, {
633
+ price: number;
634
+ change24h: number;
635
+ marketCap?: number;
636
+ }>>> {
637
+ // Convert symbols to Bybit format (add USDT suffix if needed)
638
+ const bybitSymbols = symbols.map(s => {
639
+ const upper = s.toUpperCase();
640
+ if (upper.endsWith('USDT')) return upper;
641
+ return `${upper}USDT`;
642
+ });
643
+
644
+ const result = await this.request<{ markets: any[] }>(
645
+ `/api/v1/trading/market?symbols=${bybitSymbols.join(',')}`,
646
+ { method: 'GET' }
647
+ );
648
+
649
+ if (result.success && result.data?.markets) {
650
+ const prices: Record<string, { price: number; change24h: number; marketCap?: number }> = {};
651
+ for (const market of result.data.markets) {
652
+ const symbol = market.symbol?.replace('USDT', '') || '';
653
+ prices[symbol] = {
654
+ price: parseFloat(market.lastPrice) || 0,
655
+ change24h: parseFloat(market.price24hPcnt) * 100 || 0,
656
+ marketCap: undefined, // Bybit doesn't provide this
657
+ };
658
+ }
659
+ return { success: true, data: prices };
660
+ }
661
+ return { success: false, error: result.error };
662
+ }
663
+
664
+ /**
665
+ * Get market data overview
666
+ */
667
+ async getMarketData(): Promise<ApiResponse<{
668
+ totalMarketCap: number;
669
+ totalVolume24h: number;
670
+ btcDominance: number;
671
+ markets: any[];
672
+ }>> {
673
+ const result = await this.request<{ markets: any[] }>('/api/v1/trading/market', { method: 'GET' });
674
+ if (result.success && result.data?.markets) {
675
+ return {
676
+ success: true,
677
+ data: {
678
+ totalMarketCap: 0, // Would need separate API
679
+ totalVolume24h: result.data.markets.reduce((sum, m) => sum + (parseFloat(m.volume24h) || 0), 0),
680
+ btcDominance: 0, // Would need separate API
681
+ markets: result.data.markets,
682
+ },
683
+ };
684
+ }
685
+ return { success: false, error: result.error };
686
+ }
687
+
688
+ // ===============================
689
+ // NFT ENDPOINTS
690
+ // ===============================
691
+
692
+ /**
693
+ * Get user's NFTs
694
+ */
695
+ async getUserNFTs(
696
+ walletAddress: string,
697
+ options?: { chainId?: number; limit?: number; offset?: number }
698
+ ): Promise<ApiResponse<{ nfts: NFT[]; total: number }>> {
699
+ const params = new URLSearchParams({ address: walletAddress });
700
+ if (options?.chainId) params.set('chainId', options.chainId.toString());
701
+ if (options?.limit) params.set('limit', options.limit.toString());
702
+ if (options?.offset) params.set('offset', options.offset.toString());
703
+ return this.request(`/api/v1/assets/nfts?${params}`, { method: 'GET' });
704
+ }
705
+
706
+ /**
707
+ * Get NFT details
708
+ */
709
+ async getNFTDetails(
710
+ contractAddress: string,
711
+ tokenId: string,
712
+ chainId: number
713
+ ): Promise<ApiResponse<NFT>> {
714
+ return this.request(`/api/v1/assets/nfts/${contractAddress}/${tokenId}?chainId=${chainId}`, { method: 'GET' });
715
+ }
716
+
717
+ /**
718
+ * Get NFT collection
719
+ */
720
+ async getNFTCollection(
721
+ contractAddress: string,
722
+ chainId: number
723
+ ): Promise<ApiResponse<NFTCollection>> {
724
+ return this.request(`/api/v1/assets/nfts/collection/${contractAddress}?chainId=${chainId}`, { method: 'GET' });
725
+ }
726
+
727
+ /**
728
+ * Transfer NFT
729
+ */
730
+ async transferNFT(params: {
731
+ contractAddress: string;
732
+ tokenId: string;
733
+ chainId: number;
734
+ to: string;
735
+ tokenType?: 'ERC721' | 'ERC1155';
736
+ amount?: number; // For ERC1155
737
+ }): Promise<ApiResponse<{ txHash: string; status: string }>> {
738
+ return this.request('/api/v1/assets/nfts/transfer', {
739
+ method: 'POST',
740
+ body: JSON.stringify(params),
741
+ });
742
+ }
743
+
744
+ // ===============================
745
+ // CONTRACT ENDPOINTS
746
+ // ===============================
747
+
748
+ /**
749
+ * Get user's contracts
750
+ */
751
+ async getUserContracts(
752
+ options?: { chainId?: number; limit?: number; offset?: number }
753
+ ): Promise<ApiResponse<{ contracts: Contract[]; total: number }>> {
754
+ const params = new URLSearchParams();
755
+ if (options?.chainId) params.set('chainId', options.chainId.toString());
756
+ if (options?.limit) params.set('limit', options.limit.toString());
757
+ if (options?.offset) params.set('offset', options.offset.toString());
758
+ return this.request(`/api/v1/contracts?${params}`, { method: 'GET' });
759
+ }
760
+
761
+ /**
762
+ * Get contract details
763
+ */
764
+ async getContractDetails(
765
+ address: string,
766
+ chainId: number
767
+ ): Promise<ApiResponse<Contract>> {
768
+ return this.request(`/api/v1/contracts/${address}?chainId=${chainId}`, { method: 'GET' });
769
+ }
770
+
771
+ /**
772
+ * Read contract (call view function)
773
+ */
774
+ async readContract(params: ContractReadParams): Promise<ApiResponse<any>> {
775
+ return this.request('/api/v1/contracts/read', {
776
+ method: 'POST',
777
+ body: JSON.stringify(params),
778
+ });
779
+ }
780
+
781
+ /**
782
+ * Write to contract (execute transaction)
783
+ */
784
+ async writeContract(params: ContractWriteParams): Promise<ApiResponse<{
785
+ txHash: string;
786
+ status: string;
787
+ }>> {
788
+ return this.request('/api/v1/contracts/write', {
789
+ method: 'POST',
790
+ body: JSON.stringify(params),
791
+ });
792
+ }
793
+
794
+ /**
795
+ * Deploy contract
796
+ */
797
+ async deployContract(params: ContractDeployParams): Promise<ApiResponse<{
798
+ address: string;
799
+ txHash: string;
800
+ contract: Contract;
801
+ }>> {
802
+ return this.request('/api/v1/contracts/deploy', {
803
+ method: 'POST',
804
+ body: JSON.stringify(params),
805
+ });
806
+ }
807
+
808
+ // ===============================
809
+ // OFFRAMP ENDPOINTS (Crypto-to-Fiat)
810
+ // ===============================
811
+
812
+ /**
813
+ * Get offramp quote
814
+ */
815
+ async getOfframpQuote(
816
+ cryptoCurrency: string,
817
+ cryptoAmount: number,
818
+ fiatCurrency: string,
819
+ payoutMethod?: string
820
+ ): Promise<ApiResponse<OfframpQuote[]>> {
821
+ const params = new URLSearchParams({
822
+ cryptoCurrency,
823
+ cryptoAmount: cryptoAmount.toString(),
824
+ fiatCurrency,
825
+ });
826
+ if (payoutMethod) params.set('payoutMethod', payoutMethod);
827
+ return this.request(`/api/v1/fiat/offramp/quote?${params}`, { method: 'GET' });
828
+ }
829
+
830
+ /**
831
+ * Create offramp transaction
832
+ */
833
+ async createOfframpTransaction(request: OfframpRequest): Promise<ApiResponse<OfframpTransaction>> {
834
+ return this.request('/api/v1/fiat/offramp', {
835
+ method: 'POST',
836
+ body: JSON.stringify(request),
837
+ });
838
+ }
839
+
840
+ /**
841
+ * Get offramp transaction status
842
+ */
843
+ async getOfframpStatus(transactionId: string): Promise<ApiResponse<OfframpTransaction>> {
844
+ return this.request(`/api/v1/fiat/offramp/${transactionId}`, { method: 'GET' });
845
+ }
846
+
847
+ /**
848
+ * Get supported payout methods
849
+ */
850
+ async getSupportedPayoutMethods(country?: string): Promise<ApiResponse<string[]>> {
851
+ const params = country ? `?country=${country}` : '';
852
+ return this.request(`/api/v1/fiat/offramp/methods${params}`, { method: 'GET' });
853
+ }
854
+
855
+ // ===============================
856
+ // BILL PAYMENT ENDPOINTS
857
+ // ===============================
858
+
859
+ /**
860
+ * Get bill providers
861
+ */
862
+ async getBillProviders(
863
+ country?: string,
864
+ category?: string
865
+ ): Promise<ApiResponse<BillProvider[]>> {
866
+ const params = new URLSearchParams();
867
+ if (country) params.set('country', country);
868
+ if (category) params.set('category', category);
869
+ return this.request(`/api/v1/bills/providers?${params}`, { method: 'GET' });
870
+ }
871
+
872
+ /**
873
+ * Get bill details/validate account
874
+ */
875
+ async validateBillAccount(
876
+ providerId: string,
877
+ accountNumber: string
878
+ ): Promise<ApiResponse<{
879
+ valid: boolean;
880
+ accountName?: string;
881
+ minAmount?: number;
882
+ maxAmount?: number;
883
+ dueAmount?: number;
884
+ }>> {
885
+ return this.request('/api/v1/bills/validate', {
886
+ method: 'POST',
887
+ body: JSON.stringify({ providerId, accountNumber }),
888
+ });
889
+ }
890
+
891
+ /**
892
+ * Pay bill
893
+ */
894
+ async payBill(params: {
895
+ providerId: string;
896
+ accountNumber: string;
897
+ amount: number;
898
+ currency: string;
899
+ }): Promise<ApiResponse<BillPayment>> {
900
+ return this.request('/api/v1/bills/pay', {
901
+ method: 'POST',
902
+ body: JSON.stringify(params),
903
+ });
904
+ }
905
+
906
+ /**
907
+ * Get bill payment history
908
+ */
909
+ async getBillHistory(
910
+ options?: { limit?: number; offset?: number }
911
+ ): Promise<ApiResponse<{ payments: BillPayment[]; total: number }>> {
912
+ const params = new URLSearchParams();
913
+ if (options?.limit) params.set('limit', options.limit.toString());
914
+ if (options?.offset) params.set('offset', options.offset.toString());
915
+ return this.request(`/api/v1/bills/history?${params}`, { method: 'GET' });
916
+ }
917
+
918
+ // ===============================
919
+ // STAKING ENDPOINTS
920
+ // ===============================
921
+
922
+ /**
923
+ * Get staking pools
924
+ */
925
+ async getStakingPools(
926
+ chainId?: number
927
+ ): Promise<ApiResponse<StakingPool[]>> {
928
+ const params = chainId ? `?chainId=${chainId}` : '';
929
+ return this.request(`/api/v1/staking/pools${params}`, { method: 'GET' });
930
+ }
931
+
932
+ /**
933
+ * Get user's staking positions
934
+ */
935
+ async getStakingPositions(): Promise<ApiResponse<StakingPosition[]>> {
936
+ return this.request('/api/v1/staking/positions', { method: 'GET' });
937
+ }
938
+
939
+ /**
940
+ * Stake tokens
941
+ */
942
+ async stake(params: {
943
+ poolId: string;
944
+ amount: number;
945
+ }): Promise<ApiResponse<{ positionId: string; txHash: string }>> {
946
+ return this.request('/api/v1/staking/stake', {
947
+ method: 'POST',
948
+ body: JSON.stringify(params),
949
+ });
950
+ }
951
+
952
+ /**
953
+ * Unstake tokens
954
+ */
955
+ async unstake(params: {
956
+ positionId: string;
957
+ amount?: number; // Optional for partial unstake
958
+ }): Promise<ApiResponse<{ txHash: string }>> {
959
+ return this.request('/api/v1/staking/unstake', {
960
+ method: 'POST',
961
+ body: JSON.stringify(params),
962
+ });
963
+ }
964
+
965
+ /**
966
+ * Claim staking rewards
967
+ */
968
+ async claimStakingRewards(positionId: string): Promise<ApiResponse<{ txHash: string; amount: number }>> {
969
+ return this.request('/api/v1/staking/claim', {
970
+ method: 'POST',
971
+ body: JSON.stringify({ positionId }),
972
+ });
973
+ }
974
+
975
+ // ===============================
976
+ // USER PROFILE ENDPOINTS
977
+ // ===============================
978
+
979
+ /**
980
+ * Get user profile
981
+ */
982
+ async getUserProfile(): Promise<ApiResponse<UserProfile>> {
983
+ return this.request('/api/v1/user/profile', { method: 'GET' });
984
+ }
985
+
986
+ /**
987
+ * Update user profile
988
+ */
989
+ async updateUserProfile(updates: Partial<UserProfile>): Promise<ApiResponse<UserProfile>> {
990
+ return this.request('/api/v1/user/profile', {
991
+ method: 'PATCH',
992
+ body: JSON.stringify(updates),
993
+ });
994
+ }
995
+
996
+ /**
997
+ * Get user settings
998
+ */
999
+ async getUserSettings(): Promise<ApiResponse<UserSettings>> {
1000
+ return this.request('/api/v1/user/settings', { method: 'GET' });
1001
+ }
1002
+
1003
+ /**
1004
+ * Update user settings
1005
+ */
1006
+ async updateUserSettings(updates: Partial<UserSettings>): Promise<ApiResponse<UserSettings>> {
1007
+ return this.request('/api/v1/user/settings', {
1008
+ method: 'PATCH',
1009
+ body: JSON.stringify(updates),
1010
+ });
1011
+ }
1012
+
1013
+ // ===============================
1014
+ // NOTIFICATION ENDPOINTS
1015
+ // ===============================
1016
+
1017
+ /**
1018
+ * Get notifications
1019
+ */
1020
+ async getNotifications(
1021
+ options?: { unreadOnly?: boolean; limit?: number; offset?: number }
1022
+ ): Promise<ApiResponse<{ notifications: Notification[]; unreadCount: number }>> {
1023
+ const params = new URLSearchParams();
1024
+ if (options?.unreadOnly) params.set('unreadOnly', 'true');
1025
+ if (options?.limit) params.set('limit', options.limit.toString());
1026
+ if (options?.offset) params.set('offset', options.offset.toString());
1027
+ return this.request(`/api/v1/notifications?${params}`, { method: 'GET' });
1028
+ }
1029
+
1030
+ /**
1031
+ * Mark notification as read
1032
+ */
1033
+ async markNotificationRead(notificationId: string): Promise<ApiResponse<void>> {
1034
+ return this.request(`/api/v1/notifications/${notificationId}/read`, { method: 'POST' });
1035
+ }
1036
+
1037
+ /**
1038
+ * Mark all notifications as read
1039
+ */
1040
+ async markAllNotificationsRead(): Promise<ApiResponse<void>> {
1041
+ return this.request('/api/v1/notifications/read-all', { method: 'POST' });
1042
+ }
1043
+
1044
+ // ===============================
1045
+ // REFERRAL ENDPOINTS
1046
+ // ===============================
1047
+
1048
+ /**
1049
+ * Get referral info
1050
+ */
1051
+ async getReferralInfo(): Promise<ApiResponse<ReferralInfo>> {
1052
+ return this.request('/api/v1/referral', { method: 'GET' });
1053
+ }
1054
+
1055
+ /**
1056
+ * Get referred users
1057
+ */
1058
+ async getReferrals(): Promise<ApiResponse<Referral[]>> {
1059
+ return this.request('/api/v1/referral/list', { method: 'GET' });
1060
+ }
1061
+
1062
+ /**
1063
+ * Apply referral code
1064
+ */
1065
+ async applyReferralCode(code: string): Promise<ApiResponse<{ success: boolean; message: string }>> {
1066
+ return this.request('/api/v1/referral/apply', {
1067
+ method: 'POST',
1068
+ body: JSON.stringify({ code }),
1069
+ });
1070
+ }
1071
+
1072
+ /**
1073
+ * Claim referral rewards
1074
+ */
1075
+ async claimReferralRewards(): Promise<ApiResponse<{ amount: number; txHash?: string }>> {
1076
+ return this.request('/api/v1/referral/claim', { method: 'POST' });
1077
+ }
1078
+
1079
+ // ===============================
1080
+ // KYC ENDPOINTS
1081
+ // ===============================
1082
+
1083
+ /**
1084
+ * Get KYC status
1085
+ */
1086
+ async getKycStatus(): Promise<ApiResponse<{
1087
+ status: 'none' | 'pending' | 'verified' | 'rejected';
1088
+ level: number;
1089
+ limits: { daily: number; monthly: number };
1090
+ rejectionReason?: string;
1091
+ }>> {
1092
+ return this.request('/api/v1/kyc/status', { method: 'GET' });
1093
+ }
1094
+
1095
+ /**
1096
+ * Start KYC verification
1097
+ */
1098
+ async startKycVerification(level: number): Promise<ApiResponse<{
1099
+ verificationUrl: string;
1100
+ sessionId: string;
1101
+ }>> {
1102
+ return this.request('/api/v1/kyc/start', {
1103
+ method: 'POST',
1104
+ body: JSON.stringify({ level }),
1105
+ });
1106
+ }
1107
+
1108
+ /**
1109
+ * Submit KYC documents
1110
+ */
1111
+ async submitKycDocuments(params: {
1112
+ documentType: 'passport' | 'id_card' | 'drivers_license';
1113
+ frontImage: string; // base64
1114
+ backImage?: string; // base64
1115
+ selfieImage: string; // base64
1116
+ }): Promise<ApiResponse<{ status: string; message: string }>> {
1117
+ return this.request('/api/v1/kyc/submit', {
1118
+ method: 'POST',
1119
+ body: JSON.stringify(params),
1120
+ });
1121
+ }
1122
+
1123
+ // ===============================
1124
+ // BRIDGE ENDPOINTS
1125
+ // ===============================
1126
+
1127
+ /**
1128
+ * Get bridge quote
1129
+ */
1130
+ async getBridgeQuote(params: {
1131
+ fromChainId: number;
1132
+ toChainId: number;
1133
+ fromToken: string;
1134
+ toToken: string;
1135
+ amount: string;
1136
+ walletAddress: string;
1137
+ }): Promise<ApiResponse<BridgeQuote>> {
1138
+ return this.request('/api/v1/bridge/quote', {
1139
+ method: 'POST',
1140
+ body: JSON.stringify(params),
1141
+ });
1142
+ }
1143
+
1144
+ /**
1145
+ * Execute bridge transaction
1146
+ */
1147
+ async executeBridge(params: {
1148
+ quoteId: string;
1149
+ walletAddress: string;
1150
+ }): Promise<ApiResponse<BridgeTransaction>> {
1151
+ return this.request('/api/v1/bridge/execute', {
1152
+ method: 'POST',
1153
+ body: JSON.stringify(params),
1154
+ });
1155
+ }
1156
+
1157
+ /**
1158
+ * Get bridge transaction status
1159
+ */
1160
+ async getBridgeStatus(bridgeId: string): Promise<ApiResponse<BridgeTransaction>> {
1161
+ return this.request(`/api/v1/bridge/${bridgeId}`, { method: 'GET' });
1162
+ }
1163
+
1164
+ /**
1165
+ * Get supported bridge routes
1166
+ */
1167
+ async getSupportedBridgeRoutes(): Promise<ApiResponse<{
1168
+ routes: { fromChainId: number; toChainId: number; tokens: string[] }[];
1169
+ }>> {
1170
+ return this.request('/api/v1/bridge/routes', { method: 'GET' });
1171
+ }
1172
+
1173
+ // ===============================
1174
+ // GAS ENDPOINTS
1175
+ // ===============================
1176
+
1177
+ /**
1178
+ * Get gas estimate for transaction
1179
+ */
1180
+ async getGasEstimate(params: {
1181
+ chainId: number;
1182
+ to: string;
1183
+ data?: string;
1184
+ value?: string;
1185
+ }): Promise<ApiResponse<GasEstimate>> {
1186
+ return this.request('/api/v1/gas/estimate', {
1187
+ method: 'POST',
1188
+ body: JSON.stringify(params),
1189
+ });
1190
+ }
1191
+
1192
+ /**
1193
+ * Get current gas prices for chain
1194
+ */
1195
+ async getGasPrice(chainId: number): Promise<ApiResponse<GasPrice>> {
1196
+ return this.request(`/api/v1/gas/price?chainId=${chainId}`, { method: 'GET' });
1197
+ }
1198
+
1199
+ // ===============================
1200
+ // WALLET IMPORT/EXPORT ENDPOINTS
1201
+ // ===============================
1202
+
1203
+ /**
1204
+ * Import wallet from private key or mnemonic
1205
+ */
1206
+ async importWallet(request: WalletImportRequest): Promise<ApiResponse<{
1207
+ wallet: any;
1208
+ address: string;
1209
+ smartAccountAddress?: string;
1210
+ }>> {
1211
+ return this.request('/api/v1/wallet/import', {
1212
+ method: 'POST',
1213
+ body: JSON.stringify(request),
1214
+ }, true); // Include secret key for secure import
1215
+ }
1216
+
1217
+ /**
1218
+ * Export wallet (get encrypted private key)
1219
+ * Requires additional authentication
1220
+ */
1221
+ async exportWallet(walletId: string, pin: string): Promise<ApiResponse<{
1222
+ encryptedPrivateKey: string;
1223
+ address: string;
1224
+ }>> {
1225
+ return this.request('/api/v1/wallet/export', {
1226
+ method: 'POST',
1227
+ body: JSON.stringify({ walletId, pin }),
1228
+ }, true);
1229
+ }
1230
+
1231
+ /**
1232
+ * Generate new mnemonic phrase
1233
+ */
1234
+ async generateMnemonic(): Promise<ApiResponse<{ mnemonic: string; address: string }>> {
1235
+ return this.request('/api/v1/wallet/generate-mnemonic', { method: 'POST' }, true);
1236
+ }
1237
+
1238
+ /**
1239
+ * Validate mnemonic phrase
1240
+ */
1241
+ async validateMnemonic(mnemonic: string): Promise<ApiResponse<{ valid: boolean; address?: string }>> {
1242
+ return this.request('/api/v1/wallet/validate-mnemonic', {
1243
+ method: 'POST',
1244
+ body: JSON.stringify({ mnemonic }),
1245
+ });
1246
+ }
1247
+
1248
+ // ===============================
1249
+ // PORTFOLIO ANALYTICS ENDPOINTS
1250
+ // ===============================
1251
+
1252
+ /**
1253
+ * Get portfolio analytics with historical data
1254
+ */
1255
+ async getPortfolioAnalytics(
1256
+ walletAddress: string,
1257
+ period: '24h' | '7d' | '30d' | '90d' | '1y' | 'all' = '30d'
1258
+ ): Promise<ApiResponse<PortfolioAnalytics>> {
1259
+ const params = new URLSearchParams({ address: walletAddress, period });
1260
+ return this.request(`/api/v1/analytics/portfolio?${params}`, { method: 'GET' });
1261
+ }
1262
+
1263
+ /**
1264
+ * Get transaction analytics
1265
+ */
1266
+ async getTransactionAnalytics(
1267
+ walletAddress: string,
1268
+ period: '24h' | '7d' | '30d' | '90d' = '30d'
1269
+ ): Promise<ApiResponse<{
1270
+ totalTransactions: number;
1271
+ totalVolume: number;
1272
+ avgTransactionValue: number;
1273
+ byType: Record<string, number>;
1274
+ byChain: Record<string, number>;
1275
+ }>> {
1276
+ const params = new URLSearchParams({ address: walletAddress, period });
1277
+ return this.request(`/api/v1/analytics/transactions?${params}`, { method: 'GET' });
1278
+ }
1279
+
1280
+ // ===============================
1281
+ // ADVANCED TRADING ENDPOINTS
1282
+ // ===============================
1283
+
1284
+ /**
1285
+ * Create limit order
1286
+ */
1287
+ async createLimitOrder(params: {
1288
+ tokenSymbol: string;
1289
+ type: 'buy' | 'sell';
1290
+ amount: number;
1291
+ limitPrice: number;
1292
+ chainId: number;
1293
+ expiresIn?: number; // seconds
1294
+ conditions?: TradingCondition[];
1295
+ }): Promise<ApiResponse<LimitOrder>> {
1296
+ return this.request('/api/v1/trading/limit-orders', {
1297
+ method: 'POST',
1298
+ body: JSON.stringify(params),
1299
+ });
1300
+ }
1301
+
1302
+ /**
1303
+ * Get user's limit orders
1304
+ */
1305
+ async getLimitOrders(status?: 'pending' | 'filled' | 'cancelled'): Promise<ApiResponse<LimitOrder[]>> {
1306
+ const params = status ? `?status=${status}` : '';
1307
+ return this.request(`/api/v1/trading/limit-orders${params}`, { method: 'GET' });
1308
+ }
1309
+
1310
+ /**
1311
+ * Cancel limit order
1312
+ */
1313
+ async cancelLimitOrder(orderId: string): Promise<ApiResponse<{ success: boolean }>> {
1314
+ return this.request(`/api/v1/trading/limit-orders/${orderId}`, { method: 'DELETE' });
1315
+ }
1316
+
1317
+ /**
1318
+ * Set price alert
1319
+ */
1320
+ async setPriceAlert(params: {
1321
+ tokenSymbol: string;
1322
+ targetPrice: number;
1323
+ condition: 'above' | 'below';
1324
+ notification: 'push' | 'email' | 'both';
1325
+ }): Promise<ApiResponse<{ alertId: string }>> {
1326
+ return this.request('/api/v1/trading/alerts', {
1327
+ method: 'POST',
1328
+ body: JSON.stringify(params),
1329
+ });
1330
+ }
1331
+
1332
+ /**
1333
+ * Get price alerts
1334
+ */
1335
+ async getPriceAlerts(): Promise<ApiResponse<{
1336
+ id: string;
1337
+ tokenSymbol: string;
1338
+ targetPrice: number;
1339
+ condition: 'above' | 'below';
1340
+ status: 'active' | 'triggered' | 'cancelled';
1341
+ createdAt: string;
1342
+ triggeredAt?: string;
1343
+ }[]>> {
1344
+ return this.request('/api/v1/trading/alerts', { method: 'GET' });
1345
+ }
1346
+
1347
+ /**
1348
+ * Delete price alert
1349
+ */
1350
+ async deletePriceAlert(alertId: string): Promise<ApiResponse<{ success: boolean }>> {
1351
+ return this.request(`/api/v1/trading/alerts/${alertId}`, { method: 'DELETE' });
1352
+ }
1353
+
1354
+ // ===============================
1355
+ // SESSION MANAGEMENT
1356
+ // ===============================
1357
+
1358
+ /**
1359
+ * Get active sessions
1360
+ */
1361
+ async getActiveSessions(): Promise<ApiResponse<{
1362
+ sessions: {
1363
+ id: string;
1364
+ deviceName: string;
1365
+ ipAddress: string;
1366
+ lastActive: string;
1367
+ current: boolean;
1368
+ }[];
1369
+ }>> {
1370
+ return this.request('/api/v1/auth/sessions', { method: 'GET' });
1371
+ }
1372
+
1373
+ /**
1374
+ * Revoke session
1375
+ */
1376
+ async revokeSession(sessionId: string): Promise<ApiResponse<{ success: boolean }>> {
1377
+ return this.request(`/api/v1/auth/sessions/${sessionId}`, { method: 'DELETE' });
1378
+ }
1379
+
1380
+ /**
1381
+ * Revoke all other sessions
1382
+ */
1383
+ async revokeAllOtherSessions(): Promise<ApiResponse<{ revokedCount: number }>> {
1384
+ return this.request('/api/v1/auth/sessions/revoke-all', { method: 'POST' });
1385
+ }
1386
+
1387
+ // ========== Webhooks ==========
1388
+
1389
+ /**
1390
+ * List webhooks for the project
1391
+ */
1392
+ async listWebhooks(options?: { isActive?: boolean }): Promise<ApiResponse<{ webhooks: Webhook[]; total: number }>> {
1393
+ const params = new URLSearchParams();
1394
+ if (options?.isActive !== undefined) params.set('isActive', String(options.isActive));
1395
+ const query = params.toString();
1396
+ return this.request(`/api/v1/webhooks${query ? `?${query}` : ''}`, { method: 'GET' });
1397
+ }
1398
+
1399
+ /**
1400
+ * Get webhook by ID
1401
+ */
1402
+ async getWebhook(webhookId: string): Promise<ApiResponse<{ webhook: Webhook }>> {
1403
+ return this.request(`/api/v1/webhooks/${webhookId}`, { method: 'GET' });
1404
+ }
1405
+
1406
+ /**
1407
+ * Create a webhook
1408
+ */
1409
+ async createWebhook(input: CreateWebhookInput): Promise<ApiResponse<{ webhook: Webhook }>> {
1410
+ return this.request('/api/v1/webhooks', {
1411
+ method: 'POST',
1412
+ body: JSON.stringify(input),
1413
+ });
1414
+ }
1415
+
1416
+ /**
1417
+ * Update a webhook
1418
+ */
1419
+ async updateWebhook(webhookId: string, input: UpdateWebhookInput): Promise<ApiResponse<{ webhook: Webhook }>> {
1420
+ return this.request(`/api/v1/webhooks/${webhookId}`, {
1421
+ method: 'PATCH',
1422
+ body: JSON.stringify(input),
1423
+ });
1424
+ }
1425
+
1426
+ /**
1427
+ * Delete a webhook
1428
+ */
1429
+ async deleteWebhook(webhookId: string): Promise<ApiResponse<{ deleted: boolean }>> {
1430
+ return this.request(`/api/v1/webhooks/${webhookId}`, { method: 'DELETE' });
1431
+ }
1432
+
1433
+ /**
1434
+ * Get webhook deliveries
1435
+ */
1436
+ async getWebhookDeliveries(
1437
+ webhookId: string,
1438
+ options?: { status?: 'pending' | 'success' | 'failed'; limit?: number; offset?: number }
1439
+ ): Promise<ApiResponse<{ deliveries: WebhookDelivery[]; total: number }>> {
1440
+ const params = new URLSearchParams();
1441
+ if (options?.status) params.set('status', options.status);
1442
+ if (options?.limit) params.set('limit', String(options.limit));
1443
+ if (options?.offset) params.set('offset', String(options.offset));
1444
+ const query = params.toString();
1445
+ return this.request(`/api/v1/webhooks/${webhookId}/deliveries${query ? `?${query}` : ''}`, { method: 'GET' });
1446
+ }
1447
+
1448
+ /**
1449
+ * Test a webhook
1450
+ */
1451
+ async testWebhook(webhookId: string): Promise<ApiResponse<{
1452
+ success: boolean;
1453
+ statusCode?: number;
1454
+ responseTime?: number;
1455
+ error?: string;
1456
+ }>> {
1457
+ return this.request(`/api/v1/webhooks/${webhookId}/test`, { method: 'POST' });
1458
+ }
1459
+
1460
+ // ========== Admin (requires admin role) ==========
1461
+
1462
+ /**
1463
+ * List all users (admin only)
1464
+ */
1465
+ async adminListUsers(options?: AdminListOptions & {
1466
+ role?: 'user' | 'admin';
1467
+ kycStatus?: 'none' | 'pending' | 'verified' | 'rejected';
1468
+ isActive?: boolean;
1469
+ }): Promise<ApiResponse<PaginatedResult<AdminUser>>> {
1470
+ const params = new URLSearchParams();
1471
+ if (options?.page) params.set('page', String(options.page));
1472
+ if (options?.limit) params.set('limit', String(options.limit));
1473
+ if (options?.search) params.set('search', options.search);
1474
+ if (options?.sortBy) params.set('sortBy', options.sortBy);
1475
+ if (options?.sortOrder) params.set('sortOrder', options.sortOrder);
1476
+ if (options?.role) params.set('role', options.role);
1477
+ if (options?.kycStatus) params.set('kycStatus', options.kycStatus);
1478
+ if (options?.isActive !== undefined) params.set('isActive', String(options.isActive));
1479
+ const query = params.toString();
1480
+ return this.request(`/api/v1/admin/users${query ? `?${query}` : ''}`, { method: 'GET' });
1481
+ }
1482
+
1483
+ /**
1484
+ * Get user by ID (admin only)
1485
+ */
1486
+ async adminGetUser(userId: string): Promise<ApiResponse<{ user: AdminUser }>> {
1487
+ return this.request(`/api/v1/admin/users/${userId}`, { method: 'GET' });
1488
+ }
1489
+
1490
+ /**
1491
+ * Update user (admin only)
1492
+ */
1493
+ async adminUpdateUser(userId: string, data: {
1494
+ role?: 'user' | 'admin';
1495
+ isActive?: boolean;
1496
+ kycStatus?: 'none' | 'pending' | 'verified' | 'rejected';
1497
+ }): Promise<ApiResponse<{ user: AdminUser }>> {
1498
+ return this.request(`/api/v1/admin/users/${userId}`, {
1499
+ method: 'PATCH',
1500
+ body: JSON.stringify(data),
1501
+ });
1502
+ }
1503
+
1504
+ /**
1505
+ * List all projects (admin only)
1506
+ */
1507
+ async adminListProjects(options?: AdminListOptions & {
1508
+ isActive?: boolean;
1509
+ }): Promise<ApiResponse<PaginatedResult<AdminProject>>> {
1510
+ const params = new URLSearchParams();
1511
+ if (options?.page) params.set('page', String(options.page));
1512
+ if (options?.limit) params.set('limit', String(options.limit));
1513
+ if (options?.search) params.set('search', options.search);
1514
+ if (options?.sortBy) params.set('sortBy', options.sortBy);
1515
+ if (options?.sortOrder) params.set('sortOrder', options.sortOrder);
1516
+ if (options?.isActive !== undefined) params.set('isActive', String(options.isActive));
1517
+ const query = params.toString();
1518
+ return this.request(`/api/v1/admin/projects${query ? `?${query}` : ''}`, { method: 'GET' });
1519
+ }
1520
+
1521
+ /**
1522
+ * Get project by ID (admin only)
1523
+ */
1524
+ async adminGetProject(projectId: string): Promise<ApiResponse<{ project: AdminProject }>> {
1525
+ return this.request(`/api/v1/admin/projects/${projectId}`, { method: 'GET' });
1526
+ }
1527
+
1528
+ /**
1529
+ * Update project (admin only)
1530
+ */
1531
+ async adminUpdateProject(projectId: string, data: {
1532
+ name?: string;
1533
+ isActive?: boolean;
1534
+ settings?: Record<string, unknown>;
1535
+ }): Promise<ApiResponse<{ project: AdminProject }>> {
1536
+ return this.request(`/api/v1/admin/projects/${projectId}`, {
1537
+ method: 'PATCH',
1538
+ body: JSON.stringify(data),
1539
+ });
1540
+ }
1541
+
1542
+ /**
1543
+ * Regenerate project API key (admin only)
1544
+ */
1545
+ async adminRegenerateApiKey(projectId: string): Promise<ApiResponse<{ apiKey: string }>> {
1546
+ return this.request(`/api/v1/admin/projects/${projectId}/regenerate-key`, { method: 'POST' });
1547
+ }
1548
+
1549
+ /**
1550
+ * Get system statistics (admin only)
1551
+ */
1552
+ async adminGetStats(days?: number): Promise<ApiResponse<SystemStats>> {
1553
+ const query = days ? `?days=${days}` : '';
1554
+ return this.request(`/api/v1/admin/stats${query}`, { method: 'GET' });
1555
+ }
1556
+
1557
+ /**
1558
+ * Get system logs (admin only)
1559
+ */
1560
+ async adminGetLogs(options?: {
1561
+ level?: 'info' | 'warn' | 'error';
1562
+ service?: string;
1563
+ limit?: number;
1564
+ offset?: number;
1565
+ startDate?: string;
1566
+ endDate?: string;
1567
+ }): Promise<ApiResponse<{ logs: SystemLog[]; total: number }>> {
1568
+ const params = new URLSearchParams();
1569
+ if (options?.level) params.set('level', options.level);
1570
+ if (options?.service) params.set('service', options.service);
1571
+ if (options?.limit) params.set('limit', String(options.limit));
1572
+ if (options?.offset) params.set('offset', String(options.offset));
1573
+ if (options?.startDate) params.set('startDate', options.startDate);
1574
+ if (options?.endDate) params.set('endDate', options.endDate);
1575
+ const query = params.toString();
1576
+ return this.request(`/api/v1/admin/logs${query ? `?${query}` : ''}`, { method: 'GET' });
1577
+ }
1578
+
1579
+ /**
1580
+ * Get rate limit status (admin only)
1581
+ */
1582
+ async adminGetRateLimits(options?: {
1583
+ identifier?: string;
1584
+ limit?: number;
1585
+ }): Promise<ApiResponse<{ limits: RateLimitInfo[] }>> {
1586
+ const params = new URLSearchParams();
1587
+ if (options?.identifier) params.set('identifier', options.identifier);
1588
+ if (options?.limit) params.set('limit', String(options.limit));
1589
+ const query = params.toString();
1590
+ return this.request(`/api/v1/admin/rate-limits${query ? `?${query}` : ''}`, { method: 'GET' });
1591
+ }
1592
+
1593
+ /**
1594
+ * Clear rate limits for an identifier (admin only)
1595
+ */
1596
+ async adminClearRateLimits(identifier: string): Promise<ApiResponse<{ success: boolean }>> {
1597
+ return this.request(`/api/v1/admin/rate-limits/${identifier}`, { method: 'DELETE' });
1598
+ }
1599
+
1600
+ // ========== AI Quant Trading ==========
1601
+
1602
+ /**
1603
+ * Get all AI trading strategies
1604
+ */
1605
+ async getAIStrategies(filters?: {
1606
+ category?: StrategyCategory;
1607
+ riskLevel?: number;
1608
+ minTvl?: number;
1609
+ isActive?: boolean;
1610
+ }): Promise<ApiResponse<{ strategies: AIStrategy[] }>> {
1611
+ const params = new URLSearchParams();
1612
+ if (filters?.category) params.set('category', filters.category);
1613
+ if (filters?.riskLevel) params.set('risk_level', String(filters.riskLevel));
1614
+ if (filters?.minTvl) params.set('min_tvl', String(filters.minTvl));
1615
+ if (filters?.isActive !== undefined) params.set('is_active', String(filters.isActive));
1616
+ const query = params.toString();
1617
+ return this.request(`/api/v1/ai-quant/strategies${query ? `?${query}` : ''}`, { method: 'GET' });
1618
+ }
1619
+
1620
+ /**
1621
+ * Get AI strategy details
1622
+ */
1623
+ async getAIStrategy(strategyId: string, include?: ('performance' | 'market' | 'trades')[]): Promise<ApiResponse<{
1624
+ strategy: AIStrategy;
1625
+ performance?: AINavSnapshot[];
1626
+ marketData?: AIMarketData[];
1627
+ trades?: AITradeExecution[];
1628
+ }>> {
1629
+ const params = new URLSearchParams();
1630
+ if (include?.length) params.set('include', include.join(','));
1631
+ const query = params.toString();
1632
+ return this.request(`/api/v1/ai-quant/strategies/${strategyId}${query ? `?${query}` : ''}`, { method: 'GET' });
1633
+ }
1634
+
1635
+ /**
1636
+ * Get strategy performance history
1637
+ */
1638
+ async getAIStrategyPerformance(strategyId: string, days = 30): Promise<ApiResponse<{ performance: AINavSnapshot[] }>> {
1639
+ return this.request(`/api/v1/ai-quant/strategies/${strategyId}?include=performance&days=${days}`, { method: 'GET' });
1640
+ }
1641
+
1642
+ /**
1643
+ * Get real-time market data for strategy pairs
1644
+ */
1645
+ async getAIStrategyMarketData(strategyId: string): Promise<ApiResponse<{ marketData: AIMarketData[] }>> {
1646
+ return this.request(`/api/v1/ai-quant/strategies/${strategyId}?include=market`, { method: 'GET' });
1647
+ }
1648
+
1649
+ /**
1650
+ * Create AI trading order
1651
+ */
1652
+ async createAIOrder(request: CreateAIOrderRequest): Promise<ApiResponse<{ order: AIOrder }>> {
1653
+ return this.request('/api/v1/ai-quant/orders', {
1654
+ method: 'POST',
1655
+ body: JSON.stringify(request),
1656
+ });
1657
+ }
1658
+
1659
+ /**
1660
+ * Get user's AI orders
1661
+ */
1662
+ async getAIOrders(filters?: {
1663
+ strategyId?: string;
1664
+ status?: AIOrderStatus;
1665
+ }): Promise<ApiResponse<{ orders: AIOrder[] }>> {
1666
+ const params = new URLSearchParams();
1667
+ if (filters?.strategyId) params.set('strategy_id', filters.strategyId);
1668
+ if (filters?.status) params.set('status', filters.status);
1669
+ const query = params.toString();
1670
+ return this.request(`/api/v1/ai-quant/orders${query ? `?${query}` : ''}`, { method: 'GET' });
1671
+ }
1672
+
1673
+ /**
1674
+ * Get AI order details
1675
+ */
1676
+ async getAIOrder(orderId: string): Promise<ApiResponse<{
1677
+ order: AIOrder;
1678
+ strategy: AIStrategy;
1679
+ }>> {
1680
+ return this.request(`/api/v1/ai-quant/orders/${orderId}`, { method: 'GET' });
1681
+ }
1682
+
1683
+ /**
1684
+ * Pause AI order
1685
+ */
1686
+ async pauseAIOrder(orderId: string): Promise<ApiResponse<{ order: AIOrder; message: string }>> {
1687
+ return this.request(`/api/v1/ai-quant/orders/${orderId}/pause`, { method: 'POST' });
1688
+ }
1689
+
1690
+ /**
1691
+ * Resume AI order
1692
+ */
1693
+ async resumeAIOrder(orderId: string): Promise<ApiResponse<{ order: AIOrder; message: string }>> {
1694
+ return this.request(`/api/v1/ai-quant/orders/${orderId}/resume`, { method: 'POST' });
1695
+ }
1696
+
1697
+ /**
1698
+ * Request redemption for AI order
1699
+ */
1700
+ async redeemAIOrder(orderId: string): Promise<ApiResponse<{
1701
+ success: boolean;
1702
+ redemption: AIRedemptionResult;
1703
+ message: string;
1704
+ }>> {
1705
+ return this.request(`/api/v1/ai-quant/orders/${orderId}/redeem`, { method: 'POST' });
1706
+ }
1707
+
1708
+ /**
1709
+ * Get AI portfolio summary
1710
+ */
1711
+ async getAIPortfolio(include?: ('allocations' | 'orders')[]): Promise<ApiResponse<{
1712
+ portfolio: AIPortfolioSummary;
1713
+ allocations?: AITradeAllocation[];
1714
+ orders?: AIOrder[];
1715
+ }>> {
1716
+ const params = new URLSearchParams();
1717
+ if (include?.length) params.set('include', include.join(','));
1718
+ const query = params.toString();
1719
+ return this.request(`/api/v1/ai-quant/portfolio${query ? `?${query}` : ''}`, { method: 'GET' });
1720
+ }
1721
+
1722
+ /**
1723
+ * Get user's trade allocations
1724
+ */
1725
+ async getAITradeAllocations(limit = 50): Promise<ApiResponse<{ allocations: AITradeAllocation[] }>> {
1726
+ return this.request(`/api/v1/ai-quant/portfolio?include=allocations&limit=${limit}`, { method: 'GET' });
1727
+ }
1728
+
1729
+ /**
1730
+ * Get trade history for a strategy
1731
+ */
1732
+ async getAITradeHistory(strategyId: string, limit = 50): Promise<ApiResponse<{ trades: AITradeExecution[] }>> {
1733
+ return this.request(`/api/v1/ai-quant/strategies/${strategyId}?include=trades&limit=${limit}`, { method: 'GET' });
1734
+ }
1735
+
1736
+ /**
1737
+ * Execute AI signals for a strategy (admin only)
1738
+ */
1739
+ async executeAISignals(strategyId: string): Promise<ApiResponse<{
1740
+ executions: AITradeExecution[];
1741
+ count: number;
1742
+ message: string;
1743
+ }>> {
1744
+ return this.request('/api/v1/ai-quant/execute', {
1745
+ method: 'POST',
1746
+ body: JSON.stringify({ strategyId }),
1747
+ });
1748
+ }
1749
+
1750
+ // ========== Free Price APIs (No API Key Required) ==========
1751
+
1752
+ /**
1753
+ * Get cryptocurrency prices (FREE - uses CoinGecko/Binance/CoinCap)
1754
+ */
1755
+ async getCryptoPrices(symbols: string[]): Promise<ApiResponse<{
1756
+ prices: Array<{
1757
+ symbol: string;
1758
+ price: number;
1759
+ change24h: number;
1760
+ changePercent24h: number;
1761
+ high24h: number;
1762
+ low24h: number;
1763
+ volume24h: number;
1764
+ marketCap?: number;
1765
+ lastUpdated: string;
1766
+ }>;
1767
+ }>> {
1768
+ return this.request(`/api/v1/prices?symbols=${symbols.join(',')}`, { method: 'GET' });
1769
+ }
1770
+
1771
+ /**
1772
+ * Get single cryptocurrency price (FREE)
1773
+ */
1774
+ async getCryptoPrice(symbol: string): Promise<ApiResponse<{
1775
+ price: {
1776
+ symbol: string;
1777
+ price: number;
1778
+ change24h: number;
1779
+ changePercent24h: number;
1780
+ high24h: number;
1781
+ low24h: number;
1782
+ volume24h: number;
1783
+ marketCap?: number;
1784
+ lastUpdated: string;
1785
+ };
1786
+ }>> {
1787
+ return this.request(`/api/v1/prices/${symbol}`, { method: 'GET' });
1788
+ }
1789
+
1790
+ /**
1791
+ * Get OHLCV candles for charting (FREE - from Binance)
1792
+ */
1793
+ async getCryptoCandles(
1794
+ symbol: string,
1795
+ interval: '1m' | '5m' | '15m' | '1h' | '4h' | '1d' = '1h',
1796
+ limit = 100
1797
+ ): Promise<ApiResponse<{
1798
+ symbol: string;
1799
+ interval: string;
1800
+ candles: Array<{
1801
+ timestamp: number;
1802
+ open: number;
1803
+ high: number;
1804
+ low: number;
1805
+ close: number;
1806
+ volume: number;
1807
+ }>;
1808
+ }>> {
1809
+ return this.request(`/api/v1/prices/${symbol}?candles=true&interval=${interval}&limit=${limit}`, { method: 'GET' });
1810
+ }
1811
+
1812
+ /**
1813
+ * Get top cryptocurrencies by market cap (FREE)
1814
+ */
1815
+ async getTopCryptos(limit = 20): Promise<ApiResponse<{
1816
+ prices: Array<{
1817
+ symbol: string;
1818
+ price: number;
1819
+ change24h: number;
1820
+ changePercent24h: number;
1821
+ high24h: number;
1822
+ low24h: number;
1823
+ volume24h: number;
1824
+ marketCap?: number;
1825
+ lastUpdated: string;
1826
+ }>;
1827
+ }>> {
1828
+ return this.request(`/api/v1/prices?type=top&limit=${limit}`, { method: 'GET' });
1829
+ }
1830
+
1831
+ /**
1832
+ * Get crypto market overview (FREE)
1833
+ */
1834
+ async getCryptoMarketOverview(): Promise<ApiResponse<{
1835
+ overview: {
1836
+ totalMarketCap: number;
1837
+ totalVolume24h: number;
1838
+ btcDominance: number;
1839
+ marketCapChange24h: number;
1840
+ activeCryptocurrencies: number;
1841
+ };
1842
+ }>> {
1843
+ return this.request('/api/v1/prices?type=overview', { method: 'GET' });
1844
+ }
1845
+ }
1846
+
1847
+ // Factory function
1848
+ export function createOneEngineClient(options?: {
1849
+ baseUrl?: string;
1850
+ clientId?: string;
1851
+ secretKey?: string;
1852
+ }): OneEngineClient {
1853
+ return new OneEngineClient(options);
1854
+ }