@one_deploy/sdk 1.0.2 → 1.0.4
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/package.json +1 -1
- package/src/components/OneSwapWidget.tsx +1 -1
- package/src/components/ai/OneChainSelector.tsx +183 -0
- package/src/components/ai/OneCycleSelector.tsx +187 -0
- package/src/components/ai/OnePairSelector.tsx +181 -0
- package/src/components/ai/OneTierSelector.tsx +187 -0
- package/src/components/ai/index.ts +17 -0
- package/src/components/index.ts +3 -0
- package/src/config/index.ts +1 -1
- package/src/hooks/index.ts +20 -0
- package/src/hooks/useAITrading.ts +444 -0
- package/src/index.ts +20 -0
- package/src/react-native.ts +23 -0
- package/src/services/engine.ts +184 -0
- package/src/services/index.ts +16 -0
- package/src/services/usage.ts +249 -0
- package/.turbo/turbo-build.log +0 -0
- package/.turbo/turbo-type-check.log +0 -0
- package/dist/config/index.d.mts +0 -74
- package/dist/config/index.d.ts +0 -74
- package/dist/config/index.js +0 -244
- package/dist/config/index.js.map +0 -1
- package/dist/config/index.mjs +0 -226
- package/dist/config/index.mjs.map +0 -1
- package/dist/engine-5ndtBaCr.d.ts +0 -1039
- package/dist/engine-CrlhH0nw.d.mts +0 -1039
- package/dist/hooks/index.d.mts +0 -56
- package/dist/hooks/index.d.ts +0 -56
- package/dist/hooks/index.js +0 -1360
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/index.mjs +0 -1356
- package/dist/hooks/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -356
- package/dist/index.d.ts +0 -356
- package/dist/index.js +0 -5069
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -4950
- package/dist/index.mjs.map +0 -1
- package/dist/price-CgqXPnT3.d.ts +0 -13
- package/dist/price-ClbLHHjv.d.mts +0 -13
- package/dist/providers/index.d.mts +0 -121
- package/dist/providers/index.d.ts +0 -121
- package/dist/providers/index.js +0 -1643
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/index.mjs +0 -1601
- package/dist/providers/index.mjs.map +0 -1
- package/dist/react-native.d.mts +0 -120
- package/dist/react-native.d.ts +0 -120
- package/dist/react-native.js +0 -1794
- package/dist/react-native.js.map +0 -1
- package/dist/react-native.mjs +0 -1757
- package/dist/react-native.mjs.map +0 -1
- package/dist/services/index.d.mts +0 -85
- package/dist/services/index.d.ts +0 -85
- package/dist/services/index.js +0 -1466
- package/dist/services/index.js.map +0 -1
- package/dist/services/index.mjs +0 -1458
- package/dist/services/index.mjs.map +0 -1
- package/dist/types/index.d.mts +0 -759
- package/dist/types/index.d.ts +0 -759
- package/dist/types/index.js +0 -4
- package/dist/types/index.js.map +0 -1
- package/dist/types/index.mjs +0 -3
- package/dist/types/index.mjs.map +0 -1
- package/dist/utils/index.d.mts +0 -36
- package/dist/utils/index.d.ts +0 -36
- package/dist/utils/index.js +0 -164
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/index.mjs +0 -142
- package/dist/utils/index.mjs.map +0 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OneTierSelector - Investment tier selection component for AI trading
|
|
3
|
+
* Part of ONE Ecosystem SDK - can be used by any ecosystem partner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { View, Text, StyleSheet, TouchableOpacity, ViewStyle, TextStyle } from 'react-native';
|
|
8
|
+
|
|
9
|
+
export interface Tier {
|
|
10
|
+
tier: number;
|
|
11
|
+
amount: number;
|
|
12
|
+
label: string;
|
|
13
|
+
label_zh?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface OneTierSelectorProps {
|
|
17
|
+
/** Available investment tiers */
|
|
18
|
+
tiers: Tier[];
|
|
19
|
+
/** Currently selected tier */
|
|
20
|
+
selectedTier: Tier | null;
|
|
21
|
+
/** Callback when tier selection changes */
|
|
22
|
+
onSelectTier: (tier: Tier) => void;
|
|
23
|
+
/** Accent color for selected state */
|
|
24
|
+
accentColor?: string;
|
|
25
|
+
/** Section title */
|
|
26
|
+
title?: string;
|
|
27
|
+
/** Section subtitle */
|
|
28
|
+
subtitle?: string;
|
|
29
|
+
/** Show recommended badge on middle tier */
|
|
30
|
+
showRecommended?: boolean;
|
|
31
|
+
/** Recommended label text */
|
|
32
|
+
recommendedLabel?: string;
|
|
33
|
+
/** Use Chinese labels */
|
|
34
|
+
useZhLabels?: boolean;
|
|
35
|
+
/** Custom styles */
|
|
36
|
+
style?: ViewStyle;
|
|
37
|
+
/** Custom title style */
|
|
38
|
+
titleStyle?: TextStyle;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const OneTierSelector: React.FC<OneTierSelectorProps> = ({
|
|
42
|
+
tiers,
|
|
43
|
+
selectedTier,
|
|
44
|
+
onSelectTier,
|
|
45
|
+
accentColor = '#188775',
|
|
46
|
+
title,
|
|
47
|
+
subtitle,
|
|
48
|
+
showRecommended = true,
|
|
49
|
+
recommendedLabel = 'Recommended',
|
|
50
|
+
useZhLabels = false,
|
|
51
|
+
style,
|
|
52
|
+
titleStyle,
|
|
53
|
+
}) => {
|
|
54
|
+
// Middle tier is usually recommended
|
|
55
|
+
const recommendedTierIndex = Math.floor(tiers.length / 2);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<View style={[styles.container, style]}>
|
|
59
|
+
{title && <Text style={[styles.title, titleStyle]}>{title}</Text>}
|
|
60
|
+
{subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
|
|
61
|
+
|
|
62
|
+
<View style={styles.tiersContainer}>
|
|
63
|
+
{tiers.map((tier, index) => {
|
|
64
|
+
const isSelected = selectedTier?.tier === tier.tier;
|
|
65
|
+
const isRecommended = showRecommended && index === recommendedTierIndex;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<TouchableOpacity
|
|
69
|
+
key={tier.tier}
|
|
70
|
+
style={[
|
|
71
|
+
styles.tierCard,
|
|
72
|
+
isSelected && styles.tierCardSelected,
|
|
73
|
+
isSelected && { borderColor: accentColor }
|
|
74
|
+
]}
|
|
75
|
+
onPress={() => onSelectTier(tier)}
|
|
76
|
+
activeOpacity={0.7}
|
|
77
|
+
>
|
|
78
|
+
{isRecommended && (
|
|
79
|
+
<View style={[styles.recommendedBadge, { backgroundColor: accentColor }]}>
|
|
80
|
+
<Text style={styles.recommendedText}>{recommendedLabel}</Text>
|
|
81
|
+
</View>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
<Text style={[
|
|
85
|
+
styles.tierLabel,
|
|
86
|
+
isSelected && { color: accentColor },
|
|
87
|
+
isRecommended && styles.tierLabelWithBadge
|
|
88
|
+
]}>
|
|
89
|
+
{useZhLabels && tier.label_zh ? tier.label_zh : tier.label}
|
|
90
|
+
</Text>
|
|
91
|
+
|
|
92
|
+
<Text style={[
|
|
93
|
+
styles.tierAmount,
|
|
94
|
+
isSelected && { color: accentColor }
|
|
95
|
+
]}>
|
|
96
|
+
${tier.amount.toLocaleString()}
|
|
97
|
+
</Text>
|
|
98
|
+
|
|
99
|
+
{isSelected && (
|
|
100
|
+
<View style={[styles.checkCircle, { backgroundColor: accentColor }]}>
|
|
101
|
+
<Text style={styles.checkmark}>✓</Text>
|
|
102
|
+
</View>
|
|
103
|
+
)}
|
|
104
|
+
</TouchableOpacity>
|
|
105
|
+
);
|
|
106
|
+
})}
|
|
107
|
+
</View>
|
|
108
|
+
</View>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const styles = StyleSheet.create({
|
|
113
|
+
container: {
|
|
114
|
+
marginBottom: 16,
|
|
115
|
+
},
|
|
116
|
+
title: {
|
|
117
|
+
fontSize: 16,
|
|
118
|
+
fontWeight: '600',
|
|
119
|
+
color: '#1a1a1a',
|
|
120
|
+
marginBottom: 4,
|
|
121
|
+
},
|
|
122
|
+
subtitle: {
|
|
123
|
+
fontSize: 12,
|
|
124
|
+
color: '#666',
|
|
125
|
+
marginBottom: 12,
|
|
126
|
+
},
|
|
127
|
+
tiersContainer: {
|
|
128
|
+
flexDirection: 'row',
|
|
129
|
+
gap: 8,
|
|
130
|
+
},
|
|
131
|
+
tierCard: {
|
|
132
|
+
flex: 1,
|
|
133
|
+
padding: 16,
|
|
134
|
+
backgroundColor: '#fff',
|
|
135
|
+
borderRadius: 12,
|
|
136
|
+
borderWidth: 2,
|
|
137
|
+
borderColor: '#e5e5e5',
|
|
138
|
+
alignItems: 'center',
|
|
139
|
+
position: 'relative',
|
|
140
|
+
overflow: 'hidden',
|
|
141
|
+
},
|
|
142
|
+
tierCardSelected: {
|
|
143
|
+
backgroundColor: '#fff',
|
|
144
|
+
},
|
|
145
|
+
tierLabel: {
|
|
146
|
+
fontSize: 12,
|
|
147
|
+
color: '#666',
|
|
148
|
+
marginBottom: 4,
|
|
149
|
+
},
|
|
150
|
+
tierLabelWithBadge: {
|
|
151
|
+
marginTop: 16,
|
|
152
|
+
},
|
|
153
|
+
tierAmount: {
|
|
154
|
+
fontSize: 20,
|
|
155
|
+
fontWeight: '700',
|
|
156
|
+
color: '#1a1a1a',
|
|
157
|
+
},
|
|
158
|
+
checkCircle: {
|
|
159
|
+
position: 'absolute',
|
|
160
|
+
top: -8,
|
|
161
|
+
right: -8,
|
|
162
|
+
width: 28,
|
|
163
|
+
height: 28,
|
|
164
|
+
borderRadius: 14,
|
|
165
|
+
alignItems: 'center',
|
|
166
|
+
justifyContent: 'center',
|
|
167
|
+
},
|
|
168
|
+
checkmark: {
|
|
169
|
+
fontSize: 14,
|
|
170
|
+
fontWeight: '700',
|
|
171
|
+
color: '#fff',
|
|
172
|
+
},
|
|
173
|
+
recommendedBadge: {
|
|
174
|
+
position: 'absolute',
|
|
175
|
+
top: 0,
|
|
176
|
+
left: 0,
|
|
177
|
+
right: 0,
|
|
178
|
+
paddingVertical: 4,
|
|
179
|
+
alignItems: 'center',
|
|
180
|
+
},
|
|
181
|
+
recommendedText: {
|
|
182
|
+
fontSize: 10,
|
|
183
|
+
fontWeight: '700',
|
|
184
|
+
color: '#fff',
|
|
185
|
+
textTransform: 'uppercase',
|
|
186
|
+
},
|
|
187
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ONE AI Trading Components
|
|
3
|
+
* Reusable UI components for AI trading integration
|
|
4
|
+
* Can be used by any ecosystem partner
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Chain Selection
|
|
8
|
+
export * from './OneChainSelector';
|
|
9
|
+
|
|
10
|
+
// Investment Tier Selection
|
|
11
|
+
export * from './OneTierSelector';
|
|
12
|
+
|
|
13
|
+
// Cycle Selection
|
|
14
|
+
export * from './OneCycleSelector';
|
|
15
|
+
|
|
16
|
+
// Trading Pair Selection
|
|
17
|
+
export * from './OnePairSelector';
|
package/src/components/index.ts
CHANGED
package/src/config/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ export interface OneConfig {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// Default configuration values
|
|
26
|
-
const DEFAULT_ENGINE_URL = 'https://api.one23.io
|
|
26
|
+
const DEFAULT_ENGINE_URL = 'https://api.one23.io';
|
|
27
27
|
const DEFAULT_CLIENT_ID = 'one_pk_e8f647bfa643fdcfaa3a23f760488e49be09f929296eed4a6c399d437d907f60';
|
|
28
28
|
|
|
29
29
|
let config: OneConfig | null = null;
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
1
|
export { useWalletBalance } from './useWalletBalance';
|
|
2
2
|
export { useTokenPrice, useTokenPrices } from './useTokenPrice';
|
|
3
|
+
|
|
4
|
+
// AI Trading Hooks
|
|
5
|
+
export {
|
|
6
|
+
useAIStrategies,
|
|
7
|
+
useAIStrategy,
|
|
8
|
+
useAIOrders,
|
|
9
|
+
useAIPortfolio,
|
|
10
|
+
useAIMarketData,
|
|
11
|
+
useAITrading,
|
|
12
|
+
setAITradingAccessToken,
|
|
13
|
+
clearAITradingAccessToken,
|
|
14
|
+
type UseAIStrategiesOptions,
|
|
15
|
+
type UseAIStrategiesResult,
|
|
16
|
+
type UseAIStrategyResult,
|
|
17
|
+
type UseAIOrdersOptions,
|
|
18
|
+
type UseAIOrdersResult,
|
|
19
|
+
type UseAIPortfolioResult,
|
|
20
|
+
type UseAIMarketDataResult,
|
|
21
|
+
type UseAITradingResult,
|
|
22
|
+
} from './useAITrading';
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Trading Hooks for ONE SDK
|
|
3
|
+
*
|
|
4
|
+
* React hooks for AI quantitative trading features.
|
|
5
|
+
* These hooks provide easy access to AI strategies, orders, and portfolio management.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useState, useEffect, useCallback, useMemo } from 'react';
|
|
9
|
+
import { createOneEngineClient, OneEngineClient } from '../services/engine';
|
|
10
|
+
import type {
|
|
11
|
+
AIStrategy,
|
|
12
|
+
AIOrder,
|
|
13
|
+
AIOrderStatus,
|
|
14
|
+
AIPortfolioSummary,
|
|
15
|
+
AITradeAllocation,
|
|
16
|
+
AINavSnapshot,
|
|
17
|
+
AIMarketData,
|
|
18
|
+
CreateAIOrderRequest,
|
|
19
|
+
StrategyCategory,
|
|
20
|
+
ApiResponse,
|
|
21
|
+
} from '../types';
|
|
22
|
+
|
|
23
|
+
// Singleton client instance
|
|
24
|
+
let clientInstance: OneEngineClient | null = null;
|
|
25
|
+
|
|
26
|
+
function getClient(): OneEngineClient {
|
|
27
|
+
if (!clientInstance) {
|
|
28
|
+
clientInstance = createOneEngineClient();
|
|
29
|
+
}
|
|
30
|
+
return clientInstance;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Set the access token for authenticated requests
|
|
35
|
+
*/
|
|
36
|
+
export function setAITradingAccessToken(token: string) {
|
|
37
|
+
getClient().setAccessToken(token);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Clear the access token
|
|
42
|
+
*/
|
|
43
|
+
export function clearAITradingAccessToken() {
|
|
44
|
+
getClient().clearAccessToken();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ============================================
|
|
48
|
+
// AI Strategies Hooks
|
|
49
|
+
// ============================================
|
|
50
|
+
|
|
51
|
+
export interface UseAIStrategiesOptions {
|
|
52
|
+
category?: StrategyCategory;
|
|
53
|
+
riskLevel?: number;
|
|
54
|
+
minTvl?: number;
|
|
55
|
+
isActive?: boolean;
|
|
56
|
+
autoRefresh?: boolean;
|
|
57
|
+
refreshInterval?: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface UseAIStrategiesResult {
|
|
61
|
+
strategies: AIStrategy[];
|
|
62
|
+
isLoading: boolean;
|
|
63
|
+
error: string | null;
|
|
64
|
+
refresh: () => Promise<void>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Hook to fetch and manage AI trading strategies
|
|
69
|
+
*/
|
|
70
|
+
export function useAIStrategies(options: UseAIStrategiesOptions = {}): UseAIStrategiesResult {
|
|
71
|
+
const [strategies, setStrategies] = useState<AIStrategy[]>([]);
|
|
72
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
73
|
+
const [error, setError] = useState<string | null>(null);
|
|
74
|
+
|
|
75
|
+
const { category, riskLevel, minTvl, isActive, autoRefresh = false, refreshInterval = 60000 } = options;
|
|
76
|
+
|
|
77
|
+
const fetchStrategies = useCallback(async () => {
|
|
78
|
+
setIsLoading(true);
|
|
79
|
+
setError(null);
|
|
80
|
+
try {
|
|
81
|
+
const result = await getClient().getAIStrategies({ category, riskLevel, minTvl, isActive });
|
|
82
|
+
if (result.success && result.data?.strategies) {
|
|
83
|
+
setStrategies(result.data.strategies);
|
|
84
|
+
} else {
|
|
85
|
+
setError(result.error?.message || 'Failed to fetch strategies');
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
89
|
+
} finally {
|
|
90
|
+
setIsLoading(false);
|
|
91
|
+
}
|
|
92
|
+
}, [category, riskLevel, minTvl, isActive]);
|
|
93
|
+
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
fetchStrategies();
|
|
96
|
+
}, [fetchStrategies]);
|
|
97
|
+
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (autoRefresh && refreshInterval > 0) {
|
|
100
|
+
const interval = setInterval(fetchStrategies, refreshInterval);
|
|
101
|
+
return () => clearInterval(interval);
|
|
102
|
+
}
|
|
103
|
+
}, [autoRefresh, refreshInterval, fetchStrategies]);
|
|
104
|
+
|
|
105
|
+
return { strategies, isLoading, error, refresh: fetchStrategies };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Hook to fetch a single AI strategy with performance data
|
|
110
|
+
*/
|
|
111
|
+
export interface UseAIStrategyResult {
|
|
112
|
+
strategy: AIStrategy | null;
|
|
113
|
+
performance: AINavSnapshot[];
|
|
114
|
+
marketData: AIMarketData[];
|
|
115
|
+
isLoading: boolean;
|
|
116
|
+
error: string | null;
|
|
117
|
+
refresh: () => Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function useAIStrategy(
|
|
121
|
+
strategyId: string | undefined,
|
|
122
|
+
include: ('performance' | 'market' | 'trades')[] = ['performance', 'market']
|
|
123
|
+
): UseAIStrategyResult {
|
|
124
|
+
const [strategy, setStrategy] = useState<AIStrategy | null>(null);
|
|
125
|
+
const [performance, setPerformance] = useState<AINavSnapshot[]>([]);
|
|
126
|
+
const [marketData, setMarketData] = useState<AIMarketData[]>([]);
|
|
127
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
128
|
+
const [error, setError] = useState<string | null>(null);
|
|
129
|
+
|
|
130
|
+
const fetchStrategy = useCallback(async () => {
|
|
131
|
+
if (!strategyId) {
|
|
132
|
+
setIsLoading(false);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
setIsLoading(true);
|
|
137
|
+
setError(null);
|
|
138
|
+
try {
|
|
139
|
+
const result = await getClient().getAIStrategy(strategyId, include);
|
|
140
|
+
if (result.success && result.data) {
|
|
141
|
+
setStrategy(result.data.strategy);
|
|
142
|
+
setPerformance(result.data.performance || []);
|
|
143
|
+
setMarketData(result.data.marketData || []);
|
|
144
|
+
} else {
|
|
145
|
+
setError(result.error?.message || 'Failed to fetch strategy');
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
149
|
+
} finally {
|
|
150
|
+
setIsLoading(false);
|
|
151
|
+
}
|
|
152
|
+
}, [strategyId, include.join(',')]);
|
|
153
|
+
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
fetchStrategy();
|
|
156
|
+
}, [fetchStrategy]);
|
|
157
|
+
|
|
158
|
+
return { strategy, performance, marketData, isLoading, error, refresh: fetchStrategy };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================
|
|
162
|
+
// AI Orders Hooks
|
|
163
|
+
// ============================================
|
|
164
|
+
|
|
165
|
+
export interface UseAIOrdersOptions {
|
|
166
|
+
strategyId?: string;
|
|
167
|
+
status?: AIOrderStatus;
|
|
168
|
+
autoRefresh?: boolean;
|
|
169
|
+
refreshInterval?: number;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface UseAIOrdersResult {
|
|
173
|
+
orders: AIOrder[];
|
|
174
|
+
isLoading: boolean;
|
|
175
|
+
error: string | null;
|
|
176
|
+
refresh: () => Promise<void>;
|
|
177
|
+
createOrder: (request: CreateAIOrderRequest) => Promise<ApiResponse<{ order: AIOrder }>>;
|
|
178
|
+
pauseOrder: (orderId: string) => Promise<ApiResponse<{ order: AIOrder; message: string }>>;
|
|
179
|
+
resumeOrder: (orderId: string) => Promise<ApiResponse<{ order: AIOrder; message: string }>>;
|
|
180
|
+
redeemOrder: (orderId: string) => Promise<ApiResponse<any>>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Hook to manage AI trading orders
|
|
185
|
+
*/
|
|
186
|
+
export function useAIOrders(options: UseAIOrdersOptions = {}): UseAIOrdersResult {
|
|
187
|
+
const [orders, setOrders] = useState<AIOrder[]>([]);
|
|
188
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
189
|
+
const [error, setError] = useState<string | null>(null);
|
|
190
|
+
|
|
191
|
+
const { strategyId, status, autoRefresh = true, refreshInterval = 30000 } = options;
|
|
192
|
+
|
|
193
|
+
const fetchOrders = useCallback(async () => {
|
|
194
|
+
setIsLoading(true);
|
|
195
|
+
setError(null);
|
|
196
|
+
try {
|
|
197
|
+
const result = await getClient().getAIOrders({ strategyId, status });
|
|
198
|
+
if (result.success && result.data?.orders) {
|
|
199
|
+
setOrders(result.data.orders);
|
|
200
|
+
} else {
|
|
201
|
+
setError(result.error?.message || 'Failed to fetch orders');
|
|
202
|
+
}
|
|
203
|
+
} catch (err) {
|
|
204
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
205
|
+
} finally {
|
|
206
|
+
setIsLoading(false);
|
|
207
|
+
}
|
|
208
|
+
}, [strategyId, status]);
|
|
209
|
+
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
fetchOrders();
|
|
212
|
+
}, [fetchOrders]);
|
|
213
|
+
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
if (autoRefresh && refreshInterval > 0) {
|
|
216
|
+
const interval = setInterval(fetchOrders, refreshInterval);
|
|
217
|
+
return () => clearInterval(interval);
|
|
218
|
+
}
|
|
219
|
+
}, [autoRefresh, refreshInterval, fetchOrders]);
|
|
220
|
+
|
|
221
|
+
const createOrder = useCallback(async (request: CreateAIOrderRequest) => {
|
|
222
|
+
const result = await getClient().createAIOrder(request);
|
|
223
|
+
if (result.success) {
|
|
224
|
+
await fetchOrders(); // Refresh orders list
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}, [fetchOrders]);
|
|
228
|
+
|
|
229
|
+
const pauseOrder = useCallback(async (orderId: string) => {
|
|
230
|
+
const result = await getClient().pauseAIOrder(orderId);
|
|
231
|
+
if (result.success) {
|
|
232
|
+
await fetchOrders();
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}, [fetchOrders]);
|
|
236
|
+
|
|
237
|
+
const resumeOrder = useCallback(async (orderId: string) => {
|
|
238
|
+
const result = await getClient().resumeAIOrder(orderId);
|
|
239
|
+
if (result.success) {
|
|
240
|
+
await fetchOrders();
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}, [fetchOrders]);
|
|
244
|
+
|
|
245
|
+
const redeemOrder = useCallback(async (orderId: string) => {
|
|
246
|
+
const result = await getClient().redeemAIOrder(orderId);
|
|
247
|
+
if (result.success) {
|
|
248
|
+
await fetchOrders();
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}, [fetchOrders]);
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
orders,
|
|
255
|
+
isLoading,
|
|
256
|
+
error,
|
|
257
|
+
refresh: fetchOrders,
|
|
258
|
+
createOrder,
|
|
259
|
+
pauseOrder,
|
|
260
|
+
resumeOrder,
|
|
261
|
+
redeemOrder,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ============================================
|
|
266
|
+
// AI Portfolio Hooks
|
|
267
|
+
// ============================================
|
|
268
|
+
|
|
269
|
+
export interface UseAIPortfolioResult {
|
|
270
|
+
portfolio: AIPortfolioSummary | null;
|
|
271
|
+
allocations: AITradeAllocation[];
|
|
272
|
+
activeOrders: AIOrder[];
|
|
273
|
+
isLoading: boolean;
|
|
274
|
+
error: string | null;
|
|
275
|
+
refresh: () => Promise<void>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Hook to fetch AI trading portfolio summary
|
|
280
|
+
*/
|
|
281
|
+
export function useAIPortfolio(autoRefresh = true): UseAIPortfolioResult {
|
|
282
|
+
const [portfolio, setPortfolio] = useState<AIPortfolioSummary | null>(null);
|
|
283
|
+
const [allocations, setAllocations] = useState<AITradeAllocation[]>([]);
|
|
284
|
+
const [activeOrders, setActiveOrders] = useState<AIOrder[]>([]);
|
|
285
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
286
|
+
const [error, setError] = useState<string | null>(null);
|
|
287
|
+
|
|
288
|
+
const fetchPortfolio = useCallback(async () => {
|
|
289
|
+
setIsLoading(true);
|
|
290
|
+
setError(null);
|
|
291
|
+
try {
|
|
292
|
+
const result = await getClient().getAIPortfolio(['allocations', 'orders']);
|
|
293
|
+
if (result.success && result.data) {
|
|
294
|
+
setPortfolio(result.data.portfolio);
|
|
295
|
+
setAllocations(result.data.allocations || []);
|
|
296
|
+
setActiveOrders(result.data.orders || []);
|
|
297
|
+
} else {
|
|
298
|
+
setError(result.error?.message || 'Failed to fetch portfolio');
|
|
299
|
+
}
|
|
300
|
+
} catch (err) {
|
|
301
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
302
|
+
} finally {
|
|
303
|
+
setIsLoading(false);
|
|
304
|
+
}
|
|
305
|
+
}, []);
|
|
306
|
+
|
|
307
|
+
useEffect(() => {
|
|
308
|
+
fetchPortfolio();
|
|
309
|
+
}, [fetchPortfolio]);
|
|
310
|
+
|
|
311
|
+
useEffect(() => {
|
|
312
|
+
if (autoRefresh) {
|
|
313
|
+
const interval = setInterval(fetchPortfolio, 30000);
|
|
314
|
+
return () => clearInterval(interval);
|
|
315
|
+
}
|
|
316
|
+
}, [autoRefresh, fetchPortfolio]);
|
|
317
|
+
|
|
318
|
+
return { portfolio, allocations, activeOrders, isLoading, error, refresh: fetchPortfolio };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// ============================================
|
|
322
|
+
// AI Market Data Hook
|
|
323
|
+
// ============================================
|
|
324
|
+
|
|
325
|
+
export interface UseAIMarketDataResult {
|
|
326
|
+
prices: Record<string, { price: number; change24h: number }>;
|
|
327
|
+
isLoading: boolean;
|
|
328
|
+
error: string | null;
|
|
329
|
+
refresh: () => Promise<void>;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Hook to fetch real-time market data for AI trading pairs
|
|
334
|
+
*/
|
|
335
|
+
export function useAIMarketData(
|
|
336
|
+
symbols: string[] = ['BTC', 'ETH', 'BNB', 'SOL', 'XRP', 'DOGE', 'ADA', 'AVAX'],
|
|
337
|
+
autoRefresh = true
|
|
338
|
+
): UseAIMarketDataResult {
|
|
339
|
+
const [prices, setPrices] = useState<Record<string, { price: number; change24h: number }>>({});
|
|
340
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
341
|
+
const [error, setError] = useState<string | null>(null);
|
|
342
|
+
|
|
343
|
+
const fetchPrices = useCallback(async () => {
|
|
344
|
+
setIsLoading(true);
|
|
345
|
+
setError(null);
|
|
346
|
+
try {
|
|
347
|
+
const result = await getClient().getTokenPrices(symbols);
|
|
348
|
+
if (result.success && result.data) {
|
|
349
|
+
setPrices(result.data);
|
|
350
|
+
} else {
|
|
351
|
+
setError(result.error?.message || 'Failed to fetch prices');
|
|
352
|
+
}
|
|
353
|
+
} catch (err) {
|
|
354
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
355
|
+
} finally {
|
|
356
|
+
setIsLoading(false);
|
|
357
|
+
}
|
|
358
|
+
}, [symbols.join(',')]);
|
|
359
|
+
|
|
360
|
+
useEffect(() => {
|
|
361
|
+
fetchPrices();
|
|
362
|
+
}, [fetchPrices]);
|
|
363
|
+
|
|
364
|
+
useEffect(() => {
|
|
365
|
+
if (autoRefresh) {
|
|
366
|
+
const interval = setInterval(fetchPrices, 15000); // Update every 15 seconds
|
|
367
|
+
return () => clearInterval(interval);
|
|
368
|
+
}
|
|
369
|
+
}, [autoRefresh, fetchPrices]);
|
|
370
|
+
|
|
371
|
+
return { prices, isLoading, error, refresh: fetchPrices };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ============================================
|
|
375
|
+
// Combined AI Trading Hook
|
|
376
|
+
// ============================================
|
|
377
|
+
|
|
378
|
+
export interface UseAITradingResult {
|
|
379
|
+
// Strategies
|
|
380
|
+
strategies: AIStrategy[];
|
|
381
|
+
strategiesLoading: boolean;
|
|
382
|
+
|
|
383
|
+
// Orders
|
|
384
|
+
orders: AIOrder[];
|
|
385
|
+
ordersLoading: boolean;
|
|
386
|
+
|
|
387
|
+
// Portfolio
|
|
388
|
+
portfolio: AIPortfolioSummary | null;
|
|
389
|
+
portfolioLoading: boolean;
|
|
390
|
+
|
|
391
|
+
// Market Data
|
|
392
|
+
prices: Record<string, { price: number; change24h: number }>;
|
|
393
|
+
|
|
394
|
+
// Actions
|
|
395
|
+
createOrder: (request: CreateAIOrderRequest) => Promise<ApiResponse<{ order: AIOrder }>>;
|
|
396
|
+
pauseOrder: (orderId: string) => Promise<ApiResponse<{ order: AIOrder; message: string }>>;
|
|
397
|
+
resumeOrder: (orderId: string) => Promise<ApiResponse<{ order: AIOrder; message: string }>>;
|
|
398
|
+
redeemOrder: (orderId: string) => Promise<ApiResponse<any>>;
|
|
399
|
+
|
|
400
|
+
// Refresh
|
|
401
|
+
refreshAll: () => Promise<void>;
|
|
402
|
+
|
|
403
|
+
// Error
|
|
404
|
+
error: string | null;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Combined hook for all AI trading functionality
|
|
409
|
+
*/
|
|
410
|
+
export function useAITrading(): UseAITradingResult {
|
|
411
|
+
const strategiesResult = useAIStrategies({ autoRefresh: true });
|
|
412
|
+
const ordersResult = useAIOrders({ autoRefresh: true });
|
|
413
|
+
const portfolioResult = useAIPortfolio(true);
|
|
414
|
+
const marketResult = useAIMarketData();
|
|
415
|
+
|
|
416
|
+
const refreshAll = useCallback(async () => {
|
|
417
|
+
await Promise.all([
|
|
418
|
+
strategiesResult.refresh(),
|
|
419
|
+
ordersResult.refresh(),
|
|
420
|
+
portfolioResult.refresh(),
|
|
421
|
+
marketResult.refresh(),
|
|
422
|
+
]);
|
|
423
|
+
}, [strategiesResult.refresh, ordersResult.refresh, portfolioResult.refresh, marketResult.refresh]);
|
|
424
|
+
|
|
425
|
+
const error = useMemo(() => {
|
|
426
|
+
return strategiesResult.error || ordersResult.error || portfolioResult.error || marketResult.error;
|
|
427
|
+
}, [strategiesResult.error, ordersResult.error, portfolioResult.error, marketResult.error]);
|
|
428
|
+
|
|
429
|
+
return {
|
|
430
|
+
strategies: strategiesResult.strategies,
|
|
431
|
+
strategiesLoading: strategiesResult.isLoading,
|
|
432
|
+
orders: ordersResult.orders,
|
|
433
|
+
ordersLoading: ordersResult.isLoading,
|
|
434
|
+
portfolio: portfolioResult.portfolio,
|
|
435
|
+
portfolioLoading: portfolioResult.isLoading,
|
|
436
|
+
prices: marketResult.prices,
|
|
437
|
+
createOrder: ordersResult.createOrder,
|
|
438
|
+
pauseOrder: ordersResult.pauseOrder,
|
|
439
|
+
resumeOrder: ordersResult.resumeOrder,
|
|
440
|
+
redeemOrder: ordersResult.redeemOrder,
|
|
441
|
+
refreshAll,
|
|
442
|
+
error,
|
|
443
|
+
};
|
|
444
|
+
}
|