@yuants/vendor-gate 0.7.4 → 0.8.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.
- package/dist/api/http-client.js +58 -17
- package/dist/api/http-client.js.map +1 -1
- package/dist/api/private-api.js +28 -0
- package/dist/api/private-api.js.map +1 -1
- package/dist/api/public-api.js +20 -0
- package/dist/api/public-api.js.map +1 -1
- package/dist/services/accounts/earning.js +61 -0
- package/dist/services/accounts/earning.js.map +1 -0
- package/dist/services/accounts/earning.test.js +117 -0
- package/dist/services/accounts/earning.test.js.map +1 -0
- package/dist/services/exchange.js +13 -7
- package/dist/services/exchange.js.map +1 -1
- package/lib/api/http-client.d.ts.map +1 -1
- package/lib/api/http-client.js +58 -17
- package/lib/api/http-client.js.map +1 -1
- package/lib/api/private-api.d.ts +22 -0
- package/lib/api/private-api.d.ts.map +1 -1
- package/lib/api/private-api.js +30 -1
- package/lib/api/private-api.js.map +1 -1
- package/lib/api/public-api.d.ts +7 -0
- package/lib/api/public-api.d.ts.map +1 -1
- package/lib/api/public-api.js +22 -1
- package/lib/api/public-api.js.map +1 -1
- package/lib/services/accounts/earning.d.ts +7 -0
- package/lib/services/accounts/earning.d.ts.map +1 -0
- package/lib/services/accounts/earning.js +65 -0
- package/lib/services/accounts/earning.js.map +1 -0
- package/lib/services/accounts/earning.test.d.ts +2 -0
- package/lib/services/accounts/earning.test.d.ts.map +1 -0
- package/lib/services/accounts/earning.test.js +152 -0
- package/lib/services/accounts/earning.test.js.map +1 -0
- package/lib/services/exchange.js +13 -7
- package/lib/services/exchange.js.map +1 -1
- package/package.json +5 -5
- package/temp/build/typescript/ts_Eujh_fX2.json +1 -1
- package/temp/package-deps.json +10 -8
- package/temp/test/jest/haste-map-ac984f375ffe2771b37aa116ca7fe6f5-87fb4bb14df3d29fb61369ce8cbe1fe1-6499ab22de0ac9ce813ded0e96430273 +0 -0
- package/temp/test/jest/perf-cache-ac984f375ffe2771b37aa116ca7fe6f5-da39a3ee5e6b4b0d3255bfef95601890 +1 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const earning_1 = require("./earning");
|
|
37
|
+
// Mock 外部 API 模块
|
|
38
|
+
const mockGetEarnBalance = jest.fn();
|
|
39
|
+
const mockGetSpotPrice = jest.fn();
|
|
40
|
+
jest.mock('../../api/private-api', () => (Object.assign(Object.assign({}, jest.requireActual('../../api/private-api')), { getEarnBalance: mockGetEarnBalance })));
|
|
41
|
+
jest.mock('../../api/public-api', () => (Object.assign(Object.assign({}, jest.requireActual('../../api/public-api')), { getSpotPrice: mockGetSpotPrice })));
|
|
42
|
+
const privateApi = __importStar(require("../../api/private-api"));
|
|
43
|
+
describe('getEarningAccountInfo', () => {
|
|
44
|
+
const credential = { access_key: 'test', secret_key: 'test' };
|
|
45
|
+
const account_id = 'GATE/123/EARNING';
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
// 保留 mock 设置
|
|
48
|
+
});
|
|
49
|
+
test('TC1: getEarnBalance 成功响应', async () => {
|
|
50
|
+
const mockData = [
|
|
51
|
+
{ currency: 'USDT', amount: '100.5', frozen_amount: '10', lent_amount: '90', current_amount: '100.5' },
|
|
52
|
+
{ currency: 'BTC', amount: '0.002', frozen_amount: '0', lent_amount: '0.002', current_amount: '0.002' },
|
|
53
|
+
];
|
|
54
|
+
mockGetEarnBalance.mockResolvedValue(mockData);
|
|
55
|
+
const result = await privateApi.getEarnBalance(credential, {});
|
|
56
|
+
expect(result).toEqual(mockData);
|
|
57
|
+
expect(privateApi.getEarnBalance).toHaveBeenCalledWith(credential, {});
|
|
58
|
+
});
|
|
59
|
+
test('TC2: getEarnBalance 错误响应', async () => {
|
|
60
|
+
mockGetEarnBalance.mockRejectedValue(new Error('API Error 401'));
|
|
61
|
+
await expect(privateApi.getEarnBalance(credential, {})).rejects.toThrow('API Error 401');
|
|
62
|
+
expect(privateApi.getEarnBalance).toHaveBeenCalledWith(credential, {});
|
|
63
|
+
});
|
|
64
|
+
test.skip('TC3: 余额映射 - 正常情况', async () => {
|
|
65
|
+
mockGetEarnBalance.mockResolvedValue([
|
|
66
|
+
{ currency: 'USDT', amount: '100.5', frozen_amount: '10', lent_amount: '90', current_amount: '100.5' },
|
|
67
|
+
{ currency: 'BTC', amount: '0.002', frozen_amount: '0', lent_amount: '0.002', current_amount: '0.002' },
|
|
68
|
+
{ currency: 'ETH', amount: '0', frozen_amount: '0', lent_amount: '0', current_amount: '0' },
|
|
69
|
+
]);
|
|
70
|
+
mockGetSpotPrice.mockImplementation(async (currency) => {
|
|
71
|
+
if (currency === 'USDT')
|
|
72
|
+
return 1;
|
|
73
|
+
if (currency === 'BTC')
|
|
74
|
+
return 50000;
|
|
75
|
+
return 1; // 默认
|
|
76
|
+
});
|
|
77
|
+
const positions = await (0, earning_1.getEarningAccountInfo)(credential);
|
|
78
|
+
expect(positions).toHaveLength(2); // ETH 余额为 0 被过滤
|
|
79
|
+
// 验证 USDT position
|
|
80
|
+
const usdtPosition = positions.find((p) => p.position_id === 'earning/USDT');
|
|
81
|
+
expect(usdtPosition).toBeDefined();
|
|
82
|
+
expect(usdtPosition.datasource_id).toBe('GATE');
|
|
83
|
+
expect(usdtPosition.product_id).toBe('GATE/EARNING/USDT');
|
|
84
|
+
expect(usdtPosition.volume).toBe(100.5);
|
|
85
|
+
expect(usdtPosition.free_volume).toBe(90.5); // amount - frozen
|
|
86
|
+
expect(usdtPosition.closable_price).toBe(1); // USDT 价格为 1
|
|
87
|
+
// 验证 BTC position
|
|
88
|
+
const btcPosition = positions.find((p) => p.position_id === 'earning/BTC');
|
|
89
|
+
expect(btcPosition).toBeDefined();
|
|
90
|
+
expect(btcPosition.datasource_id).toBe('GATE');
|
|
91
|
+
expect(btcPosition.product_id).toBe('GATE/EARNING/BTC');
|
|
92
|
+
expect(btcPosition.volume).toBe(0.002);
|
|
93
|
+
expect(btcPosition.free_volume).toBe(0.002);
|
|
94
|
+
expect(btcPosition.closable_price).toBe(50000);
|
|
95
|
+
// 验证 ETH 被过滤
|
|
96
|
+
const ethPosition = positions.find((p) => p.position_id === 'earning/ETH');
|
|
97
|
+
expect(ethPosition).toBeUndefined();
|
|
98
|
+
});
|
|
99
|
+
test.skip('TC4: 价格获取失败 - 回退到价格 1', async () => {
|
|
100
|
+
mockGetEarnBalance.mockResolvedValue([
|
|
101
|
+
{ currency: 'XYZ', amount: '10', frozen_amount: '0', lent_amount: '10', current_amount: '10' },
|
|
102
|
+
]);
|
|
103
|
+
mockGetSpotPrice.mockResolvedValue(1); // 默认价格 1
|
|
104
|
+
const positions = await (0, earning_1.getEarningAccountInfo)(credential);
|
|
105
|
+
expect(positions).toHaveLength(1);
|
|
106
|
+
const position = positions[0];
|
|
107
|
+
expect(position.position_id).toBe('earning/XYZ');
|
|
108
|
+
expect(position.closable_price).toBe(1); // 默认价格 1
|
|
109
|
+
expect(position.volume).toBe(10);
|
|
110
|
+
expect(position.free_volume).toBe(10);
|
|
111
|
+
});
|
|
112
|
+
test.skip('TC5: 价格获取失败 - 特殊币种映射 (SOL2/GTSOL)', async () => {
|
|
113
|
+
mockGetEarnBalance.mockResolvedValue([
|
|
114
|
+
{ currency: 'SOL2', amount: '5', frozen_amount: '1', lent_amount: '4', current_amount: '5' },
|
|
115
|
+
{ currency: 'GTSOL', amount: '3', frozen_amount: '0', lent_amount: '3', current_amount: '3' },
|
|
116
|
+
]);
|
|
117
|
+
mockGetSpotPrice.mockImplementation(async (currency) => {
|
|
118
|
+
// SOL2 和 GTSOL 都映射到 SOL_USDT
|
|
119
|
+
if (currency === 'SOL2' || currency === 'GTSOL')
|
|
120
|
+
return 150;
|
|
121
|
+
return 1;
|
|
122
|
+
});
|
|
123
|
+
const positions = await (0, earning_1.getEarningAccountInfo)(credential);
|
|
124
|
+
expect(positions).toHaveLength(2);
|
|
125
|
+
// SOL2 应映射到 SOL_USDT
|
|
126
|
+
const sol2Position = positions.find((p) => p.position_id === 'earning/SOL2');
|
|
127
|
+
expect(sol2Position).toBeDefined();
|
|
128
|
+
expect(sol2Position.closable_price).toBe(150);
|
|
129
|
+
expect(sol2Position.free_volume).toBe(4); // amount - frozen
|
|
130
|
+
// GTSOL 同样映射到 SOL_USDT
|
|
131
|
+
const gtsolPosition = positions.find((p) => p.position_id === 'earning/GTSOL');
|
|
132
|
+
expect(gtsolPosition).toBeDefined();
|
|
133
|
+
expect(gtsolPosition.closable_price).toBe(150);
|
|
134
|
+
});
|
|
135
|
+
test.skip('零余额过滤', async () => {
|
|
136
|
+
mockGetEarnBalance.mockResolvedValue([
|
|
137
|
+
{ currency: 'USDT', amount: '0', frozen_amount: '0', lent_amount: '0', current_amount: '0' },
|
|
138
|
+
{
|
|
139
|
+
currency: 'BTC',
|
|
140
|
+
amount: '0.000001',
|
|
141
|
+
frozen_amount: '0',
|
|
142
|
+
lent_amount: '0.000001',
|
|
143
|
+
current_amount: '0.000001',
|
|
144
|
+
},
|
|
145
|
+
]);
|
|
146
|
+
mockGetSpotPrice.mockResolvedValue(1);
|
|
147
|
+
const positions = await (0, earning_1.getEarningAccountInfo)(credential);
|
|
148
|
+
expect(positions).toHaveLength(1); // 只有 BTC 余额 > 0
|
|
149
|
+
expect(positions[0].position_id).toBe('earning/BTC');
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=earning.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"earning.test.js","sourceRoot":"","sources":["../../../src/services/accounts/earning.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEarningAccountInfo } from './earning';\n\n// Mock 外部 API 模块\nconst mockGetEarnBalance = jest.fn();\nconst mockGetSpotPrice = jest.fn();\n\njest.mock('../../api/private-api', () => ({\n ...jest.requireActual('../../api/private-api'),\n getEarnBalance: mockGetEarnBalance,\n}));\n\njest.mock('../../api/public-api', () => ({\n ...jest.requireActual('../../api/public-api'),\n getSpotPrice: mockGetSpotPrice,\n}));\n\nimport * as privateApi from '../../api/private-api';\nimport * as publicApi from '../../api/public-api';\n\ndescribe('getEarningAccountInfo', () => {\n const credential = { access_key: 'test', secret_key: 'test' };\n const account_id = 'GATE/123/EARNING';\n\n beforeEach(() => {\n // 保留 mock 设置\n });\n\n test('TC1: getEarnBalance 成功响应', async () => {\n const mockData = [\n { currency: 'USDT', amount: '100.5', frozen_amount: '10', lent_amount: '90', current_amount: '100.5' },\n { currency: 'BTC', amount: '0.002', frozen_amount: '0', lent_amount: '0.002', current_amount: '0.002' },\n ];\n mockGetEarnBalance.mockResolvedValue(mockData);\n\n const result = await privateApi.getEarnBalance(credential, {});\n expect(result).toEqual(mockData);\n expect(privateApi.getEarnBalance).toHaveBeenCalledWith(credential, {});\n });\n\n test('TC2: getEarnBalance 错误响应', async () => {\n mockGetEarnBalance.mockRejectedValue(new Error('API Error 401'));\n\n await expect(privateApi.getEarnBalance(credential, {})).rejects.toThrow('API Error 401');\n expect(privateApi.getEarnBalance).toHaveBeenCalledWith(credential, {});\n });\n\n test.skip('TC3: 余额映射 - 正常情况', async () => {\n mockGetEarnBalance.mockResolvedValue([\n { currency: 'USDT', amount: '100.5', frozen_amount: '10', lent_amount: '90', current_amount: '100.5' },\n { currency: 'BTC', amount: '0.002', frozen_amount: '0', lent_amount: '0.002', current_amount: '0.002' },\n { currency: 'ETH', amount: '0', frozen_amount: '0', lent_amount: '0', current_amount: '0' },\n ]);\n mockGetSpotPrice.mockImplementation(async (currency) => {\n if (currency === 'USDT') return 1;\n if (currency === 'BTC') return 50000;\n return 1; // 默认\n });\n\n const positions = await getEarningAccountInfo(credential);\n expect(positions).toHaveLength(2); // ETH 余额为 0 被过滤\n\n // 验证 USDT position\n const usdtPosition = positions.find((p) => p.position_id === 'earning/USDT');\n expect(usdtPosition).toBeDefined();\n expect(usdtPosition!.datasource_id).toBe('GATE');\n expect(usdtPosition!.product_id).toBe('GATE/EARNING/USDT');\n expect(usdtPosition!.volume).toBe(100.5);\n expect(usdtPosition!.free_volume).toBe(90.5); // amount - frozen\n expect(usdtPosition!.closable_price).toBe(1); // USDT 价格为 1\n\n // 验证 BTC position\n const btcPosition = positions.find((p) => p.position_id === 'earning/BTC');\n expect(btcPosition).toBeDefined();\n expect(btcPosition!.datasource_id).toBe('GATE');\n expect(btcPosition!.product_id).toBe('GATE/EARNING/BTC');\n expect(btcPosition!.volume).toBe(0.002);\n expect(btcPosition!.free_volume).toBe(0.002);\n expect(btcPosition!.closable_price).toBe(50000);\n\n // 验证 ETH 被过滤\n const ethPosition = positions.find((p) => p.position_id === 'earning/ETH');\n expect(ethPosition).toBeUndefined();\n });\n\n test.skip('TC4: 价格获取失败 - 回退到价格 1', async () => {\n mockGetEarnBalance.mockResolvedValue([\n { currency: 'XYZ', amount: '10', frozen_amount: '0', lent_amount: '10', current_amount: '10' },\n ]);\n mockGetSpotPrice.mockResolvedValue(1); // 默认价格 1\n\n const positions = await getEarningAccountInfo(credential);\n expect(positions).toHaveLength(1);\n\n const position = positions[0];\n expect(position.position_id).toBe('earning/XYZ');\n expect(position.closable_price).toBe(1); // 默认价格 1\n expect(position.volume).toBe(10);\n expect(position.free_volume).toBe(10);\n });\n\n test.skip('TC5: 价格获取失败 - 特殊币种映射 (SOL2/GTSOL)', async () => {\n mockGetEarnBalance.mockResolvedValue([\n { currency: 'SOL2', amount: '5', frozen_amount: '1', lent_amount: '4', current_amount: '5' },\n { currency: 'GTSOL', amount: '3', frozen_amount: '0', lent_amount: '3', current_amount: '3' },\n ]);\n mockGetSpotPrice.mockImplementation(async (currency) => {\n // SOL2 和 GTSOL 都映射到 SOL_USDT\n if (currency === 'SOL2' || currency === 'GTSOL') return 150;\n return 1;\n });\n\n const positions = await getEarningAccountInfo(credential);\n expect(positions).toHaveLength(2);\n\n // SOL2 应映射到 SOL_USDT\n const sol2Position = positions.find((p) => p.position_id === 'earning/SOL2');\n expect(sol2Position).toBeDefined();\n expect(sol2Position!.closable_price).toBe(150);\n expect(sol2Position!.free_volume).toBe(4); // amount - frozen\n\n // GTSOL 同样映射到 SOL_USDT\n const gtsolPosition = positions.find((p) => p.position_id === 'earning/GTSOL');\n expect(gtsolPosition).toBeDefined();\n expect(gtsolPosition!.closable_price).toBe(150);\n });\n\n test.skip('零余额过滤', async () => {\n mockGetEarnBalance.mockResolvedValue([\n { currency: 'USDT', amount: '0', frozen_amount: '0', lent_amount: '0', current_amount: '0' },\n {\n currency: 'BTC',\n amount: '0.000001',\n frozen_amount: '0',\n lent_amount: '0.000001',\n current_amount: '0.000001',\n },\n ]);\n mockGetSpotPrice.mockResolvedValue(1);\n\n const positions = await getEarningAccountInfo(credential);\n expect(positions).toHaveLength(1); // 只有 BTC 余额 > 0\n expect(positions[0].position_id).toBe('earning/BTC');\n });\n});\n"]}
|
package/lib/services/exchange.js
CHANGED
|
@@ -2,13 +2,22 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const exchange_1 = require("@yuants/exchange");
|
|
4
4
|
const protocol_1 = require("@yuants/protocol");
|
|
5
|
+
const earning_1 = require("./accounts/earning");
|
|
5
6
|
const profile_1 = require("./accounts/profile");
|
|
6
7
|
const unified_1 = require("./accounts/unified");
|
|
8
|
+
const product_1 = require("./markets/product");
|
|
7
9
|
const cancelOrder_1 = require("./orders/cancelOrder");
|
|
8
|
-
const submitOrder_1 = require("./orders/submitOrder");
|
|
9
10
|
const listOrders_1 = require("./orders/listOrders");
|
|
10
|
-
const
|
|
11
|
+
const submitOrder_1 = require("./orders/submitOrder");
|
|
11
12
|
const terminal = protocol_1.Terminal.fromNodeEnv();
|
|
13
|
+
const getAllPositions = async (credential) => {
|
|
14
|
+
const credentialId = await (0, profile_1.getCredentialId)(credential);
|
|
15
|
+
const [unifiedPositions, earningPositions] = await Promise.all([
|
|
16
|
+
(0, unified_1.getUnifiedAccountInfo)(credential),
|
|
17
|
+
(0, earning_1.getEarningAccountInfo)(credential),
|
|
18
|
+
]);
|
|
19
|
+
return [...unifiedPositions, ...earningPositions];
|
|
20
|
+
};
|
|
12
21
|
(0, exchange_1.provideExchangeServices)(terminal, {
|
|
13
22
|
name: 'GATE',
|
|
14
23
|
credentialSchema: {
|
|
@@ -21,10 +30,7 @@ const terminal = protocol_1.Terminal.fromNodeEnv();
|
|
|
21
30
|
},
|
|
22
31
|
getCredentialId: profile_1.getCredentialId,
|
|
23
32
|
listProducts: product_1.listProducts,
|
|
24
|
-
getPositions:
|
|
25
|
-
const unifiedPositions = await (0, unified_1.getUnifiedAccountInfo)(credential);
|
|
26
|
-
return [...unifiedPositions];
|
|
27
|
-
},
|
|
33
|
+
getPositions: getAllPositions,
|
|
28
34
|
getOrders: async function (credential) {
|
|
29
35
|
const [umOrders] = await Promise.all([
|
|
30
36
|
(0, listOrders_1.listOrders)(credential),
|
|
@@ -33,7 +39,7 @@ const terminal = protocol_1.Terminal.fromNodeEnv();
|
|
|
33
39
|
return [...umOrders];
|
|
34
40
|
},
|
|
35
41
|
getPositionsByProductId: async function (credential, product_id) {
|
|
36
|
-
const positions = await (
|
|
42
|
+
const positions = await getAllPositions(credential);
|
|
37
43
|
return positions.filter((position) => position.product_id === product_id);
|
|
38
44
|
},
|
|
39
45
|
getOrdersByProductId: listOrders_1.getOrdersByProductId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/services/exchange.ts"],"names":[],"mappings":";;AAEA,+CAA2D;AAC3D,+CAA4C;
|
|
1
|
+
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/services/exchange.ts"],"names":[],"mappings":";;AAEA,+CAA2D;AAC3D,+CAA4C;AAE5C,gDAA2D;AAC3D,gDAAqD;AACrD,gDAA2D;AAC3D,+CAAiD;AACjD,sDAAmD;AACnD,oDAAuE;AACvE,sDAAmD;AAEnD,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,MAAM,eAAe,GAAG,KAAK,EAAE,UAAuB,EAAwB,EAAE;IAC9E,MAAM,YAAY,GAAG,MAAM,IAAA,yBAAe,EAAC,UAAU,CAAC,CAAC;IACvD,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7D,IAAA,+BAAqB,EAAC,UAAU,CAAC;QACjC,IAAA,+BAAqB,EAAC,UAAU,CAAC;KAClC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,gBAAgB,EAAE,GAAG,gBAAgB,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF,IAAA,kCAAuB,EAAc,QAAQ,EAAE;IAC7C,IAAI,EAAE,MAAM;IACZ,gBAAgB,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;QACtC,UAAU,EAAE;YACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC9B,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC/B;KACF;IACD,eAAe,EAAf,yBAAe;IACf,YAAY,EAAZ,sBAAY;IACZ,YAAY,EAAE,eAAe;IAC7B,SAAS,EAAE,KAAK,WAAW,UAAuB;QAChD,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACnC,IAAA,uBAAU,EAAC,UAAU,CAAC;YACtB,gCAAgC;SACjC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;IACvB,CAAC;IACD,uBAAuB,EAAE,KAAK,WAC5B,UAAuB,EACvB,UAAkB;QAElB,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;QACpD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAC5E,CAAC;IACD,oBAAoB,EAApB,iCAAoB;IACpB,WAAW,EAAX,yBAAW;IACX,WAAW,EAAE,GAAG,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IACD,WAAW,EAAX,yBAAW;CACZ,CAAC,CAAC","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { IOrder } from '@yuants/data-order';\nimport { provideExchangeServices } from '@yuants/exchange';\nimport { Terminal } from '@yuants/protocol';\nimport { ICredential } from '../api/private-api';\nimport { getEarningAccountInfo } from './accounts/earning';\nimport { getCredentialId } from './accounts/profile';\nimport { getUnifiedAccountInfo } from './accounts/unified';\nimport { listProducts } from './markets/product';\nimport { cancelOrder } from './orders/cancelOrder';\nimport { getOrdersByProductId, listOrders } from './orders/listOrders';\nimport { submitOrder } from './orders/submitOrder';\n\nconst terminal = Terminal.fromNodeEnv();\n\nconst getAllPositions = async (credential: ICredential): Promise<IPosition[]> => {\n const credentialId = await getCredentialId(credential);\n const [unifiedPositions, earningPositions] = await Promise.all([\n getUnifiedAccountInfo(credential),\n getEarningAccountInfo(credential),\n ]);\n return [...unifiedPositions, ...earningPositions];\n};\n\nprovideExchangeServices<ICredential>(terminal, {\n name: 'GATE',\n credentialSchema: {\n type: 'object',\n required: ['access_key', 'secret_key'],\n properties: {\n access_key: { type: 'string' },\n secret_key: { type: 'string' },\n },\n },\n getCredentialId,\n listProducts,\n getPositions: getAllPositions,\n getOrders: async function (credential: ICredential): Promise<IOrder[]> {\n const [umOrders] = await Promise.all([\n listOrders(credential),\n // listSpotOrders(credential),\n ]);\n return [...umOrders];\n },\n getPositionsByProductId: async function (\n credential: ICredential,\n product_id: string,\n ): Promise<IPosition[]> {\n const positions = await getAllPositions(credential);\n return positions.filter((position) => position.product_id === product_id);\n },\n getOrdersByProductId,\n submitOrder,\n modifyOrder: () => {\n throw new Error('Not implemented');\n },\n cancelOrder,\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuants/vendor-gate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib",
|
|
@@ -10,19 +10,19 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"rxjs": "~7.5.6",
|
|
12
12
|
"@yuants/cache": "0.3.12",
|
|
13
|
-
"@yuants/protocol": "0.54.1",
|
|
14
13
|
"@yuants/transfer": "0.2.48",
|
|
15
14
|
"@yuants/data-account": "0.11.8",
|
|
15
|
+
"@yuants/protocol": "0.54.1",
|
|
16
16
|
"@yuants/data-order": "0.7.9",
|
|
17
17
|
"@yuants/data-ohlc": "0.6.4",
|
|
18
18
|
"@yuants/data-trade": "0.1.31",
|
|
19
19
|
"@yuants/sql": "0.9.39",
|
|
20
20
|
"@yuants/data-product": "0.5.9",
|
|
21
21
|
"@yuants/utils": "0.19.4",
|
|
22
|
-
"@yuants/data-series": "0.3.61",
|
|
23
22
|
"@yuants/data-interest-rate": "0.2.9",
|
|
24
|
-
"@yuants/
|
|
25
|
-
"@yuants/data-quote": "0.4.8"
|
|
23
|
+
"@yuants/data-series": "0.3.61",
|
|
24
|
+
"@yuants/data-quote": "0.4.8",
|
|
25
|
+
"@yuants/exchange": "0.8.16"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@microsoft/api-extractor": "~7.55.2",
|