@yuants/vendor-turboflow 1.2.0 → 1.2.2

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 (48) hide show
  1. package/.rush/temp/chunked-rush-logs/vendor-turboflow.build.chunks.jsonl +7 -7
  2. package/.rush/temp/operation/build/all.log +7 -7
  3. package/.rush/temp/operation/build/log-chunks.jsonl +7 -7
  4. package/.rush/temp/operation/build/state.json +1 -1
  5. package/.rush/temp/shrinkwrap-deps.json +1 -1
  6. package/CHANGELOG.json +54 -0
  7. package/CHANGELOG.md +15 -1
  8. package/lib/api/private-api.d.ts +1 -1
  9. package/lib/api/private-api.d.ts.map +1 -1
  10. package/lib/api/private-api.js +5 -4
  11. package/lib/api/private-api.js.map +1 -1
  12. package/lib/api/public-api.d.ts +31 -0
  13. package/lib/api/public-api.d.ts.map +1 -0
  14. package/lib/api/public-api.js +29 -0
  15. package/lib/api/public-api.js.map +1 -0
  16. package/lib/index.d.ts +1 -2
  17. package/lib/index.d.ts.map +1 -1
  18. package/lib/index.js +1 -3
  19. package/lib/index.js.map +1 -1
  20. package/lib/services/exchange.d.ts +2 -0
  21. package/lib/services/exchange.d.ts.map +1 -0
  22. package/lib/services/exchange.js +96 -0
  23. package/lib/services/exchange.js.map +1 -0
  24. package/lib/services/orders/cancelOrder.d.ts.map +1 -1
  25. package/lib/services/orders/cancelOrder.js +21 -28
  26. package/lib/services/orders/cancelOrder.js.map +1 -1
  27. package/lib/services/orders/listOrders.d.ts +2 -2
  28. package/lib/services/orders/listOrders.d.ts.map +1 -1
  29. package/lib/services/orders/listOrders.js +9 -23
  30. package/lib/services/orders/listOrders.js.map +1 -1
  31. package/lib/services/orders/submitOrder.d.ts.map +1 -1
  32. package/lib/services/orders/submitOrder.js +7 -5
  33. package/lib/services/orders/submitOrder.js.map +1 -1
  34. package/package.json +7 -5
  35. package/rush-logs/vendor-turboflow.build.log +7 -7
  36. package/src/api/private-api.ts +14 -6
  37. package/src/api/public-api.ts +65 -0
  38. package/src/index.ts +1 -3
  39. package/src/services/exchange.ts +107 -0
  40. package/src/services/orders/cancelOrder.ts +22 -29
  41. package/src/services/orders/listOrders.ts +11 -28
  42. package/src/services/orders/submitOrder.ts +6 -5
  43. package/temp/package-deps.json +17 -14
  44. package/lib/services/account-actions-with-credential.d.ts +0 -2
  45. package/lib/services/account-actions-with-credential.d.ts.map +0 -1
  46. package/lib/services/account-actions-with-credential.js +0 -60
  47. package/lib/services/account-actions-with-credential.js.map +0 -1
  48. package/src/services/account-actions-with-credential.ts +0 -76
@@ -5,37 +5,30 @@ const utils_1 = require("@yuants/utils");
5
5
  const private_api_1 = require("../../api/private-api");
