@yuants/vendor-turboflow 1.1.1 → 1.2.1

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 (56) hide show
  1. package/.rush/temp/chunked-rush-logs/vendor-turboflow.build.chunks.jsonl +5 -5
  2. package/.rush/temp/operation/build/all.log +5 -5
  3. package/.rush/temp/operation/build/log-chunks.jsonl +5 -5
  4. package/.rush/temp/operation/build/state.json +1 -1
  5. package/.rush/temp/shrinkwrap-deps.json +1 -1
  6. package/CHANGELOG.json +34 -0
  7. package/CHANGELOG.md +15 -1
  8. package/README.md +134 -0
  9. package/lib/api/private-api.d.ts +3 -3
  10. package/lib/api/private-api.d.ts.map +1 -1
  11. package/lib/api/private-api.js +14 -16
  12. package/lib/api/private-api.js.map +1 -1
  13. package/lib/api/public-api.d.ts +31 -0
  14. package/lib/api/public-api.d.ts.map +1 -0
  15. package/lib/api/public-api.js +29 -0
  16. package/lib/api/public-api.js.map +1 -0
  17. package/lib/index.d.ts +1 -0
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +2 -0
  20. package/lib/index.js.map +1 -1
  21. package/lib/services/exchange.d.ts +2 -0
  22. package/lib/services/exchange.d.ts.map +1 -0
  23. package/lib/services/exchange.js +96 -0
  24. package/lib/services/exchange.js.map +1 -0
  25. package/lib/services/order-actions-with-credential.d.ts +2 -0
  26. package/lib/services/order-actions-with-credential.d.ts.map +1 -0
  27. package/lib/services/order-actions-with-credential.js +25 -0
  28. package/lib/services/order-actions-with-credential.js.map +1 -0
  29. package/lib/services/orders/cancelOrder.d.ts +4 -0
  30. package/lib/services/orders/cancelOrder.d.ts.map +1 -0
  31. package/lib/services/orders/cancelOrder.js +35 -0
  32. package/lib/services/orders/cancelOrder.js.map +1 -0
  33. package/lib/services/orders/listOrders.d.ts +7 -0
  34. package/lib/services/orders/listOrders.d.ts.map +1 -0
  35. package/lib/services/orders/listOrders.js +64 -0
  36. package/lib/services/orders/listOrders.js.map +1 -0
  37. package/lib/services/orders/modifyOrder.d.ts +4 -0
  38. package/lib/services/orders/modifyOrder.d.ts.map +1 -0
  39. package/lib/services/orders/modifyOrder.js +46 -0
  40. package/lib/services/orders/modifyOrder.js.map +1 -0
  41. package/lib/services/orders/submitOrder.d.ts +6 -0
  42. package/lib/services/orders/submitOrder.d.ts.map +1 -0
  43. package/lib/services/orders/submitOrder.js +63 -0
  44. package/lib/services/orders/submitOrder.js.map +1 -0
  45. package/package.json +5 -1
  46. package/rush-logs/vendor-turboflow.build.log +5 -5
  47. package/src/api/private-api.ts +28 -20
  48. package/src/api/public-api.ts +65 -0
  49. package/src/index.ts +1 -0
  50. package/src/services/exchange.ts +107 -0
  51. package/src/services/order-actions-with-credential.ts +30 -0
  52. package/src/services/orders/cancelOrder.ts +36 -0
  53. package/src/services/orders/listOrders.ts +67 -0
  54. package/src/services/orders/modifyOrder.ts +46 -0
  55. package/src/services/orders/submitOrder.ts +64 -0
  56. package/temp/package-deps.json +18 -6