6
6
  const cancelOrderAction = async (credential, order) => {
7
7
  console.info(`[${(0, utils_1.formatTime)(Date.now())}] Cancelling order ${order.order_id}`);
8
- try {
9
- // Parse product_id to get pair_id
10
- const productParts = order.product_id.split('/');
11
- const pair_id = productParts[productParts.length - 1];
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
- }
19
- catch (e) {
20
- console.warn(`[${(0, utils_1.formatTime)(Date.now())}] Failed to parse order comment:`, e);
21
- }
8
+ // Parse product_id to get pair_id
9
+ const productParts = order.product_id.split('/');
10
+ const pair_id = productParts[productParts.length - 1];
11
+ // Parse comment for pool_id
12
+ let pool_id = 1;
13
+ if (order.comment) {
14
+ try {
15
+ const params = JSON.parse(order.comment);
16
+ pool_id = params.pool_id || 1;
22
17
  }
23
- if (!order.order_id) {
24
- throw new Error('order_id is required for cancelling order');
18
+ catch (e) {
19
+ console.warn(`[${(0, utils_1.formatTime)(Date.now())}] Failed to parse order comment:`, e);
25
20
  }
26
- const response = await (0, private_api_1.cancelOrder)(credential, {
27
- pair_id,
28
- order_id: order.order_id,
29
- pool_id,
30
- });
31
- if (response.errno !== '0') {
32
- throw new Error(`Failed to cancel order: ${response.msg}`);
33
- }
34
- console.info(`[${(0, utils_1.formatTime)(Date.now())}] Order ${order.order_id} cancelled successfully`);
35
21
  }
36
- catch (error) {
37
- console.error(`[${(0, utils_1.formatTime)(Date.now())}] Error cancelling order:`, error);
38
- throw error;
22
+ if (!order.order_id) {
23
+ throw new Error('order_id is required for cancelling order');
24
+ }
25
+ const response = await (0, private_api_1.cancelOrder)(credential, {
26
+ pair_id,
27
+ order_id: order.order_id,
28
+ pool_id,
29
+ });
30
+ if (response.errno !== '200') {
31
+ throw new Error(`Failed to cancel order: ${response.msg}`);
39
32
  }
40
33
  };
41
34
  exports.cancelOrderAction = cancelOrderAction;
@@ -1 +1 @@
1
- {"version":3,"file":"cancelOrder.js","sourceRoot":"","sources":["../../../src/services/orders/cancelOrder.ts"],"names":[],"mappings":";;;AACA,yCAA2C;AAC3C,uDAAmF;AAE5E,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAuB,EAAE,KAAa,EAAiB,EAAE;IAC/F,OAAO,CAAC,IAAI,CAAC,IAAI,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,sBAAsB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE/E,IAAI;QACF,kCAAkC;QAClC,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEtD,4BAA4B;QAC5B,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,KAAK,CAAC,OAAO,EAAE;YACjB,IAAI;gBACF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;aAC/B;YAAC,OAAO,CAAC,EAAE;gBACV,OAAO,CAAC,IAAI,CAAC,IAAI,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,kCAAkC,EAAE,CAAC,CAAC,CAAC;aAC/E;SACF;QAED,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;SAC9D;QAED,MAAM,QAAQ,GAAG,MAAM,IAAA,yBAAc,EAAC,UAAU,EAAE;YAChD,OAAO;YACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO;SACR,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,KAAK,KAAK,GAAG,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;SAC5D;QAED,OAAO,CAAC,IAAI,CAAC,IAAI,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,KAAK,CAAC,QAAQ,yBAAyB,CAAC,CAAC;KAC5F;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,IAAI,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QAC5E,MAAM,KAAK,CAAC;KACb;AACH,CAAC,CAAC;AAtCW,QAAA,iBAAiB,qBAsC5B","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { formatTime } from '@yuants/utils';\nimport { ICredential, cancelOrder as cancelOrderApi } from '../../api/private-api';\n\nexport const cancelOrderAction = async (credential: ICredential, order: IOrder): Promise<void> => {\n console.info(`[${formatTime(Date.now())}] Cancelling order ${order.order_id}`);\n\n try {\n // Parse product_id to get pair_id\n const productParts = order.product_id.split('/');\n const pair_id = productParts[productParts.length - 1];\n\n // Parse comment for pool_id\n let pool_id = 1;\n if (order.comment) {\n try {\n const params = JSON.parse(order.comment);\n pool_id = params.pool_id || 1;\n } catch (e) {\n console.warn(`[${formatTime(Date.now())}] Failed to parse order comment:`, e);\n }\n }\n\n if (!order.order_id) {\n throw new Error('order_id is required for cancelling order');\n }\n\n const response = await cancelOrderApi(credential, {\n pair_id,\n order_id: order.order_id,\n pool_id,\n });\n\n if (response.errno !== '0') {\n throw new Error(`Failed to cancel order: ${response.msg}`);\n }\n\n console.info(`[${formatTime(Date.now())}] Order ${order.order_id} cancelled successfully`);\n } catch (error) {\n console.error(`[${formatTime(Date.now())}] Error cancelling order:`, error);\n throw error;\n }\n};\n"]}
1
+ {"version":3,"file":"cancelOrder.js","sourceRoot":"","sources":["../../../src/services/orders/cancelOrder.ts"],"names":[],"mappings":";;;AACA,yCAA2C;AAC3C,uDAAmF;AAE5E,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAuB,EAAE,KAAa,EAAiB,EAAE;IAC/F,OAAO,CAAC,IAAI,CAAC,IAAI,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,sBAAsB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE/E,kCAAkC;IAClC,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEtD,4BAA4B;IAC5B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,KAAK,CAAC,OAAO,EAAE;QACjB,IAAI;YACF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;SAC/B;QAAC,OAAO,CAAC,EAAE;YACV,OAAO,CAAC,IAAI,CAAC,IAAI,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,kCAAkC,EAAE,CAAC,CAAC,CAAC;SAC/E;KACF;IAED,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;KAC9D;IAED,MAAM,QAAQ,GAAG,MAAM,IAAA,yBAAc,EAAC,UAAU,EAAE;QAChD,OAAO;QACP,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;KAC5D;AACH,CAAC,CAAC;AA/BW,QAAA,iBAAiB,qBA+B5B","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { formatTime } from '@yuants/utils';\nimport { ICredential, cancelOrder as cancelOrderApi } from '../../api/private-api';\n\nexport const cancelOrderAction = async (credential: ICredential, order: IOrder): Promise<void> => {\n console.info(`[${formatTime(Date.now())}] Cancelling order ${order.order_id}`);\n\n // Parse product_id to get pair_id\n const productParts = order.product_id.split('/');\n const pair_id = productParts[productParts.length - 1];\n\n // Parse comment for pool_id\n let pool_id = 1;\n if (order.comment) {\n try {\n const params = JSON.parse(order.comment);\n pool_id = params.pool_id || 1;\n } catch (e) {\n console.warn(`[${formatTime(Date.now())}] Failed to parse order comment:`, e);\n }\n }\n\n if (!order.order_id) {\n throw new Error('order_id is required for cancelling order');\n }\n\n const response = await cancelOrderApi(credential, {\n pair_id,\n order_id: order.order_id,\n pool_id,\n });\n\n if (response.errno !== '200') {\n throw new Error(`Failed to cancel order: ${response.msg}`);\n }\n};\n"]}
@@ -1,7 +1,7 @@
1
- import { IActionHandlerOfListOrders } from '@yuants/data-order';
1
+ import { IOrder } from '@yuants/data-order';
2
2
  import { ICredential } from '../../api/private-api';
3
3
  /**
4
4
  * List orders implementation
5
5
  */
6
- export declare const listOrders: IActionHandlerOfListOrders<ICredential>;
6
+ export declare const listOrders: (credential: ICredential) => Promise<IOrder[]>;
7
7
  //# sourceMappingURL=listOrders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listOrders.d.ts","sourceRoot":"","sources":["../../../src/services/orders/listOrders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAU,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AAqDlE;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,0BAA0B,CAAC,WAAW,CAyB9D,CAAC"}
1
+ {"version":3,"file":"listOrders.d.ts","sourceRoot":"","sources":["../../../src/services/orders/listOrders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AAqDlE;;GAEG;AACH,eAAO,MAAM,UAAU,eAAsB,WAAW,KAAG,QAAQ,MAAM,EAAE,CAQ1E,CAAC"}
@@ -24,12 +24,12 @@ const mapOrderDirection = (order_way) => {
24
24
  /**
25
25
  * Map TurboFlow order to Yuan IOrder format
26
26
  */
27
- const mapOrder = (order, account_id) => {
27
+ const mapOrder = (order) => {
28
28
  const volume = parseFloat(order.size) || 0;
29
29
  const price = parseFloat(order.price) || 0;
30
30
  return {
31
31
  order_id: order.id,
32
- account_id,
32
+ account_id: '',
33
33
  product_id: (0, utils_1.encodePath)('PERPETUAL', order.pair_id),
34
34
  order_type: order.order_type.toUpperCase(),
35
35
  order_direction: mapOrderDirection(order.order_way),
@@ -52,27 +52,13 @@ const mapOrder = (order, account_id) => {
52
52
  /**
53
53
  * List orders implementation
54
54
  */
55
- const listOrders = async (credential, account_id) => {
56
- console.info(`[${(0, utils_1.formatTime)(Date.now())}] Listing orders for account: ${account_id}`);
57
- try {
58
- // Get pending orders
59
- const response = await (0, private_api_1.getOrderList)(credential, {
60
- page_num: 1,
61
- page_size: 100,
62
- status: 'Pending',
63
- });
64
- if (response.errno !== '0') {
65
- throw new Error(`Failed to list orders: ${response.msg}`);
66
- }
67
- const orders = response.data.data.map((order) => mapOrder(order, account_id));
68
- console.info(`[${(0, utils_1.formatTime)(Date.now())}] Found ${orders.length} orders`);
69
- return orders;
70
- }
71
- catch (error) {
72
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
73
- console.error(`[${(0, utils_1.formatTime)(Date.now())}] Failed to list orders for ${account_id}: ${errorMessage}`);
74
- throw new Error(`Failed to list orders: ${errorMessage}`);
75
- }
55
+ const listOrders = async (credential) => {
56
+ const response = await (0, private_api_1.getOrderList)(credential, {
57
+ page_num: 1,
58
+ page_size: 100,
59
+ status: 'Pending',
60
+ });
61
+ return response.data.data.map((order) => mapOrder(order));
76
62
  };
77
63
  exports.listOrders = listOrders;
78
64
  //# sourceMappingURL=listOrders.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"listOrders.js","sourceRoot":"","sources":["../../../src/services/orders/listOrders.ts"],"names":[],"mappings":"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","sourcesContent":["import { IActionHandlerOfListOrders, IOrder } from '@yuants/data-order';\nimport { encodePath, formatTime } from '@yuants/utils';\nimport { ICredential, getOrderList } from '../../api/private-api';\n\ntype OrderDirection = 'OPEN_LONG' | 'OPEN_SHORT' | 'CLOSE_LONG' | 'CLOSE_SHORT';\n\n/**\n * Map TurboFlow order_way to order direction\n * 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)\n */\nconst mapOrderDirection = (order_way: number): OrderDirection => {\n switch (order_way) {\n case 1:\n return 'OPEN_LONG';\n case 2:\n return 'CLOSE_SHORT';\n case 3:\n return 'OPEN_SHORT';\n case 4:\n return 'CLOSE_LONG';\n default:\n return 'OPEN_LONG';\n }\n};\n\n/**\n * Map TurboFlow order to Yuan IOrder format\n */\nconst mapOrder = (order: any, account_id: string): IOrder => {\n const volume = parseFloat(order.size) || 0;\n const price = parseFloat(order.price) || 0;\n\n return {\n order_id: order.id,\n account_id,\n product_id: encodePath('PERPETUAL', order.pair_id),\n order_type: order.order_type.toUpperCase() as any,\n order_direction: mapOrderDirection(order.order_way),\n volume: Number.isFinite(volume) ? volume : 0,\n price: Number.isFinite(price) && price > 0 ? price : undefined,\n submit_at: new Date(order.created_at).getTime(),\n order_status: order.order_status.toLowerCase(),\n comment: JSON.stringify({\n pool_id: order.pool_id,\n pair_id: order.pair_id,\n coin_code: order.coin_code,\n leverage: order.leverage,\n margin_type: order.margin_type,\n fee_mode: order.fee_mode,\n pos_mode: order.pos_mode,\n position_id: order.position_id,\n }),\n };\n};\n\n/**\n * List orders implementation\n */\nexport const listOrders: IActionHandlerOfListOrders<ICredential> = async (credential, account_id) => {\n console.info(`[${formatTime(Date.now())}] Listing orders for account: ${account_id}`);\n\n try {\n // Get pending orders\n const response = await getOrderList(credential, {\n page_num: 1,\n page_size: 100,\n status: 'Pending',\n });\n\n if (response.errno !== '0') {\n throw new Error(`Failed to list orders: ${response.msg}`);\n }\n\n const orders = response.data.data.map((order) => mapOrder(order, account_id));\n\n console.info(`[${formatTime(Date.now())}] Found ${orders.length} orders`);\n\n return orders;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n console.error(`[${formatTime(Date.now())}] Failed to list orders for ${account_id}: ${errorMessage}`);\n throw new Error(`Failed to list orders: ${errorMessage}`);\n }\n};\n"]}
1
+ {"version":3,"file":"listOrders.js","sourceRoot":"","sources":["../../../src/services/orders/listOrders.ts"],"names":[],"mappings":";;;AACA,yCAA2C;AAC3C,uDAAkE;AAIlE;;;GAGG;AACH,MAAM,iBAAiB,GAAG,CAAC,SAAiB,EAAkB,EAAE;IAC9D,QAAQ,SAAS,EAAE;QACjB,KAAK,CAAC;YACJ,OAAO,WAAW,CAAC;QACrB,KAAK,CAAC;YACJ,OAAO,aAAa,CAAC;QACvB,KAAK,CAAC;YACJ,OAAO,YAAY,CAAC;QACtB,KAAK,CAAC;YACJ,OAAO,YAAY,CAAC;QACtB;YACE,OAAO,WAAW,CAAC;KACtB;AACH,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,QAAQ,GAAG,CAAC,KAAU,EAAU,EAAE;IACtC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE3C,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,EAAE;QAClB,UAAU,EAAE,EAAE;QACd,UAAU,EAAE,IAAA,kBAAU,EAAC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC;QAClD,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,EAAS;QACjD,eAAe,EAAE,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC;QACnD,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QAC9D,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;QAC/C,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE;QAC9C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW,EAAE,KAAK,CAAC,WAAW;SAC/B,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACI,MAAM,UAAU,GAAG,KAAK,EAAE,UAAuB,EAAqB,EAAE;IAC7E,MAAM,QAAQ,GAAG,MAAM,IAAA,0BAAY,EAAC,UAAU,EAAE;QAC9C,QAAQ,EAAE,CAAC;QACX,SAAS,EAAE,GAAG;QACd,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC;AARW,QAAA,UAAU,cAQrB","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { encodePath } from '@yuants/utils';\nimport { ICredential, getOrderList } from '../../api/private-api';\n\ntype OrderDirection = 'OPEN_LONG' | 'OPEN_SHORT' | 'CLOSE_LONG' | 'CLOSE_SHORT';\n\n/**\n * Map TurboFlow order_way to order direction\n * 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)\n */\nconst mapOrderDirection = (order_way: number): OrderDirection => {\n switch (order_way) {\n case 1:\n return 'OPEN_LONG';\n case 2:\n return 'CLOSE_SHORT';\n case 3:\n return 'OPEN_SHORT';\n case 4:\n return 'CLOSE_LONG';\n default:\n return 'OPEN_LONG';\n }\n};\n\n/**\n * Map TurboFlow order to Yuan IOrder format\n */\nconst mapOrder = (order: any): IOrder => {\n const volume = parseFloat(order.size) || 0;\n const price = parseFloat(order.price) || 0;\n\n return {\n order_id: order.id,\n account_id: '', // Will be filled in listOrders\n product_id: encodePath('PERPETUAL', order.pair_id),\n order_type: order.order_type.toUpperCase() as any,\n order_direction: mapOrderDirection(order.order_way),\n volume: Number.isFinite(volume) ? volume : 0,\n price: Number.isFinite(price) && price > 0 ? price : undefined,\n submit_at: new Date(order.created_at).getTime(),\n order_status: order.order_status.toLowerCase(),\n comment: JSON.stringify({\n pool_id: order.pool_id,\n pair_id: order.pair_id,\n coin_code: order.coin_code,\n leverage: order.leverage,\n margin_type: order.margin_type,\n fee_mode: order.fee_mode,\n pos_mode: order.pos_mode,\n position_id: order.position_id,\n }),\n };\n};\n\n/**\n * List orders implementation\n */\nexport const listOrders = async (credential: ICredential): Promise<IOrder[]> => {\n const response = await getOrderList(credential, {\n page_num: 1,\n page_size: 100,\n status: 'Pending',\n });\n\n return response.data.data.map((order) => mapOrder(order));\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"submitOrder.d.ts","sourceRoot":"","sources":["../../../src/services/orders/submitOrder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAiC,MAAM,uBAAuB,CAAC;AAEnF,eAAO,MAAM,WAAW,eAAsB,WAAW,SAAS,MAAM,KAAG,QAAQ;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CA0DtG,CAAC"}
1
+ {"version":3,"file":"submitOrder.d.ts","sourceRoot":"","sources":["../../../src/services/orders/submitOrder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAiC,MAAM,uBAAuB,CAAC;AAEnF,eAAO,MAAM,WAAW,eAAsB,WAAW,SAAS,MAAM,KAAG,QAAQ;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CA2DtG,CAAC"}
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.submitOrder = void 0;
4
+ const utils_1 = require("@yuants/utils");
4
5
  const private_api_1 = require("../../api/private-api");
5
6
  const submitOrder = async (credential, order) => {
6
- var _a;
7
+ var _a, _b;
7
8
  // Parse product_id to get pair_id
8
- const productParts = order.product_id.split('/');
9
- const pair_id = productParts[productParts.length - 1];
9
+ const [, _SWAP, _NAME, pair_id] = (0, utils_1.decodePath)(order.product_id);
10
10
  // Determine order_way based on order_direction
11
11
  // 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)
12
12
  let order_way;
@@ -47,14 +47,16 @@ const submitOrder = async (credential, order) => {
47
47
  order_type,
48
48
  order_way,
49
49
  margin_type: 2,
50
- leverage: 100,
51
- size: order.volume.toString(),
50
+ leverage: 1,
51
+ vol: order.volume,
52
52
  position_mode: 1,
53
53
  time_in_force: 'GTC',
54
54
  fee_mode: 1,
55
55
  order_mode: 1,
56
56
  price: (_a = order.price) === null || _a === void 0 ? void 0 : _a.toString(),
57
57
  });
58
+ if (!((_b = response.data) === null || _b === void 0 ? void 0 : _b.order))
59
+ throw (0, utils_1.newError)('TURBOFLOW_SUBMIT_ORDER_FAILED', { response });
58
60
  return { order_id: response.data.order.id };
59
61
  };
60
62
  exports.submitOrder = submitOrder;
@@ -1 +1 @@
1
- {"version":3,"file":"submitOrder.js","sourceRoot":"","sources":["../../../src/services/orders/submitOrder.ts"],"names":[],"mappings":";;;AAEA,uDAAmF;AAE5E,MAAM,WAAW,GAAG,KAAK,EAAE,UAAuB,EAAE,KAAa,EAAiC,EAAE;;IACzG,kCAAkC;IAClC,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEtD,+CAA+C;IAC/C,iFAAiF;IACjF,IAAI,SAAwB,CAAC;IAC7B,QAAQ,KAAK,CAAC,eAAe,EAAE;QAC7B,KAAK,WAAW;YACd,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR,KAAK,aAAa;YAChB,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR,KAAK,YAAY;YACf,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR,KAAK,YAAY;YACf,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;KAC5E;IAED,uBAAuB;IACvB,IAAI,UAA6D,CAAC;IAClE,QAAQ,KAAK,CAAC,UAAU,EAAE;QACxB,KAAK,OAAO;YACV,UAAU,GAAG,OAAO,CAAC;YACrB,MAAM;QACR,KAAK,QAAQ;YACX,UAAU,GAAG,QAAQ,CAAC;YACtB,MAAM;QACR;YACE,UAAU,GAAG,OAAO,CAAC;KACxB;IAED,0BAA0B;IAE1B,MAAM,QAAQ,GAAG,MAAM,IAAA,yBAAc,EAAC,UAAU,EAAE;QAChD,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;QACtB,OAAO;QACP,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,GAAG;QACd,UAAU;QACV,SAAS;QACT,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,GAAG;QACb,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE;QAC7B,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,KAAc;QAC7B,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAU;QACtB,KAAK,EAAE,MAAA,KAAK,CAAC,KAAK,0CAAE,QAAQ,EAAE;KAC/B,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;AAC9C,CAAC,CAAC;AA1DW,QAAA,WAAW,eA0DtB","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { formatTime } from '@yuants/utils';\nimport { ICredential, submitOrder as submitOrderApi } from '../../api/private-api';\n\nexport const submitOrder = async (credential: ICredential, order: IOrder): Promise<{ order_id: string }> => {\n // Parse product_id to get pair_id\n const productParts = order.product_id.split('/');\n const pair_id = productParts[productParts.length - 1];\n\n // Determine order_way based on order_direction\n // 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)\n let order_way: 1 | 2 | 3 | 4;\n switch (order.order_direction) {\n case 'OPEN_LONG':\n order_way = 1;\n break;\n case 'CLOSE_SHORT':\n order_way = 2;\n break;\n case 'OPEN_SHORT':\n order_way = 3;\n break;\n case 'CLOSE_LONG':\n order_way = 4;\n break;\n default:\n throw new Error(`Unsupported order direction: ${order.order_direction}`);\n }\n\n // Determine order_type\n let order_type: 'limit' | 'market' | 'stop_limit' | 'stop_market';\n switch (order.order_type) {\n case 'LIMIT':\n order_type = 'limit';\n break;\n case 'MARKET':\n order_type = 'market';\n break;\n default:\n order_type = 'limit';\n }\n\n // Build the order request\n\n const response = await submitOrderApi(credential, {\n request_id: Date.now(),\n pair_id,\n pool_id: 2, // usdc\n coin_code: '2', // usdc\n order_type,\n order_way,\n margin_type: 2, // Default to cross margin\n leverage: 100,\n size: order.volume.toString(), // usdc value\n position_mode: 1, // Default to one-way\n time_in_force: 'GTC' as const,\n fee_mode: 1,\n order_mode: 1 as const, // Normal order\n price: order.price?.toString(),\n });\n\n return { order_id: response.data.order.id };\n};\n"]}
1
+ {"version":3,"file":"submitOrder.js","sourceRoot":"","sources":["../../../src/services/orders/submitOrder.ts"],"names":[],"mappings":";;;AACA,yCAAiE;AACjE,uDAAmF;AAE5E,MAAM,WAAW,GAAG,KAAK,EAAE,UAAuB,EAAE,KAAa,EAAiC,EAAE;;IACzG,kCAAkC;IAClC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,IAAA,kBAAU,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAE/D,+CAA+C;IAC/C,iFAAiF;IACjF,IAAI,SAAwB,CAAC;IAC7B,QAAQ,KAAK,CAAC,eAAe,EAAE;QAC7B,KAAK,WAAW;YACd,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR,KAAK,aAAa;YAChB,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR,KAAK,YAAY;YACf,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR,KAAK,YAAY;YACf,SAAS,GAAG,CAAC,CAAC;YACd,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;KAC5E;IAED,uBAAuB;IACvB,IAAI,UAA6D,CAAC;IAClE,QAAQ,KAAK,CAAC,UAAU,EAAE;QACxB,KAAK,OAAO;YACV,UAAU,GAAG,OAAO,CAAC;YACrB,MAAM;QACR,KAAK,QAAQ;YACX,UAAU,GAAG,QAAQ,CAAC;YACtB,MAAM;QACR;YACE,UAAU,GAAG,OAAO,CAAC;KACxB;IAED,0BAA0B;IAE1B,MAAM,QAAQ,GAAG,MAAM,IAAA,yBAAc,EAAC,UAAU,EAAE;QAChD,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;QACtB,OAAO;QACP,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,GAAG;QACd,UAAU;QACV,SAAS;QACT,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,CAAC;QACX,GAAG,EAAE,KAAK,CAAC,MAAM;QACjB,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,KAAc;QAC7B,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAU;QACtB,KAAK,EAAE,MAAA,KAAK,CAAC,KAAK,0CAAE,QAAQ,EAAE;KAC/B,CAAC,CAAC;IAEH,IAAI,CAAC,CAAA,MAAA,QAAQ,CAAC,IAAI,0CAAE,KAAK,CAAA;QAAE,MAAM,IAAA,gBAAQ,EAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEzF,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;AAC9C,CAAC,CAAC;AA3DW,QAAA,WAAW,eA2DtB","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { decodePath, formatTime, newError } from '@yuants/utils';\nimport { ICredential, submitOrder as submitOrderApi } from '../../api/private-api';\n\nexport const submitOrder = async (credential: ICredential, order: IOrder): Promise<{ order_id: string }> => {\n // Parse product_id to get pair_id\n const [, _SWAP, _NAME, pair_id] = decodePath(order.product_id);\n\n // Determine order_way based on order_direction\n // 1: 开多 (Open Long), 2: 平空 (Close Short), 3: 开空 (Open Short), 4: 平多 (Close Long)\n let order_way: 1 | 2 | 3 | 4;\n switch (order.order_direction) {\n case 'OPEN_LONG':\n order_way = 1;\n break;\n case 'CLOSE_SHORT':\n order_way = 2;\n break;\n case 'OPEN_SHORT':\n order_way = 3;\n break;\n case 'CLOSE_LONG':\n order_way = 4;\n break;\n default:\n throw new Error(`Unsupported order direction: ${order.order_direction}`);\n }\n\n // Determine order_type\n let order_type: 'limit' | 'market' | 'stop_limit' | 'stop_market';\n switch (order.order_type) {\n case 'LIMIT':\n order_type = 'limit';\n break;\n case 'MARKET':\n order_type = 'market';\n break;\n default:\n order_type = 'limit';\n }\n\n // Build the order request\n\n const response = await submitOrderApi(credential, {\n request_id: Date.now(),\n pair_id,\n pool_id: 2, // usdc\n coin_code: '2', // usdc\n order_type,\n order_way,\n margin_type: 2, // Default to cross margin\n leverage: 1,\n vol: order.volume, // usdc value\n position_mode: 1, // Default to one-way\n time_in_force: 'GTC' as const,\n fee_mode: 1,\n order_mode: 1 as const, // Normal order\n price: order.price?.toString(),\n });\n\n if (!response.data?.order) throw newError('TURBOFLOW_SUBMIT_ORDER_FAILED', { response });\n\n return { order_id: response.data.order.id };\n};\n"]}
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@yuants/vendor-turboflow",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "main": "lib/index.js",
5
5
  "dependencies": {
6
- "@yuants/protocol": "0.53.0",
7
- "@yuants/utils": "0.13.0",
8
- "@yuants/data-account": "0.8.2",
9
- "@yuants/data-order": "0.6.4",
6
+ "@yuants/protocol": "0.53.1",
7
+ "@yuants/utils": "0.14.0",
8
+ "@yuants/exchange": "0.1.1",
9
+ "@yuants/data-product": "0.4.20",
10
+ "@yuants/data-account": "0.8.3",
11
+ "@yuants/data-order": "0.6.5",
10
12
  "rxjs": "~7.5.6"
11
13
  },
12
14
  "devDependencies": {
@@ -6,18 +6,18 @@ Starting test
6
6
  ---- Clean started ----
7
7
  ---- Clean finished (1ms) ----
8
8
  ---- Pre-compile started ----
9
- ---- Pre-compile finished (0ms) ----
9
+ ---- Pre-compile finished (1ms) ----
10
10
  ---- Compile started ----
11
11
  [typescript] Using TypeScript version 4.7.4
12
- ---- Compile finished (3001ms) ----
12
+ ---- Compile finished (3806ms) ----
13
13
  ---- Bundle started ----
14
- ---- Bundle finished (2ms) ----
14
+ ---- Bundle finished (3ms) ----
15
15
  ---- Post-build started ----
16
16
  ---- Post-build finished (0ms) ----
17
17
  ---- Test started ----
18
- ---- Test finished (2ms) ----
19
- -------------------- Finished (3.313s) --------------------
20
- Project: @yuants/vendor-turboflow@1.2.0
18
+ ---- Test finished (1ms) ----
19
+ -------------------- Finished (4.335s) --------------------
20
+ Project: @yuants/vendor-turboflow@1.2.2
21
21
  Heft version: 0.47.11
22
22
  Node version: v22.14.0
23
- 2025-11-25T11:54:42.712Z no Dockerfile found, skip building docker image
23
+ 2025-11-28T23:59:13.571Z no Dockerfile found, skip building docker image
@@ -1,4 +1,11 @@
1
- import { decodeBase58, fromPrivateKey, HmacSHA256, scopeError, signMessageByEd25519 } from '@yuants/utils';
1
+ import {
2
+ decodeBase58,
3
+ encodeHex,
4
+ fromPrivateKey,
5
+ HmacSHA256,
6
+ scopeError,
7
+ signMessageByEd25519,
8
+ } from '@yuants/utils';
2
9
 
3
10
  export interface ICredential {
4
11
  /**
@@ -26,7 +33,7 @@ export const privateRequest = async (
26
33
 
27
34
  const publicKey = fromPrivateKey(credential.private_key).public_key;
28
35
  const publicKeyBinary = decodeBase58(publicKey);
29
- const publicKeyHex = Buffer.from(publicKeyBinary).toString('hex');
36
+ const publicKeyHex = encodeHex(publicKeyBinary);
30
37
 
31
38
  const privateKeyBinary = decodeBase58(credential.private_key);
32
39
 
@@ -43,22 +50,23 @@ export const privateRequest = async (
43
50
  const hashData = await HmacSHA256(new TextEncoder().encode(data), publicKeyBinary);
44
51
 
45
52
  const signature = signMessageByEd25519(hashData, privateKeyBinary);
46
- const signatureHex = Buffer.from(signature).toString('hex');
53
+ const signatureHex = encodeHex(signature);
47
54
 
48
55
  headers['API-KEY'] = publicKeyHex;
49
56
  headers['TIMESTAMP'] = timestamp;
50
57
  headers['SIGN'] = signatureHex;
51
58
  headers['LANG'] = 'zh-cn';
52
59
 
60
+ const body = method === 'POST' ? JSON.stringify(params) : undefined;
53
61
  const response = await fetch(url.toString(), {
54
62
  method,
55
63
  headers,
56
- body: method === 'POST' ? JSON.stringify(params) : undefined,
64
+ body,
57
65
  });
58
66
 
59
67
  const text = await response.text();
60
68
 
61
- console.info(url.toString(), headers, text);
69
+ console.info(url.toString(), headers, text, params, body);
62
70
 
63
71
  return scopeError('TurboAPIError', { status: response.status, statusText: response.statusText, text }, () =>
64
72
  JSON.parse(text),
@@ -152,7 +160,7 @@ export const submitOrder = createPrivateApi<
152
160
  order_way: 1 | 2 | 3 | 4; // 1:开多 2:平空 3:开空 4:平多
153
161
  margin_type: 1 | 2; // 1:逐仓 2:全仓
154
162
  leverage: number;
155
- size: string; // 交易数量
163
+ vol: number; // 交易数量
156
164
  position_mode: 1 | 2 | 3; // 1:单向 2:双向 3:原子
157
165
  time_in_force: 'GTC' | 'IOC' | 'FOK';
158
166
  fee_mode: 1 | 2; // 1:固定 2:利润分层
@@ -0,0 +1,65 @@
1
+ import { decodeBase58, fromPrivateKey, HmacSHA256, scopeError, signMessageByEd25519 } from '@yuants/utils';
2
+
3
+ export interface ICredential {
4
+ /**
5
+ * ED25519 Private KEY (base58)
6
+ */
7
+ private_key: string;
8
+ }
9
+
10
+ const BASE_URL = 'https://surfv2-api.surf.one';
11
+
12
+ export const publicRequest = async (method: string, path: string, params: any = {}) => {
13
+ const url = new URL(BASE_URL);
14
+ url.pathname = path;
15
+
16
+ if (method === 'GET') {
17
+ for (const [key, value] of Object.entries(params)) {
18
+ url.searchParams.set(key, `${value}`);
19
+ }
20
+ }
21
+
22
+ const response = await fetch(url.toString(), {
23
+ method,
24
+ body: method === 'POST' ? JSON.stringify(params) : undefined,
25
+ });
26
+
27
+ const text = await response.text();
28
+
29
+ console.info(url.toString(), text);
30
+
31
+ return scopeError('TurboAPIError', { status: response.status, statusText: response.statusText, text }, () =>
32
+ JSON.parse(text),
33
+ );
34
+ };
35
+
36
+ export const createPublicApi =
37
+ <T, K>(method: string, path: string) =>
38
+ (params: T): Promise<K> =>
39
+ publicRequest(method, path, params);
40
+
41
+ /**
42
+ * 获取账户信息
43
+ */
44
+ export const getPoolPairList = createPublicApi<
45
+ void,
46
+ {
47
+ errno: string;
48
+ msg: string;
49
+ data: {
50
+ pair_id: string;
51
+ base_token: string;
52
+ quote_token: string;
53
+ base_token_logo: string;
54
+ base_token_name: string;
55
+ volume_24h: string;
56
+ price: string;
57
+ c: string;
58
+ max_leverage: number;
59
+ avg_order_book_fee: string;
60
+ funding_fee_interval: number;
61
+ created_at: string;
62
+ tag_id_list: number[];
63
+ }[];
64
+ }
65
+ >('GET', '/pool/pair/list');
package/src/index.ts CHANGED
@@ -1,3 +1 @@
1
- // Import services
2
- import './services/account-actions-with-credential';
3
- import './services/order-actions-with-credential';
1
+ import './services/exchange';
@@ -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
+ });
@@ -5,39 +5,32 @@ import { ICredential, cancelOrder as cancelOrderApi } from '../../api/private-ap
5
5
  export const cancelOrderAction = async (credential: ICredential, order: IOrder): Promise<void> => {
6
6
  console.info(`[${formatTime(Date.now())}] Cancelling order ${order.order_id}`);
7
7
 
8
- try {
9
- // Parse product_id to get pair_id
10
- const productParts = order.product_id.split('/');
11
- const pair_id = productParts[productParts.length - 1];
8
+ // Parse product_id to get pair_id
9
+ const productParts = order.product_id.split('/');
10
+ const pair_id = productParts[productParts.length - 1];
12
11
 
13
- // Parse comment for pool_id
14
- let pool_id = 1;
15
- if (order.comment) {
16
- try {
17
- const params = JSON.parse(order.comment);
18
- pool_id = params.pool_id || 1;
19
- } catch (e) {
20
- console.warn(`[${formatTime(Date.now())}] Failed to parse order comment:`, e);
21
- }
22
- }
23
-
24
- if (!order.order_id) {
25
- throw new Error('order_id is required for cancelling order');
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);
26
20
  }
21
+ }
27
22
 
28
- const response = await cancelOrderApi(credential, {
29
- pair_id,
30
- order_id: order.order_id,
31
- pool_id,
32
- });
23
+ if (!order.order_id) {
24
+ throw new Error('order_id is required for cancelling order');
25
+ }
33
26
 
34
- if (response.errno !== '0') {
35
- throw new Error(`Failed to cancel order: ${response.msg}`);
36
- }
27
+ const response = await cancelOrderApi(credential, {
28
+ pair_id,
29
+ order_id: order.order_id,
30
+ pool_id,
31
+ });
37
32
 
38
- console.info(`[${formatTime(Date.now())}] Order ${order.order_id} cancelled successfully`);
39
- } catch (error) {
40
- console.error(`[${formatTime(Date.now())}] Error cancelling order:`, error);
41
- throw error;
33
+ if (response.errno !== '200') {
34
+ throw new Error(`Failed to cancel order: ${response.msg}`);
42
35
  }
43
36
  };
@@ -1,5 +1,5 @@
1
- import { IActionHandlerOfListOrders, IOrder } from '@yuants/data-order';
2
- import { encodePath, formatTime } from '@yuants/utils';
1
+ import { IOrder } from '@yuants/data-order';
2
+ import { encodePath } from '@yuants/utils';
3
3
  import { ICredential, getOrderList } from '../../api/private-api';
4
4
 
5
5
  type OrderDirection = 'OPEN_LONG' | 'OPEN_SHORT' | 'CLOSE_LONG' | 'CLOSE_SHORT';
@@ -26,13 +26,13 @@ const mapOrderDirection = (order_way: number): OrderDirection => {
26
26
  /**
27
27
  * Map TurboFlow order to Yuan IOrder format
28
28
  */
29
- const mapOrder = (order: any, account_id: string): IOrder => {
29
+ const mapOrder = (order: any): IOrder => {
30
30
  const volume = parseFloat(order.size) || 0;
31
31
  const price = parseFloat(order.price) || 0;
32
32
 
33
33
  return {
34
34
  order_id: order.id,
35
- account_id,
35
+ account_id: '', // Will be filled in listOrders
36
36
  product_id: encodePath('PERPETUAL', order.pair_id),
37
37
  order_type: order.order_type.toUpperCase() as any,
38
38
  order_direction: mapOrderDirection(order.order_way),
@@ -56,29 +56,12 @@ const mapOrder = (order: any, account_id: string): IOrder => {
56
56
  /**
57
57
  * List orders implementation
58
58
  */
59
- export const listOrders: IActionHandlerOfListOrders<ICredential> = async (credential, account_id) => {
60
- console.info(`[${formatTime(Date.now())}] Listing orders for account: ${account_id}`);
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
+ });
61
65
 
62
- try {
63
- // Get pending orders
64
- const response = await getOrderList(credential, {
65
- page_num: 1,
66
- page_size: 100,
67
- status: 'Pending',
68
- });
69
-
70
- if (response.errno !== '0') {
71
- throw new Error(`Failed to list orders: ${response.msg}`);
72
- }
73
-
74
- const orders = response.data.data.map((order) => mapOrder(order, account_id));
75
-
76
- console.info(`[${formatTime(Date.now())}] Found ${orders.length} orders`);
77
-
78
- return orders;
79
- } catch (error) {
80
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
81
- console.error(`[${formatTime(Date.now())}] Failed to list orders for ${account_id}: ${errorMessage}`);
82
- throw new Error(`Failed to list orders: ${errorMessage}`);
83
- }
66
+ return response.data.data.map((order) => mapOrder(order));
84
67
  };