@@ -0,0 +1,107 @@
1
+ import { IPosition, makeSpotPosition } from '@yuants/data-account';
2
+ import { IOrder } from '@yuants/data-order';
3
+ import { provideExchangeServices } from '@yuants/exchange';
4
+ import { Terminal } from '@yuants/protocol';
5
+ import { getAccountAssets, getAccountInfo, getPositionList, ICredential } from '../api/private-api';
6
+ import { encodePath } from '@yuants/utils';
7
+ import { submitOrder } from './orders/submitOrder';
8
+ import { modifyOrder } from './orders/modifyOrder';
9
+ import { cancelOrderAction } from './orders/cancelOrder';
10
+ import { listOrders } from './orders/listOrders';
11
+ import { getPoolPairList } from '../api/public-api';
12
+ import { IProduct } from '@yuants/data-product';
13
+
14
+ const terminal = Terminal.fromNodeEnv();
15
+
16
+ provideExchangeServices<ICredential>(terminal, {
17
+ name: 'TURBOFLOW',
18
+ credentialSchema: {
19
+ type: 'object',
20
+ required: ['private_key'],
21
+ properties: {
22
+ private_key: {
23
+ type: 'string',
24
+ description: 'ED25519 Private Key (base58 encoded)',
25
+ },
26
+ },
27
+ },
28
+ getCredentialId: async function (credential): Promise<string> {
29
+ const accountInfo = await getAccountInfo(credential);
30
+
31
+ return encodePath('TURBOFLOW', accountInfo.data.account_id);
32
+ },
33
+ listProducts: async () => {
34
+ const data = await getPoolPairList();
35
+ return data.data.map(
36
+ (pair): IProduct => ({
37
+ datasource_id: 'TURBOFLOW',
38
+ product_id: encodePath('TURBOFLOW', 'PERP', pair.base_token, pair.pair_id),
39
+ name: `${pair.base_token}-${pair.quote_token}`,
40
+ quote_currency: pair.quote_token,
41
+ base_currency: pair.base_token,
42
+ price_step: 1e-15,
43
+ volume_step: 1e-15,
44
+ value_scale: 1,
45
+ value_scale_unit: '',
46
+ margin_rate: 1 / pair.max_leverage,
47
+ value_based_cost: 0,
48
+ volume_based_cost: 0,
49
+ max_position: 0,
50
+ max_volume: 0,
51
+ allow_long: true,
52
+ allow_short: true,
53
+ }),
54
+ );
55
+ },
56
+ getPositions: async function (credential) {
57
+ const assetsResponse = await getAccountAssets(credential, {
58
+ fill_coin_sub_info: '1',
59
+ });
60
+
61
+ const assetPositions = assetsResponse.data.list.map((x) =>
62
+ makeSpotPosition({
63
+ position_id: x.coin_code,
64
+ product_id: encodePath('SPOT', x.coin_name),
65
+ volume: parseFloat(x.available_balance),
66
+ free_volume: parseFloat(x.available_balance),
67
+ closable_price: 1,
68
+ }),
69
+ );
70
+
71
+ const positionsResponse = await getPositionList(credential, { status: 'Holding' });
72
+
73
+ const positions: IPosition[] = (positionsResponse.data.data || []).map((position) => {
74
+ const side = position.side === 1 ? 'LONG' : 'SHORT';
75
+ const holdSize = parseFloat(position.hold_size);
76
+ const holdAv = parseFloat(position.hold_av);
77
+ const unpnl = parseFloat(position.unpnl);
78
+ const im = parseFloat(position.im);
79
+
80
+ return {
81
+ position_id: position.id,
82
+ datasource_id: 'TURBOFLOW',
83
+ product_id: encodePath('TURBOFLOW', 'PERP', position.symbol, position.pair_id),
84
+ direction: side,
85
+ volume: holdSize,
86
+ free_volume: holdSize, // Assuming all volume is free
87
+ position_price: holdAv,
88
+ closable_price: holdAv,
89
+ floating_profit: unpnl,
90
+ valuation: holdSize * holdAv,
91
+ margin: im,
92
+ };
93
+ });
94
+
95
+ return [...assetPositions, ...positions];
96
+ },
97
+ getOrders: listOrders,
98
+ getPositionsByProductId: function (credential: ICredential, product_id: string): Promise<IPosition[]> {
99
+ throw new Error('Function not implemented.');
100
+ },
101
+ getOrdersByProductId: function (credential: ICredential, product_id: string): Promise<IOrder[]> {
102
+ throw new Error('Function not implemented.');
103
+ },
104
+ submitOrder: submitOrder,
105
+ modifyOrder: modifyOrder,
106
+ cancelOrder: cancelOrderAction,
107
+ });
@@ -0,0 +1,30 @@
1
+ import { provideOrderActionsWithCredential } from '@yuants/data-order';
2
+ import { Terminal } from '@yuants/protocol';
3
+ import { ICredential } from '../api/private-api';
4
+ import { cancelOrderAction } from './orders/cancelOrder';
5
+ import { listOrders } from './orders/listOrders';
6
+ import { modifyOrder } from './orders/modifyOrder';
7
+ import { submitOrder } from './orders/submitOrder';
8
+
9
+ const terminal = Terminal.fromNodeEnv();
10
+
11
+ provideOrderActionsWithCredential<ICredential>(
12
+ terminal,
13
+ 'TURBOFLOW',
14
+ {
15
+ type: 'object',
16
+ required: ['private_key'],
17
+ properties: {
18
+ private_key: {
19
+ type: 'string',
20
+ description: 'ED25519 Private Key (base58 encoded)',
21
+ },
22
+ },
23
+ },
24
+ {
25
+ submitOrder: submitOrder,
26
+ cancelOrder: cancelOrderAction,
27
+ modifyOrder: modifyOrder,
28
+ listOrders: listOrders,
29
+ },
30
+ );
@@ -0,0 +1,36 @@
1
+ import { IOrder } from '@yuants/data-order';
2
+ import { formatTime } from '@yuants/utils';
3
+ import { ICredential, cancelOrder as cancelOrderApi } from '../../api/private-api';
4
+
5
+ export const cancelOrderAction = async (credential: ICredential, order: IOrder): Promise<void> => {
6
+ console.info(`[${formatTime(Date.now())}] Cancelling order ${order.order_id}`);
7
+
8
+ // Parse product_id to get pair_id
9
+ const productParts = order.product_id.split('/');
10
+ const pair_id = productParts[productParts.length - 1];
11
+
12
+ // Parse comment for pool_id
13
+ let pool_id = 1;
14
+ if (order.comment) {
15
+ try {
16
+ const params = JSON.parse(order.comment);
17
+ pool_id = params.pool_id || 1;
18
+ } catch (e) {
19
+ console.warn(`[${formatTime(Date.now())}] Failed to parse order comment:`, e);
20
+ }
21
+ }
22
+
23
+ if (!order.order_id) {
24
+ throw new Error('order_id is required for cancelling order');
25
+ }
26
+
27
+ const response = await cancelOrderApi(credential, {
28
+ pair_id,
29
+ order_id: order.order_id,
30
+ pool_id,
31
+ });
32
+
33
+ if (response.errno !== '200') {
34
+ throw new Error(`Failed to cancel order: ${response.msg}`);
35
+ }
36
+ };
@@ -0,0 +1,67 @@
1
+ import { IOrder } from '@yuants/data-order';
2
+ import { encodePath } from '@yuants/utils';
3
+ import { ICredential, getOrderList } from '../../api/private-api';
4
+
5
+ type OrderDirection = 'OPEN_LONG' | 'OPEN_SHORT' | 'CLOSE_LONG' | 'CLOSE_SHORT';
6
+
7
+ /**
8
+ * Map TurboFlow order_way to order direction
9
+ * 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)
10
+ */
11
+ const mapOrderDirection = (order_way: number): OrderDirection => {
12
+ switch (order_way) {
13
+ case 1:
14
+ return 'OPEN_LONG';
15
+ case 2:
16
+ return 'CLOSE_SHORT';
17
+ case 3:
18
+ return 'OPEN_SHORT';
19
+ case 4:
20
+ return 'CLOSE_LONG';
21
+ default:
22
+ return 'OPEN_LONG';
23
+ }
24
+ };
25
+
26
+ /**
27
+ * Map TurboFlow order to Yuan IOrder format
28
+ */
29
+ const mapOrder = (order: any): IOrder => {
30
+ const volume = parseFloat(order.size) || 0;
31
+ const price = parseFloat(order.price) || 0;
32
+
33
+ return {
34
+ order_id: order.id,
35
+ account_id: '', // Will be filled in listOrders
36
+ product_id: encodePath('PERPETUAL', order.pair_id),
37
+ order_type: order.order_type.toUpperCase() as any,
38
+ order_direction: mapOrderDirection(order.order_way),
39
+ volume: Number.isFinite(volume) ? volume : 0,
40
+ price: Number.isFinite(price) && price > 0 ? price : undefined,
41
+ submit_at: new Date(order.created_at).getTime(),
42
+ order_status: order.order_status.toLowerCase(),
43
+ comment: JSON.stringify({
44
+ pool_id: order.pool_id,
45
+ pair_id: order.pair_id,
46
+ coin_code: order.coin_code,
47
+ leverage: order.leverage,
48
+ margin_type: order.margin_type,
49
+ fee_mode: order.fee_mode,
50
+ pos_mode: order.pos_mode,
51
+ position_id: order.position_id,
52
+ }),
53
+ };
54
+ };
55
+
56
+ /**
57
+ * List orders implementation
58
+ */
59
+ export const listOrders = async (credential: ICredential): Promise<IOrder[]> => {
60
+ const response = await getOrderList(credential, {
61
+ page_num: 1,
62
+ page_size: 100,
63
+ status: 'Pending',
64
+ });
65
+
66
+ return response.data.data.map((order) => mapOrder(order));
67
+ };
@@ -0,0 +1,46 @@
1
+ import { IOrder } from '@yuants/data-order';
2
+ import { formatTime } from '@yuants/utils';
3
+ import { ICredential, remendOrder } from '../../api/private-api';
4
+
5
+ export const modifyOrder = async (credential: ICredential, order: IOrder): Promise<void> => {
6
+ console.info(`[${formatTime(Date.now())}] Modifying order ${order.order_id}`);
7
+
8
+ try {
9
+ // Parse comment for position_id and other parameters
10
+ let position_id: string | undefined;
11
+ let tp_order: any;
12
+ let sl_order: any;
13
+
14
+ if (order.comment) {
15
+ try {
16
+ const params = JSON.parse(order.comment);
17
+ position_id = params.position_id;
18
+ tp_order = params.tp_order;
19
+ sl_order = params.sl_order;
20
+ } catch (e) {
21
+ console.warn(`[${formatTime(Date.now())}] Failed to parse order comment:`, e);
22
+ }
23
+ }
24
+
25
+ if (!position_id) {
26
+ throw new Error('position_id is required for modifying order');
27
+ }
28
+
29
+ const response = await remendOrder(credential, {
30
+ position_id,
31
+ price: order.price?.toString(),
32
+ vol: order.volume.toString(),
33
+ tp_order,
34
+ sl_order,
35
+ });
36
+
37
+ if (response.errno !== '0') {
38
+ throw new Error(`Failed to modify order: ${response.msg}`);
39
+ }
40
+
41
+ console.info(`[${formatTime(Date.now())}] Order modified successfully`);
42
+ } catch (error) {
43
+ console.error(`[${formatTime(Date.now())}] Error modifying order:`, error);
44
+ throw error;
45
+ }
46
+ };
@@ -0,0 +1,64 @@
1
+ import { IOrder } from '@yuants/data-order';
2
+ import { decodePath, formatTime, newError } from '@yuants/utils';
3
+ import { ICredential, submitOrder as submitOrderApi } from '../../api/private-api';
4
+
5
+ export const submitOrder = async (credential: ICredential, order: IOrder): Promise<{ order_id: string }> => {
6
+ // Parse product_id to get pair_id
7
+ const [, _SWAP, _NAME, pair_id] = decodePath(order.product_id);
8
+
9
+ // Determine order_way based on order_direction
10
+ // 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)
11
+ let order_way: 1 | 2 | 3 | 4;
12
+ switch (order.order_direction) {
13
+ case 'OPEN_LONG':
14
+ order_way = 1;
15
+ break;
16
+ case 'CLOSE_SHORT':
17
+ order_way = 2;
18
+ break;
19
+ case 'OPEN_SHORT':
20
+ order_way = 3;
21
+ break;
22
+ case 'CLOSE_LONG':
23
+ order_way = 4;
24
+ break;
25
+ default:
26
+ throw new Error(`Unsupported order direction: ${order.order_direction}`);
27
+ }
28
+
29
+ // Determine order_type
30
+ let order_type: 'limit' | 'market' | 'stop_limit' | 'stop_market';
31
+ switch (order.order_type) {
32
+ case 'LIMIT':
33
+ order_type = 'limit';
34
+ break;
35
+ case 'MARKET':
36
+ order_type = 'market';
37
+ break;
38
+ default:
39
+ order_type = 'limit';
40
+ }
41
+
42
+ // Build the order request
43
+
44
+ const response = await submitOrderApi(credential, {
45
+ request_id: Date.now(),
46
+ pair_id,
47
+ pool_id: 2, // usdc
48
+ coin_code: '2', // usdc
49
+ order_type,
50
+ order_way,
51
+ margin_type: 2, // Default to cross margin
52
+ leverage: 1,
53
+ vol: order.volume, // usdc value
54
+ position_mode: 1, // Default to one-way
55
+ time_in_force: 'GTC' as const,
56
+ fee_mode: 1,
57
+ order_mode: 1 as const, // Normal order
58
+ price: order.price?.toString(),
59
+ });
60
+
61
+ if (!response.data?.order) throw newError('TURBOFLOW_SUBMIT_ORDER_FAILED', { response });
62
+
63
+ return { order_id: response.data.order.id };
64
+ };
@@ -1,12 +1,24 @@
1
1
  {
2
- "apps/vendor-turboflow/CHANGELOG.json": "993957e5ec660f4096003c1304d818653157acac",
3
- "apps/vendor-turboflow/CHANGELOG.md": "45b18746bd2291a76306fd108804d0a00f7d1fde",
4
- "apps/vendor-turboflow/package.json": "a9e5c15b625bbff75184b9a62343b73e2fb15a10",
5
- "apps/vendor-turboflow/src/api/private-api.ts": "bd1289d75502eab773dbf903c50aaebb3330bbc7",
6
- "apps/vendor-turboflow/src/index.ts": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
2
+ "apps/vendor-turboflow/CHANGELOG.json": "18813dc048fa2d00e3bdfafaa7fc9e67219b12da",
3
+ "apps/vendor-turboflow/CHANGELOG.md": "d85f5a83fc01eeb1107f3a3379cb7f34fa271519",
4
+ "apps/vendor-turboflow/README.md": "084c5960ccac11196467867e63c790f6b14ca3a5",
5
+ "apps/vendor-turboflow/package.json": "feb0499078143b8eb8610f5cc967eeac042c53ae",
6
+ "apps/vendor-turboflow/src/api/private-api.ts": "4b11942303ef65e515911b1d9a8bc654f599ddf4",
7
+ "apps/vendor-turboflow/src/api/public-api.ts": "e5a8e21bf4797e56fdd6b1948b761ede54aa34eb",
8
+ "apps/vendor-turboflow/src/index.ts": "44b85b7532783f7734eaab6f90e426cb84da16eb",
9
+ "apps/vendor-turboflow/src/services/exchange.ts": "cd87240a3e66be141308cffab150e6d600315e95",
10
+ "apps/vendor-turboflow/src/services/order-actions-with-credential.ts": "65a026635484aca00a22ad1e3a37fdcc87955311",
11
+ "apps/vendor-turboflow/src/services/orders/cancelOrder.ts": "722b2cecb9d103df9e68ea54e7e0556d597d0da7",
12
+ "apps/vendor-turboflow/src/services/orders/listOrders.ts": "8e23af975d3395004b2479332a7d9e57dc4514b4",
13
+ "apps/vendor-turboflow/src/services/orders/modifyOrder.ts": "b833093cf61948efe6007cfc95583ef525201cd1",
14
+ "apps/vendor-turboflow/src/services/orders/submitOrder.ts": "c95aa70551f8ce8e6d7ff696082d26145dfc89ac",
7
15
  "apps/vendor-turboflow/tsconfig.json": "5d15ec8bd54da210724db6ed27c0f925f86ee153",
8
- "apps/vendor-turboflow/.rush/temp/shrinkwrap-deps.json": "28785b0befb5998cb952f15644f5134b770d497b",
16
+ "apps/vendor-turboflow/.rush/temp/shrinkwrap-deps.json": "4db58413c55e23c69bcd2319c8fd3f010f5487e4",
9
17
  "libraries/protocol/temp/package-deps.json": "00d9a96a90bfc0e57ef3b9547151f2970a600402",
10
18
  "libraries/utils/temp/package-deps.json": "4a683c07df7c75079b700111b9f6beb36c74ff7d",
19
+ "libraries/exchange/temp/package-deps.json": "16a4864218e5ef6afb856b728aa0751bb89cc9e8",
20
+ "libraries/data-product/temp/package-deps.json": "c9a00b88e1570374aeb333756f59975d7dcc7400",
21
+ "libraries/data-account/temp/package-deps.json": "bf8b41c4d878dab0f39ea684fffaf6bc3c74c988",
22
+ "libraries/data-order/temp/package-deps.json": "4a0272551da88c9eb52150775640b12c31786de8",
11
23
  "tools/toolkit/temp/package-deps.json": "23e053490eb8feade23e4d45de4e54883e322711"
12
24
  }