@yuants/vendor-aster 0.7.12 → 0.7.13
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/private-api.js +4 -0
- package/dist/api/private-api.js.map +1 -1
- package/dist/api/public-api.js +4 -0
- package/dist/api/public-api.js.map +1 -1
- package/dist/services/markets/quote.js +5 -5
- package/dist/services/markets/quote.js.map +1 -1
- package/lib/api/private-api.d.ts.map +1 -1
- package/lib/api/private-api.js +4 -0
- package/lib/api/private-api.js.map +1 -1
- package/lib/api/public-api.d.ts.map +1 -1
- package/lib/api/public-api.js +4 -0
- package/lib/api/public-api.js.map +1 -1
- package/lib/services/markets/quote.js +4 -4
- package/lib/services/markets/quote.js.map +1 -1
- package/package.json +1 -1
- package/temp/package-deps.json +6 -6
package/dist/api/private-api.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { encodeHex, HmacSHA256 } from '@yuants/utils';
|
|
2
|
+
import { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';
|
|
3
|
+
const MetricsAsterApiCallCounter = GlobalPrometheusRegistry.counter('aster_api_call', 'Number of aster api call');
|
|
4
|
+
const terminal = Terminal.fromNodeEnv();
|
|
2
5
|
const request = async (credential, method, baseURL, endpoint, params = {}) => {
|
|
3
6
|
const url = new URL(baseURL);
|
|
4
7
|
url.pathname = endpoint;
|
|
@@ -12,6 +15,7 @@ const request = async (credential, method, baseURL, endpoint, params = {}) => {
|
|
|
12
15
|
const signature = encodeHex(await HmacSHA256(new TextEncoder().encode(msg), new TextEncoder().encode(credential.secret_key)));
|
|
13
16
|
url.searchParams.set('signature', signature);
|
|
14
17
|
console.info(url.toString());
|
|
18
|
+
MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
15
19
|
const response = await fetch(url.toString(), {
|
|
16
20
|
method,
|
|
17
21
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-api.js","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeHex, HmacSHA256 } from '@yuants/utils';\n\nexport interface ICredential {\n address: string;\n api_key: string;\n secret_key: string;\n}\n\nexport interface IAsterFutureOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n updateTime: number;\n avgPrice: string;\n reduceOnly?: boolean;\n closePosition?: boolean;\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n workingType?: string;\n priceProtect?: boolean;\n origType?: string;\n stopPrice?: string;\n symbol: string;\n}\n\nexport interface IAsterSpotOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n cummulativeQuoteQty?: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n stopPrice?: string;\n icebergQty?: string;\n time: number;\n updateTime: number;\n isWorking?: boolean;\n avgPrice?: string;\n symbol: string;\n}\n\nconst request = async <T>(\n credential: ICredential,\n method: string,\n baseURL: string,\n endpoint: string,\n params: any = {},\n): Promise<T> => {\n const url = new URL(baseURL);\n url.pathname = endpoint;\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n url.searchParams.set(key, `${value}`);\n }\n\n url.searchParams.set('timestamp', `${Date.now()}`);\n const msg = url.search.slice(1); // 去掉开头的 '?'\n const signature = encodeHex(\n await HmacSHA256(new TextEncoder().encode(msg), new TextEncoder().encode(credential.secret_key)),\n );\n url.searchParams.set('signature', signature);\n\n console.info(url.toString());\n const response = await fetch(url.toString(), {\n method,\n headers: {\n 'X-MBX-APIKEY': credential.api_key,\n },\n });\n\n const resText = await response.text();\n\n try {\n const res = JSON.parse(resText);\n\n if (res.code && res.code !== 0) {\n throw resText;\n }\n return res;\n } catch (e) {\n throw `APIError: ${response.status} ${response.statusText} ${resText}`;\n }\n};\n\nconst createApi =\n (baseURL: string) =>\n <TReq, TRes>(method: string, endpoint: string) =>\n (credential: ICredential, params: TReq) =>\n request<TRes>(credential, method, baseURL, endpoint, params);\n\nconst createFutureApi = createApi('https://fapi.asterdex.com');\nconst createSpotApi = createApi('https://sapi.asterdex.com');\n\n/**\n * 获取账户信息\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AFv4-user_data\n */\nexport const getFApiV4Account = createFutureApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n updateTime: number;\n totalInitialMargin: string;\n totalMaintMargin: string;\n totalWalletBalance: string;\n totalUnrealizedProfit: string;\n totalMarginBalance: string;\n totalPositionInitialMargin: string;\n totalOpenOrderInitialMargin: string;\n totalCrossWalletBalance: string;\n totalCrossUnPnl: string;\n availableBalance: string;\n maxWithdrawAmount: string;\n assets: {\n asset: string;\n walletBalance: string;\n unrealizedProfit: string;\n marginBalance: string;\n maintMargin: string;\n initialMargin: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n maxWithdrawAmount: string;\n crossWalletBalance: string;\n crossUnPnl: string;\n availableBalance: string;\n marginAvailable: boolean;\n updateTime: number;\n }[];\n positions: {\n symbol: string;\n initialMargin: string;\n maintMargin: string;\n unrealizedProfit: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n leverage: string;\n isolated: boolean;\n entryPrice: string;\n maxNotional: string;\n positionSide: 'BOTH' | 'LONG' | 'SHORT';\n positionAmt: string;\n notional: string;\n isolatedWallet: string;\n updateTime: number;\n }[];\n }\n>('GET', '/fapi/v4/account');\n\nexport const getFApiV2Balance = createFutureApi<\n {},\n {\n accountAlias: string; // 账户唯一识别码\n asset: string; // 资产\n balance: string; // 总余额\n crossWalletBalance: string; // 全仓余额\n crossUnPnl: string; // 全仓持仓未实现盈亏\n availableBalance: string; // 下单可用余额\n maxWithdrawAmount: string; // 最大可转出余额\n marginAvailable: boolean; // 是否可用作联合保证金\n updateTime: number;\n }[]\n>('GET', '/fapi/v2/balance');\n\nexport const postFApiV1Order = createFutureApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n type:\n | 'MARKET'\n | 'LIMIT'\n | 'STOP'\n | 'STOP_MARKET'\n | 'TAKE_PROFIT'\n | 'TAKE_PROFIT_MARKET'\n | 'TRAILING_STOP_MARKET';\n reduceOnly?: 'true' | 'false';\n quantity?: number;\n price?: number;\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'HIDDEN';\n },\n {}\n>('POST', '/fapi/v1/order');\n\n/**\n * 查询当前挂单 (永续)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#L2728-L2766\n */\nexport const getFApiV1OpenOrders = createFutureApi<\n {\n symbol?: string;\n },\n IAsterFutureOpenOrder[]\n>('GET', '/fapi/v1/openOrders');\n\n/**\n * 查询当前挂单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1196-L1234\n */\nexport const getApiV1OpenOrders = createSpotApi<\n {\n symbol?: string;\n },\n IAsterSpotOpenOrder[]\n>('GET', '/api/v1/openOrders');\n\nexport const deleteFApiV1Order = createFutureApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/fapi/v1/order');\n\n/**\n * 获取账户信息 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AF-user_data\n */\nexport const getApiV1Account = createSpotApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n canBurnAsset: boolean;\n updateTime: number;\n balances: {\n asset: string;\n free: string;\n locked: string;\n }[];\n }\n>('GET', '/api/v1/account');\n\n/**\n * 获取最新价格\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC\n */\nexport const getApiV1TickerPrice = createSpotApi<\n {},\n {\n symbol: string;\n price: string;\n time: number;\n }[]\n>('GET', '/api/v1/ticker/price');\n\nexport const postApiV1Order = createSpotApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n type: 'MARKET' | 'LIMIT' | 'STOP' | 'STOP_MARKET' | 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET';\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX';\n quantity?: number;\n quoteOrderQty?: number;\n price?: number;\n },\n {\n orderId: number; // 系统的订单ID\n }\n>('POST', '/api/v1/order');\n\n/**\n * 取消有效订单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1040-L1074\n */\nexport const deleteApiV1Order = createSpotApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/api/v1/order');\n"]}
|
|
1
|
+
{"version":3,"file":"private-api.js","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeHex, HmacSHA256 } from '@yuants/utils';\n\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\n\nconst MetricsAsterApiCallCounter = GlobalPrometheusRegistry.counter(\n 'aster_api_call',\n 'Number of aster api call',\n);\nconst terminal = Terminal.fromNodeEnv();\n\nexport interface ICredential {\n address: string;\n api_key: string;\n secret_key: string;\n}\n\nexport interface IAsterFutureOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n updateTime: number;\n avgPrice: string;\n reduceOnly?: boolean;\n closePosition?: boolean;\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n workingType?: string;\n priceProtect?: boolean;\n origType?: string;\n stopPrice?: string;\n symbol: string;\n}\n\nexport interface IAsterSpotOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n cummulativeQuoteQty?: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n stopPrice?: string;\n icebergQty?: string;\n time: number;\n updateTime: number;\n isWorking?: boolean;\n avgPrice?: string;\n symbol: string;\n}\n\nconst request = async <T>(\n credential: ICredential,\n method: string,\n baseURL: string,\n endpoint: string,\n params: any = {},\n): Promise<T> => {\n const url = new URL(baseURL);\n url.pathname = endpoint;\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n url.searchParams.set(key, `${value}`);\n }\n\n url.searchParams.set('timestamp', `${Date.now()}`);\n const msg = url.search.slice(1); // 去掉开头的 '?'\n const signature = encodeHex(\n await HmacSHA256(new TextEncoder().encode(msg), new TextEncoder().encode(credential.secret_key)),\n );\n url.searchParams.set('signature', signature);\n\n console.info(url.toString());\n MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();\n const response = await fetch(url.toString(), {\n method,\n headers: {\n 'X-MBX-APIKEY': credential.api_key,\n },\n });\n\n const resText = await response.text();\n\n try {\n const res = JSON.parse(resText);\n\n if (res.code && res.code !== 0) {\n throw resText;\n }\n return res;\n } catch (e) {\n throw `APIError: ${response.status} ${response.statusText} ${resText}`;\n }\n};\n\nconst createApi =\n (baseURL: string) =>\n <TReq, TRes>(method: string, endpoint: string) =>\n (credential: ICredential, params: TReq) =>\n request<TRes>(credential, method, baseURL, endpoint, params);\n\nconst createFutureApi = createApi('https://fapi.asterdex.com');\nconst createSpotApi = createApi('https://sapi.asterdex.com');\n\n/**\n * 获取账户信息\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AFv4-user_data\n */\nexport const getFApiV4Account = createFutureApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n updateTime: number;\n totalInitialMargin: string;\n totalMaintMargin: string;\n totalWalletBalance: string;\n totalUnrealizedProfit: string;\n totalMarginBalance: string;\n totalPositionInitialMargin: string;\n totalOpenOrderInitialMargin: string;\n totalCrossWalletBalance: string;\n totalCrossUnPnl: string;\n availableBalance: string;\n maxWithdrawAmount: string;\n assets: {\n asset: string;\n walletBalance: string;\n unrealizedProfit: string;\n marginBalance: string;\n maintMargin: string;\n initialMargin: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n maxWithdrawAmount: string;\n crossWalletBalance: string;\n crossUnPnl: string;\n availableBalance: string;\n marginAvailable: boolean;\n updateTime: number;\n }[];\n positions: {\n symbol: string;\n initialMargin: string;\n maintMargin: string;\n unrealizedProfit: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n leverage: string;\n isolated: boolean;\n entryPrice: string;\n maxNotional: string;\n positionSide: 'BOTH' | 'LONG' | 'SHORT';\n positionAmt: string;\n notional: string;\n isolatedWallet: string;\n updateTime: number;\n }[];\n }\n>('GET', '/fapi/v4/account');\n\nexport const getFApiV2Balance = createFutureApi<\n {},\n {\n accountAlias: string; // 账户唯一识别码\n asset: string; // 资产\n balance: string; // 总余额\n crossWalletBalance: string; // 全仓余额\n crossUnPnl: string; // 全仓持仓未实现盈亏\n availableBalance: string; // 下单可用余额\n maxWithdrawAmount: string; // 最大可转出余额\n marginAvailable: boolean; // 是否可用作联合保证金\n updateTime: number;\n }[]\n>('GET', '/fapi/v2/balance');\n\nexport const postFApiV1Order = createFutureApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n type:\n | 'MARKET'\n | 'LIMIT'\n | 'STOP'\n | 'STOP_MARKET'\n | 'TAKE_PROFIT'\n | 'TAKE_PROFIT_MARKET'\n | 'TRAILING_STOP_MARKET';\n reduceOnly?: 'true' | 'false';\n quantity?: number;\n price?: number;\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'HIDDEN';\n },\n {}\n>('POST', '/fapi/v1/order');\n\n/**\n * 查询当前挂单 (永续)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#L2728-L2766\n */\nexport const getFApiV1OpenOrders = createFutureApi<\n {\n symbol?: string;\n },\n IAsterFutureOpenOrder[]\n>('GET', '/fapi/v1/openOrders');\n\n/**\n * 查询当前挂单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1196-L1234\n */\nexport const getApiV1OpenOrders = createSpotApi<\n {\n symbol?: string;\n },\n IAsterSpotOpenOrder[]\n>('GET', '/api/v1/openOrders');\n\nexport const deleteFApiV1Order = createFutureApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/fapi/v1/order');\n\n/**\n * 获取账户信息 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AF-user_data\n */\nexport const getApiV1Account = createSpotApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n canBurnAsset: boolean;\n updateTime: number;\n balances: {\n asset: string;\n free: string;\n locked: string;\n }[];\n }\n>('GET', '/api/v1/account');\n\n/**\n * 获取最新价格\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC\n */\nexport const getApiV1TickerPrice = createSpotApi<\n {},\n {\n symbol: string;\n price: string;\n time: number;\n }[]\n>('GET', '/api/v1/ticker/price');\n\nexport const postApiV1Order = createSpotApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n type: 'MARKET' | 'LIMIT' | 'STOP' | 'STOP_MARKET' | 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET';\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX';\n quantity?: number;\n quoteOrderQty?: number;\n price?: number;\n },\n {\n orderId: number; // 系统的订单ID\n }\n>('POST', '/api/v1/order');\n\n/**\n * 取消有效订单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1040-L1074\n */\nexport const deleteApiV1Order = createSpotApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/api/v1/order');\n"]}
|
package/dist/api/public-api.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const BASE_URL = 'https://fapi.asterdex.com';
|
|
2
|
+
import { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';
|
|
3
|
+
const MetricsAsterApiCallCounter = GlobalPrometheusRegistry.counter('aster_api_call', 'Number of aster api call');
|
|
4
|
+
const terminal = Terminal.fromNodeEnv();
|
|
2
5
|
const request = async (method, endpoint, params = {}) => {
|
|
3
6
|
const url = new URL(BASE_URL);
|
|
4
7
|
url.pathname = endpoint;
|
|
@@ -8,6 +11,7 @@ const request = async (method, endpoint, params = {}) => {
|
|
|
8
11
|
url.searchParams.set(key, `${value}`);
|
|
9
12
|
}
|
|
10
13
|
console.info(url.toString());
|
|
14
|
+
MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
11
15
|
const res = await fetch(url.toString(), {
|
|
12
16
|
method,
|
|
13
17
|
}).then((response) => response.json());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEtE,MAAM,0BAA0B,GAAG,wBAAwB,CAAC,OAAO,CACjE,gBAAgB,EAChB,0BAA0B,CAC3B,CAAC;AACF,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,OAAO,GAAG,KAAK,EAAK,MAAc,EAAE,QAAgB,EAAE,SAAc,EAAE,EAAc,EAAE;IAC1F,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;KACvC;IAED,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7B,0BAA0B,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IACnG,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QACtC,MAAM;KACP,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE;QAC9B,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;KAC3B;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,SAAS,GACb,CAAa,MAAc,EAAE,QAAgB,EAAE,EAAE,CACjD,CAAC,MAAY,EAAE,EAAE,CACf,OAAO,CAAO,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAE5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAY3C,KAAK,EAAE,sBAAsB,CAAC,CAAC;AAEjC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,SAAS,CAkB5C,KAAK,EAAE,uBAAuB,CAAC,CAAC;AAElC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,SAAS,CAS5C,KAAK,EAAE,uBAAuB,CAAC,CAAC;AAElC;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAO3C,KAAK,EAAE,uBAAuB,CAAC,CAAC","sourcesContent":["const BASE_URL = 'https://fapi.asterdex.com';\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\n\nconst MetricsAsterApiCallCounter = GlobalPrometheusRegistry.counter(\n 'aster_api_call',\n 'Number of aster api call',\n);\nconst terminal = Terminal.fromNodeEnv();\nconst request = async <T>(method: string, endpoint: string, params: any = {}): Promise<T> => {\n const url = new URL(BASE_URL);\n url.pathname = endpoint;\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n url.searchParams.set(key, `${value}`);\n }\n\n console.info(url.toString());\n MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();\n const res = await fetch(url.toString(), {\n method,\n }).then((response) => response.json());\n if (res.code && res.code !== 0) {\n throw JSON.stringify(res);\n }\n return res;\n};\n\nconst createApi =\n <TReq, TRes>(method: string, endpoint: string) =>\n (params: TReq) =>\n request<TRes>(method, endpoint, params);\n\n/**\n * 获取资金费率历史\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E6%9F%A5%E8%AF%A2%E8%B5%84%E9%87%91%E8%B4%B9%E7%8E%87%E5%8E%86%E5%8F%B2\n */\nexport const getFApiV1FundingRate = createApi<\n {\n symbol?: string;\n startTime?: number;\n endTime?: number;\n limit?: number;\n },\n {\n symbol: string;\n fundingRate: string;\n fundingTime: number;\n }[]\n>('GET', '/fapi/v1/fundingRate');\n\n/**\n * 获取交易对信息\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E4%BA%A4%E6%98%93%E5%AF%B9%E4%BF%A1%E6%81%AF\n */\nexport const getFApiV1ExchangeInfo = createApi<\n {},\n {\n symbols: {\n symbol: string;\n status: 'TRADING' | 'BREAK' | 'HALT';\n baseAsset: string;\n quoteAsset: string;\n pricePrecision: number;\n quantityPrecision: number;\n baseAssetPrecision: number;\n quotePrecision: number;\n filters: {\n filterType: string;\n [key: string]: any;\n }[];\n }[];\n }\n>('GET', '/fapi/v1/exchangeInfo');\n\n/**\n * 获取未平仓合约数量\n *\n * 无 API 文档 (weird)\n */\nexport const getFApiV1OpenInterest = createApi<\n {\n symbol: string;\n },\n {\n symbol: string;\n openInterest: string;\n time: number;\n }\n>('GET', '/fapi/v1/openInterest');\n\n/**\n * 获取最新价格\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC\n */\nexport const getFApiV1TickerPrice = createApi<\n {},\n {\n symbol: string;\n price: string;\n time?: number;\n }[]\n>('GET', '/fapi/v1/ticker/price');\n"]}
|
|
@@ -2,7 +2,7 @@ import { createCache } from '@yuants/cache';
|
|
|
2
2
|
import { Terminal } from '@yuants/protocol';
|
|
3
3
|
import { writeToSQL } from '@yuants/sql';
|
|
4
4
|
import { decodePath, encodePath } from '@yuants/utils';
|
|
5
|
-
import { defer, filter,
|
|
5
|
+
import { defer, filter, map, mergeMap, repeat, retry, shareReplay } from 'rxjs';
|
|
6
6
|
import { getFApiV1OpenInterest, getFApiV1TickerPrice } from '../../api/public-api';
|
|
7
7
|
const terminal = Terminal.fromNodeEnv();
|
|
8
8
|
const OPEN_INTEREST_TTL = process.env.OPEN_INTEREST_TTL ? Number(process.env.OPEN_INTEREST_TTL) : 120000;
|
|
@@ -16,18 +16,18 @@ const openInterestCache = createCache(async (symbol) => {
|
|
|
16
16
|
return undefined;
|
|
17
17
|
}
|
|
18
18
|
}, { expire: OPEN_INTEREST_TTL });
|
|
19
|
-
const quote$ = defer(() => getFApiV1TickerPrice({})).pipe(mergeMap((tickers) => tickers || []),
|
|
19
|
+
const quote$ = defer(() => getFApiV1TickerPrice({})).pipe(mergeMap((tickers) => tickers || []), map((ticker) => {
|
|
20
20
|
var _a;
|
|
21
21
|
return ({
|
|
22
22
|
datasource_id: 'ASTER',
|
|
23
|
-
product_id: encodePath('PERP', ticker.symbol),
|
|
23
|
+
product_id: encodePath('ASTER', 'PERP', ticker.symbol),
|
|
24
24
|
last_price: `${ticker.price}`,
|
|
25
25
|
bid_price: `${ticker.price}`,
|
|
26
26
|
ask_price: `${ticker.price}`,
|
|
27
|
-
open_interest:
|
|
27
|
+
open_interest: '0',
|
|
28
28
|
updated_at: new Date((_a = ticker.time) !== null && _a !== void 0 ? _a : Date.now()).toISOString(),
|
|
29
29
|
});
|
|
30
|
-
})
|
|
30
|
+
}), repeat({ delay: 1000 }), retry({ delay: 5000 }), shareReplay({ bufferSize: 1, refCount: true }));
|
|
31
31
|
if (process.env.WRITE_QUOTE_TO_SQL === 'true') {
|
|
32
32
|
quote$
|
|
33
33
|
.pipe(writeToSQL({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../src/services/markets/quote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../src/services/markets/quote.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport type { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { writeToSQL } from '@yuants/sql';\nimport { decodePath, encodePath } from '@yuants/utils';\nimport { defer, filter, from, map, mergeMap, repeat, retry, shareReplay } from 'rxjs';\nimport { getFApiV1OpenInterest, getFApiV1TickerPrice } from '../../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\nconst OPEN_INTEREST_TTL = process.env.OPEN_INTEREST_TTL ? Number(process.env.OPEN_INTEREST_TTL) : 120_000;\n\nconst openInterestCache = createCache<string>(\n async (symbol: string) => {\n try {\n const data = await getFApiV1OpenInterest({ symbol });\n return data.openInterest;\n } catch (error) {\n console.warn('getFApiV1OpenInterest failed', symbol, error);\n return undefined;\n }\n },\n { expire: OPEN_INTEREST_TTL },\n);\n\nconst quote$ = defer(() => getFApiV1TickerPrice({})).pipe(\n mergeMap((tickers) => tickers || []),\n map(\n (ticker): Partial<IQuote> => ({\n datasource_id: 'ASTER',\n product_id: encodePath('ASTER', 'PERP', ticker.symbol),\n last_price: `${ticker.price}`,\n bid_price: `${ticker.price}`,\n ask_price: `${ticker.price}`,\n open_interest: '0',\n updated_at: new Date(ticker.time ?? Date.now()).toISOString(),\n }),\n ),\n repeat({ delay: 1000 }),\n retry({ delay: 5000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nif (process.env.WRITE_QUOTE_TO_SQL === 'true') {\n quote$\n .pipe(\n writeToSQL({\n terminal,\n tableName: 'quote',\n writeInterval: 1000,\n conflictKeys: ['datasource_id', 'product_id'],\n }),\n )\n .subscribe();\n\n terminal.channel.publishChannel('quote', { pattern: '^ASTER/' }, (channel_id) => {\n const [datasourceId, productId] = decodePath(channel_id);\n if (!datasourceId || !productId) {\n throw new Error(`Invalid channel_id: ${channel_id}`);\n }\n return quote$.pipe(filter((quote) => quote.product_id === productId));\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-api.d.ts","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"private-api.d.ts","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":"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"}
|
package/lib/api/private-api.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.deleteApiV1Order = exports.postApiV1Order = exports.getApiV1TickerPrice = exports.getApiV1Account = exports.deleteFApiV1Order = exports.getApiV1OpenOrders = exports.getFApiV1OpenOrders = exports.postFApiV1Order = exports.getFApiV2Balance = exports.getFApiV4Account = void 0;
|
|
4
4
|
const utils_1 = require("@yuants/utils");
|
|
5
|
+
const protocol_1 = require("@yuants/protocol");
|
|
6
|
+
const MetricsAsterApiCallCounter = protocol_1.GlobalPrometheusRegistry.counter('aster_api_call', 'Number of aster api call');
|
|
7
|
+
const terminal = protocol_1.Terminal.fromNodeEnv();
|
|
5
8
|
const request = async (credential, method, baseURL, endpoint, params = {}) => {
|
|
6
9
|
const url = new URL(baseURL);
|
|
7
10
|
url.pathname = endpoint;
|
|
@@ -15,6 +18,7 @@ const request = async (credential, method, baseURL, endpoint, params = {}) => {
|
|
|
15
18
|
const signature = (0, utils_1.encodeHex)(await (0, utils_1.HmacSHA256)(new TextEncoder().encode(msg), new TextEncoder().encode(credential.secret_key)));
|
|
16
19
|
url.searchParams.set('signature', signature);
|
|
17
20
|
console.info(url.toString());
|
|
21
|
+
MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
18
22
|
const response = await fetch(url.toString(), {
|
|
19
23
|
method,
|
|
20
24
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-api.js","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":";;;AAAA,yCAAsD;AAkDtD,MAAM,OAAO,GAAG,KAAK,EACnB,UAAuB,EACvB,MAAc,EACd,OAAe,EACf,QAAgB,EAChB,SAAc,EAAE,EACJ,EAAE;IACd,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;KACvC;IAED,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY;IAC7C,MAAM,SAAS,GAAG,IAAA,iBAAS,EACzB,MAAM,IAAA,kBAAU,EAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CACjG,CAAC;IACF,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAE7C,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QAC3C,MAAM;QACN,OAAO,EAAE;YACP,cAAc,EAAE,UAAU,CAAC,OAAO;SACnC;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEtC,IAAI;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE;YAC9B,MAAM,OAAO,CAAC;SACf;QACD,OAAO,GAAG,CAAC;KACZ;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,aAAa,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC;KACxE;AACH,CAAC,CAAC;AAEF,MAAM,SAAS,GACb,CAAC,OAAe,EAAE,EAAE,CACpB,CAAa,MAAc,EAAE,QAAgB,EAAE,EAAE,CACjD,CAAC,UAAuB,EAAE,MAAY,EAAE,EAAE,CACxC,OAAO,CAAO,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEjE,MAAM,eAAe,GAAG,SAAS,CAAC,2BAA2B,CAAC,CAAC;AAC/D,MAAM,aAAa,GAAG,SAAS,CAAC,2BAA2B,CAAC,CAAC;AAE7D;;;;GAIG;AACU,QAAA,gBAAgB,GAAG,eAAe,CAqD7C,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAEhB,QAAA,gBAAgB,GAAG,eAAe,CAa7C,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAEhB,QAAA,eAAe,GAAG,eAAe,CAmB5C,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAE5B;;;;GAIG;AACU,QAAA,mBAAmB,GAAG,eAAe,CAKhD,KAAK,EAAE,qBAAqB,CAAC,CAAC;AAEhC;;;;GAIG;AACU,QAAA,kBAAkB,GAAG,aAAa,CAK7C,KAAK,EAAE,oBAAoB,CAAC,CAAC;AAElB,QAAA,iBAAiB,GAAG,eAAe,CAO9C,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AAE9B;;;;GAIG;AACU,QAAA,eAAe,GAAG,aAAa,CAe1C,KAAK,EAAE,iBAAiB,CAAC,CAAC;AAE5B;;;GAGG;AACU,QAAA,mBAAmB,GAAG,aAAa,CAO9C,KAAK,EAAE,sBAAsB,CAAC,CAAC;AAEpB,QAAA,cAAc,GAAG,aAAa,CAazC,MAAM,EAAE,eAAe,CAAC,CAAC;AAE3B;;;;GAIG;AACU,QAAA,gBAAgB,GAAG,aAAa,CAO3C,QAAQ,EAAE,eAAe,CAAC,CAAC","sourcesContent":["import { encodeHex, HmacSHA256 } from '@yuants/utils';\n\nexport interface ICredential {\n address: string;\n api_key: string;\n secret_key: string;\n}\n\nexport interface IAsterFutureOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n updateTime: number;\n avgPrice: string;\n reduceOnly?: boolean;\n closePosition?: boolean;\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n workingType?: string;\n priceProtect?: boolean;\n origType?: string;\n stopPrice?: string;\n symbol: string;\n}\n\nexport interface IAsterSpotOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n cummulativeQuoteQty?: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n stopPrice?: string;\n icebergQty?: string;\n time: number;\n updateTime: number;\n isWorking?: boolean;\n avgPrice?: string;\n symbol: string;\n}\n\nconst request = async <T>(\n credential: ICredential,\n method: string,\n baseURL: string,\n endpoint: string,\n params: any = {},\n): Promise<T> => {\n const url = new URL(baseURL);\n url.pathname = endpoint;\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n url.searchParams.set(key, `${value}`);\n }\n\n url.searchParams.set('timestamp', `${Date.now()}`);\n const msg = url.search.slice(1); // 去掉开头的 '?'\n const signature = encodeHex(\n await HmacSHA256(new TextEncoder().encode(msg), new TextEncoder().encode(credential.secret_key)),\n );\n url.searchParams.set('signature', signature);\n\n console.info(url.toString());\n const response = await fetch(url.toString(), {\n method,\n headers: {\n 'X-MBX-APIKEY': credential.api_key,\n },\n });\n\n const resText = await response.text();\n\n try {\n const res = JSON.parse(resText);\n\n if (res.code && res.code !== 0) {\n throw resText;\n }\n return res;\n } catch (e) {\n throw `APIError: ${response.status} ${response.statusText} ${resText}`;\n }\n};\n\nconst createApi =\n (baseURL: string) =>\n <TReq, TRes>(method: string, endpoint: string) =>\n (credential: ICredential, params: TReq) =>\n request<TRes>(credential, method, baseURL, endpoint, params);\n\nconst createFutureApi = createApi('https://fapi.asterdex.com');\nconst createSpotApi = createApi('https://sapi.asterdex.com');\n\n/**\n * 获取账户信息\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AFv4-user_data\n */\nexport const getFApiV4Account = createFutureApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n updateTime: number;\n totalInitialMargin: string;\n totalMaintMargin: string;\n totalWalletBalance: string;\n totalUnrealizedProfit: string;\n totalMarginBalance: string;\n totalPositionInitialMargin: string;\n totalOpenOrderInitialMargin: string;\n totalCrossWalletBalance: string;\n totalCrossUnPnl: string;\n availableBalance: string;\n maxWithdrawAmount: string;\n assets: {\n asset: string;\n walletBalance: string;\n unrealizedProfit: string;\n marginBalance: string;\n maintMargin: string;\n initialMargin: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n maxWithdrawAmount: string;\n crossWalletBalance: string;\n crossUnPnl: string;\n availableBalance: string;\n marginAvailable: boolean;\n updateTime: number;\n }[];\n positions: {\n symbol: string;\n initialMargin: string;\n maintMargin: string;\n unrealizedProfit: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n leverage: string;\n isolated: boolean;\n entryPrice: string;\n maxNotional: string;\n positionSide: 'BOTH' | 'LONG' | 'SHORT';\n positionAmt: string;\n notional: string;\n isolatedWallet: string;\n updateTime: number;\n }[];\n }\n>('GET', '/fapi/v4/account');\n\nexport const getFApiV2Balance = createFutureApi<\n {},\n {\n accountAlias: string; // 账户唯一识别码\n asset: string; // 资产\n balance: string; // 总余额\n crossWalletBalance: string; // 全仓余额\n crossUnPnl: string; // 全仓持仓未实现盈亏\n availableBalance: string; // 下单可用余额\n maxWithdrawAmount: string; // 最大可转出余额\n marginAvailable: boolean; // 是否可用作联合保证金\n updateTime: number;\n }[]\n>('GET', '/fapi/v2/balance');\n\nexport const postFApiV1Order = createFutureApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n type:\n | 'MARKET'\n | 'LIMIT'\n | 'STOP'\n | 'STOP_MARKET'\n | 'TAKE_PROFIT'\n | 'TAKE_PROFIT_MARKET'\n | 'TRAILING_STOP_MARKET';\n reduceOnly?: 'true' | 'false';\n quantity?: number;\n price?: number;\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'HIDDEN';\n },\n {}\n>('POST', '/fapi/v1/order');\n\n/**\n * 查询当前挂单 (永续)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#L2728-L2766\n */\nexport const getFApiV1OpenOrders = createFutureApi<\n {\n symbol?: string;\n },\n IAsterFutureOpenOrder[]\n>('GET', '/fapi/v1/openOrders');\n\n/**\n * 查询当前挂单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1196-L1234\n */\nexport const getApiV1OpenOrders = createSpotApi<\n {\n symbol?: string;\n },\n IAsterSpotOpenOrder[]\n>('GET', '/api/v1/openOrders');\n\nexport const deleteFApiV1Order = createFutureApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/fapi/v1/order');\n\n/**\n * 获取账户信息 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AF-user_data\n */\nexport const getApiV1Account = createSpotApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n canBurnAsset: boolean;\n updateTime: number;\n balances: {\n asset: string;\n free: string;\n locked: string;\n }[];\n }\n>('GET', '/api/v1/account');\n\n/**\n * 获取最新价格\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC\n */\nexport const getApiV1TickerPrice = createSpotApi<\n {},\n {\n symbol: string;\n price: string;\n time: number;\n }[]\n>('GET', '/api/v1/ticker/price');\n\nexport const postApiV1Order = createSpotApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n type: 'MARKET' | 'LIMIT' | 'STOP' | 'STOP_MARKET' | 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET';\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX';\n quantity?: number;\n quoteOrderQty?: number;\n price?: number;\n },\n {\n orderId: number; // 系统的订单ID\n }\n>('POST', '/api/v1/order');\n\n/**\n * 取消有效订单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1040-L1074\n */\nexport const deleteApiV1Order = createSpotApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/api/v1/order');\n"]}
|
|
1
|
+
{"version":3,"file":"private-api.js","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeHex, HmacSHA256 } from '@yuants/utils';\n\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\n\nconst MetricsAsterApiCallCounter = GlobalPrometheusRegistry.counter(\n 'aster_api_call',\n 'Number of aster api call',\n);\nconst terminal = Terminal.fromNodeEnv();\n\nexport interface ICredential {\n address: string;\n api_key: string;\n secret_key: string;\n}\n\nexport interface IAsterFutureOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n updateTime: number;\n avgPrice: string;\n reduceOnly?: boolean;\n closePosition?: boolean;\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n workingType?: string;\n priceProtect?: boolean;\n origType?: string;\n stopPrice?: string;\n symbol: string;\n}\n\nexport interface IAsterSpotOpenOrder {\n orderId: number;\n clientOrderId: string;\n price: string;\n origQty: string;\n executedQty: string;\n cummulativeQuoteQty?: string;\n status: string;\n timeInForce: string;\n type: string;\n side: 'BUY' | 'SELL';\n stopPrice?: string;\n icebergQty?: string;\n time: number;\n updateTime: number;\n isWorking?: boolean;\n avgPrice?: string;\n symbol: string;\n}\n\nconst request = async <T>(\n credential: ICredential,\n method: string,\n baseURL: string,\n endpoint: string,\n params: any = {},\n): Promise<T> => {\n const url = new URL(baseURL);\n url.pathname = endpoint;\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n url.searchParams.set(key, `${value}`);\n }\n\n url.searchParams.set('timestamp', `${Date.now()}`);\n const msg = url.search.slice(1); // 去掉开头的 '?'\n const signature = encodeHex(\n await HmacSHA256(new TextEncoder().encode(msg), new TextEncoder().encode(credential.secret_key)),\n );\n url.searchParams.set('signature', signature);\n\n console.info(url.toString());\n MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();\n const response = await fetch(url.toString(), {\n method,\n headers: {\n 'X-MBX-APIKEY': credential.api_key,\n },\n });\n\n const resText = await response.text();\n\n try {\n const res = JSON.parse(resText);\n\n if (res.code && res.code !== 0) {\n throw resText;\n }\n return res;\n } catch (e) {\n throw `APIError: ${response.status} ${response.statusText} ${resText}`;\n }\n};\n\nconst createApi =\n (baseURL: string) =>\n <TReq, TRes>(method: string, endpoint: string) =>\n (credential: ICredential, params: TReq) =>\n request<TRes>(credential, method, baseURL, endpoint, params);\n\nconst createFutureApi = createApi('https://fapi.asterdex.com');\nconst createSpotApi = createApi('https://sapi.asterdex.com');\n\n/**\n * 获取账户信息\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AFv4-user_data\n */\nexport const getFApiV4Account = createFutureApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n updateTime: number;\n totalInitialMargin: string;\n totalMaintMargin: string;\n totalWalletBalance: string;\n totalUnrealizedProfit: string;\n totalMarginBalance: string;\n totalPositionInitialMargin: string;\n totalOpenOrderInitialMargin: string;\n totalCrossWalletBalance: string;\n totalCrossUnPnl: string;\n availableBalance: string;\n maxWithdrawAmount: string;\n assets: {\n asset: string;\n walletBalance: string;\n unrealizedProfit: string;\n marginBalance: string;\n maintMargin: string;\n initialMargin: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n maxWithdrawAmount: string;\n crossWalletBalance: string;\n crossUnPnl: string;\n availableBalance: string;\n marginAvailable: boolean;\n updateTime: number;\n }[];\n positions: {\n symbol: string;\n initialMargin: string;\n maintMargin: string;\n unrealizedProfit: string;\n positionInitialMargin: string;\n openOrderInitialMargin: string;\n leverage: string;\n isolated: boolean;\n entryPrice: string;\n maxNotional: string;\n positionSide: 'BOTH' | 'LONG' | 'SHORT';\n positionAmt: string;\n notional: string;\n isolatedWallet: string;\n updateTime: number;\n }[];\n }\n>('GET', '/fapi/v4/account');\n\nexport const getFApiV2Balance = createFutureApi<\n {},\n {\n accountAlias: string; // 账户唯一识别码\n asset: string; // 资产\n balance: string; // 总余额\n crossWalletBalance: string; // 全仓余额\n crossUnPnl: string; // 全仓持仓未实现盈亏\n availableBalance: string; // 下单可用余额\n maxWithdrawAmount: string; // 最大可转出余额\n marginAvailable: boolean; // 是否可用作联合保证金\n updateTime: number;\n }[]\n>('GET', '/fapi/v2/balance');\n\nexport const postFApiV1Order = createFutureApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n positionSide?: 'BOTH' | 'LONG' | 'SHORT';\n type:\n | 'MARKET'\n | 'LIMIT'\n | 'STOP'\n | 'STOP_MARKET'\n | 'TAKE_PROFIT'\n | 'TAKE_PROFIT_MARKET'\n | 'TRAILING_STOP_MARKET';\n reduceOnly?: 'true' | 'false';\n quantity?: number;\n price?: number;\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX' | 'HIDDEN';\n },\n {}\n>('POST', '/fapi/v1/order');\n\n/**\n * 查询当前挂单 (永续)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#L2728-L2766\n */\nexport const getFApiV1OpenOrders = createFutureApi<\n {\n symbol?: string;\n },\n IAsterFutureOpenOrder[]\n>('GET', '/fapi/v1/openOrders');\n\n/**\n * 查询当前挂单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1196-L1234\n */\nexport const getApiV1OpenOrders = createSpotApi<\n {\n symbol?: string;\n },\n IAsterSpotOpenOrder[]\n>('GET', '/api/v1/openOrders');\n\nexport const deleteFApiV1Order = createFutureApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/fapi/v1/order');\n\n/**\n * 获取账户信息 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AF-user_data\n */\nexport const getApiV1Account = createSpotApi<\n {},\n {\n feeTier: number;\n canTrade: boolean;\n canDeposit: boolean;\n canWithdraw: boolean;\n canBurnAsset: boolean;\n updateTime: number;\n balances: {\n asset: string;\n free: string;\n locked: string;\n }[];\n }\n>('GET', '/api/v1/account');\n\n/**\n * 获取最新价格\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC\n */\nexport const getApiV1TickerPrice = createSpotApi<\n {},\n {\n symbol: string;\n price: string;\n time: number;\n }[]\n>('GET', '/api/v1/ticker/price');\n\nexport const postApiV1Order = createSpotApi<\n {\n symbol: string;\n side: 'BUY' | 'SELL';\n type: 'MARKET' | 'LIMIT' | 'STOP' | 'STOP_MARKET' | 'TAKE_PROFIT' | 'TAKE_PROFIT_MARKET';\n timeInForce?: 'GTC' | 'IOC' | 'FOK' | 'GTX';\n quantity?: number;\n quoteOrderQty?: number;\n price?: number;\n },\n {\n orderId: number; // 系统的订单ID\n }\n>('POST', '/api/v1/order');\n\n/**\n * 取消有效订单 (现货)\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-spot-api_CN.md#L1040-L1074\n */\nexport const deleteApiV1Order = createSpotApi<\n {\n symbol: string;\n orderId?: string | number;\n origClientOrderId?: string;\n },\n {}\n>('DELETE', '/api/v1/order');\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;YAQrB,MAAM;iBACD,MAAM;iBACN,MAAM;IAES,CAAC;AAEjC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;gBAIpB,MAAM;gBACN,SAAS,GAAG,OAAO,GAAG,MAAM;mBACzB,MAAM;oBACL,MAAM;wBACF,MAAM;2BACH,MAAM;4BACL,MAAM;wBACV,MAAM;;;wBAER,MAAM;;;EAKO,CAAC;AAElC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;YAEtB,MAAM;;YAGN,MAAM;kBACA,MAAM;UACd,MAAM;EAEiB,CAAC;AAElC;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;YAGrB,MAAM;WACP,MAAM;;IAGgB,CAAC"}
|
package/lib/api/public-api.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getFApiV1TickerPrice = exports.getFApiV1OpenInterest = exports.getFApiV1ExchangeInfo = exports.getFApiV1FundingRate = void 0;
|
|
4
4
|
const BASE_URL = 'https://fapi.asterdex.com';
|
|
5
|
+
const protocol_1 = require("@yuants/protocol");
|
|
6
|
+
const MetricsAsterApiCallCounter = protocol_1.GlobalPrometheusRegistry.counter('aster_api_call', 'Number of aster api call');
|
|
7
|
+
const terminal = protocol_1.Terminal.fromNodeEnv();
|
|
5
8
|
const request = async (method, endpoint, params = {}) => {
|
|
6
9
|
const url = new URL(BASE_URL);
|
|
7
10
|
url.pathname = endpoint;
|
|
@@ -11,6 +14,7 @@ const request = async (method, endpoint, params = {}) => {
|
|
|
11
14
|
url.searchParams.set(key, `${value}`);
|
|
12
15
|
}
|
|
13
16
|
console.info(url.toString());
|
|
17
|
+
MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
14
18
|
const res = await fetch(url.toString(), {
|
|
15
19
|
method,
|
|
16
20
|
}).then((response) => response.json());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":";;;AAAA,MAAM,QAAQ,GAAG,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":";;;AAAA,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAC7C,+CAAsE;AAEtE,MAAM,0BAA0B,GAAG,mCAAwB,CAAC,OAAO,CACjE,gBAAgB,EAChB,0BAA0B,CAC3B,CAAC;AACF,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,OAAO,GAAG,KAAK,EAAK,MAAc,EAAE,QAAgB,EAAE,SAAc,EAAE,EAAc,EAAE;IAC1F,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;QACjD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;KACvC;IAED,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7B,0BAA0B,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IACnG,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QACtC,MAAM;KACP,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE;QAC9B,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;KAC3B;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,SAAS,GACb,CAAa,MAAc,EAAE,QAAgB,EAAE,EAAE,CACjD,CAAC,MAAY,EAAE,EAAE,CACf,OAAO,CAAO,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAE5C;;;;GAIG;AACU,QAAA,oBAAoB,GAAG,SAAS,CAY3C,KAAK,EAAE,sBAAsB,CAAC,CAAC;AAEjC;;;;GAIG;AACU,QAAA,qBAAqB,GAAG,SAAS,CAkB5C,KAAK,EAAE,uBAAuB,CAAC,CAAC;AAElC;;;;GAIG;AACU,QAAA,qBAAqB,GAAG,SAAS,CAS5C,KAAK,EAAE,uBAAuB,CAAC,CAAC;AAElC;;;;GAIG;AACU,QAAA,oBAAoB,GAAG,SAAS,CAO3C,KAAK,EAAE,uBAAuB,CAAC,CAAC","sourcesContent":["const BASE_URL = 'https://fapi.asterdex.com';\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\n\nconst MetricsAsterApiCallCounter = GlobalPrometheusRegistry.counter(\n 'aster_api_call',\n 'Number of aster api call',\n);\nconst terminal = Terminal.fromNodeEnv();\nconst request = async <T>(method: string, endpoint: string, params: any = {}): Promise<T> => {\n const url = new URL(BASE_URL);\n url.pathname = endpoint;\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined) continue;\n url.searchParams.set(key, `${value}`);\n }\n\n console.info(url.toString());\n MetricsAsterApiCallCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();\n const res = await fetch(url.toString(), {\n method,\n }).then((response) => response.json());\n if (res.code && res.code !== 0) {\n throw JSON.stringify(res);\n }\n return res;\n};\n\nconst createApi =\n <TReq, TRes>(method: string, endpoint: string) =>\n (params: TReq) =>\n request<TRes>(method, endpoint, params);\n\n/**\n * 获取资金费率历史\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E6%9F%A5%E8%AF%A2%E8%B5%84%E9%87%91%E8%B4%B9%E7%8E%87%E5%8E%86%E5%8F%B2\n */\nexport const getFApiV1FundingRate = createApi<\n {\n symbol?: string;\n startTime?: number;\n endTime?: number;\n limit?: number;\n },\n {\n symbol: string;\n fundingRate: string;\n fundingTime: number;\n }[]\n>('GET', '/fapi/v1/fundingRate');\n\n/**\n * 获取交易对信息\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E4%BA%A4%E6%98%93%E5%AF%B9%E4%BF%A1%E6%81%AF\n */\nexport const getFApiV1ExchangeInfo = createApi<\n {},\n {\n symbols: {\n symbol: string;\n status: 'TRADING' | 'BREAK' | 'HALT';\n baseAsset: string;\n quoteAsset: string;\n pricePrecision: number;\n quantityPrecision: number;\n baseAssetPrecision: number;\n quotePrecision: number;\n filters: {\n filterType: string;\n [key: string]: any;\n }[];\n }[];\n }\n>('GET', '/fapi/v1/exchangeInfo');\n\n/**\n * 获取未平仓合约数量\n *\n * 无 API 文档 (weird)\n */\nexport const getFApiV1OpenInterest = createApi<\n {\n symbol: string;\n },\n {\n symbol: string;\n openInterest: string;\n time: number;\n }\n>('GET', '/fapi/v1/openInterest');\n\n/**\n * 获取最新价格\n *\n * https://github.com/asterdex/api-docs/blob/master/aster-finance-futures-api_CN.md#%E6%9C%80%E6%96%B0%E4%BB%B7%E6%A0%BC\n */\nexport const getFApiV1TickerPrice = createApi<\n {},\n {\n symbol: string;\n price: string;\n time?: number;\n }[]\n>('GET', '/fapi/v1/ticker/price');\n"]}
|
|
@@ -18,18 +18,18 @@ const openInterestCache = (0, cache_1.createCache)(async (symbol) => {
|
|
|
18
18
|
return undefined;
|
|
19
19
|
}
|
|
20
20
|
}, { expire: OPEN_INTEREST_TTL });
|
|
21
|
-
const quote$ = (0, rxjs_1.defer)(() => (0, public_api_1.getFApiV1TickerPrice)({})).pipe((0, rxjs_1.mergeMap)((tickers) => tickers || []), (0, rxjs_1.
|
|
21
|
+
const quote$ = (0, rxjs_1.defer)(() => (0, public_api_1.getFApiV1TickerPrice)({})).pipe((0, rxjs_1.mergeMap)((tickers) => tickers || []), (0, rxjs_1.map)((ticker) => {
|
|
22
22
|
var _a;
|
|
23
23
|
return ({
|
|
24
24
|
datasource_id: 'ASTER',
|
|
25
|
-
product_id: (0, utils_1.encodePath)('PERP', ticker.symbol),
|
|
25
|
+
product_id: (0, utils_1.encodePath)('ASTER', 'PERP', ticker.symbol),
|
|
26
26
|
last_price: `${ticker.price}`,
|
|
27
27
|
bid_price: `${ticker.price}`,
|
|
28
28
|
ask_price: `${ticker.price}`,
|
|
29
|
-
open_interest:
|
|
29
|
+
open_interest: '0',
|
|
30
30
|
updated_at: new Date((_a = ticker.time) !== null && _a !== void 0 ? _a : Date.now()).toISOString(),
|
|
31
31
|
});
|
|
32
|
-
})
|
|
32
|
+
}), (0, rxjs_1.repeat)({ delay: 1000 }), (0, rxjs_1.retry)({ delay: 5000 }), (0, rxjs_1.shareReplay)({ bufferSize: 1, refCount: true }));
|
|
33
33
|
if (process.env.WRITE_QUOTE_TO_SQL === 'true') {
|
|
34
34
|
quote$
|
|
35
35
|
.pipe((0, sql_1.writeToSQL)({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../src/services/markets/quote.ts"],"names":[],"mappings":";;AAAA,yCAA4C;AAE5C,+CAA4C;AAC5C,qCAAyC;AACzC,yCAAuD;AACvD,+BAAsF;AACtF,qDAAmF;AAEnF,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAO,CAAC;AAE1G,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EACnC,KAAK,EAAE,MAAc,EAAE,EAAE;IACvB,IAAI;QACF,MAAM,IAAI,GAAG,MAAM,IAAA,kCAAqB,EAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,YAAY,CAAC;KAC1B;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC5D,OAAO,SAAS,CAAC;KAClB;AACH,CAAC,EACD,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAC9B,CAAC;AAEF,MAAM,MAAM,GAAG,IAAA,YAAK,EAAC,GAAG,EAAE,CAAC,IAAA,iCAAoB,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CACvD,IAAA,eAAQ,EAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,EACpC,IAAA,
|
|
1
|
+
{"version":3,"file":"quote.js","sourceRoot":"","sources":["../../../src/services/markets/quote.ts"],"names":[],"mappings":";;AAAA,yCAA4C;AAE5C,+CAA4C;AAC5C,qCAAyC;AACzC,yCAAuD;AACvD,+BAAsF;AACtF,qDAAmF;AAEnF,MAAM,QAAQ,GAAG,mBAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,MAAO,CAAC;AAE1G,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EACnC,KAAK,EAAE,MAAc,EAAE,EAAE;IACvB,IAAI;QACF,MAAM,IAAI,GAAG,MAAM,IAAA,kCAAqB,EAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,YAAY,CAAC;KAC1B;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC5D,OAAO,SAAS,CAAC;KAClB;AACH,CAAC,EACD,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAC9B,CAAC;AAEF,MAAM,MAAM,GAAG,IAAA,YAAK,EAAC,GAAG,EAAE,CAAC,IAAA,iCAAoB,EAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CACvD,IAAA,eAAQ,EAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,EACpC,IAAA,UAAG,EACD,CAAC,MAAM,EAAmB,EAAE;;IAAC,OAAA,CAAC;QAC5B,aAAa,EAAE,OAAO;QACtB,UAAU,EAAE,IAAA,kBAAU,EAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;QACtD,UAAU,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE;QAC7B,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE;QAC5B,SAAS,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE;QAC5B,aAAa,EAAE,GAAG;QAClB,UAAU,EAAE,IAAI,IAAI,CAAC,MAAA,MAAM,CAAC,IAAI,mCAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;KAC9D,CAAC,CAAA;CAAA,CACH,EACD,IAAA,aAAM,EAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EACvB,IAAA,YAAK,EAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EACtB,IAAA,kBAAW,EAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC/C,CAAC;AAEF,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,MAAM,EAAE;IAC7C,MAAM;SACH,IAAI,CACH,IAAA,gBAAU,EAAC;QACT,QAAQ;QACR,SAAS,EAAE,OAAO;QAClB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,CAAC,eAAe,EAAE,YAAY,CAAC;KAC9C,CAAC,CACH;SACA,SAAS,EAAE,CAAC;IAEf,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE;QAC9E,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,EAAE;YAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;SACtD;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAA,aAAM,EAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;CACJ","sourcesContent":["import { createCache } from '@yuants/cache';\nimport type { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { writeToSQL } from '@yuants/sql';\nimport { decodePath, encodePath } from '@yuants/utils';\nimport { defer, filter, from, map, mergeMap, repeat, retry, shareReplay } from 'rxjs';\nimport { getFApiV1OpenInterest, getFApiV1TickerPrice } from '../../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\nconst OPEN_INTEREST_TTL = process.env.OPEN_INTEREST_TTL ? Number(process.env.OPEN_INTEREST_TTL) : 120_000;\n\nconst openInterestCache = createCache<string>(\n async (symbol: string) => {\n try {\n const data = await getFApiV1OpenInterest({ symbol });\n return data.openInterest;\n } catch (error) {\n console.warn('getFApiV1OpenInterest failed', symbol, error);\n return undefined;\n }\n },\n { expire: OPEN_INTEREST_TTL },\n);\n\nconst quote$ = defer(() => getFApiV1TickerPrice({})).pipe(\n mergeMap((tickers) => tickers || []),\n map(\n (ticker): Partial<IQuote> => ({\n datasource_id: 'ASTER',\n product_id: encodePath('ASTER', 'PERP', ticker.symbol),\n last_price: `${ticker.price}`,\n bid_price: `${ticker.price}`,\n ask_price: `${ticker.price}`,\n open_interest: '0',\n updated_at: new Date(ticker.time ?? Date.now()).toISOString(),\n }),\n ),\n repeat({ delay: 1000 }),\n retry({ delay: 5000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nif (process.env.WRITE_QUOTE_TO_SQL === 'true') {\n quote$\n .pipe(\n writeToSQL({\n terminal,\n tableName: 'quote',\n writeInterval: 1000,\n conflictKeys: ['datasource_id', 'product_id'],\n }),\n )\n .subscribe();\n\n terminal.channel.publishChannel('quote', { pattern: '^ASTER/' }, (channel_id) => {\n const [datasourceId, productId] = decodePath(channel_id);\n if (!datasourceId || !productId) {\n throw new Error(`Invalid channel_id: ${channel_id}`);\n }\n return quote$.pipe(filter((quote) => quote.product_id === productId));\n });\n}\n"]}
|
package/package.json
CHANGED
package/temp/package-deps.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"apps/vendor-aster/AGENTS.md": "dcd006d19a5c3b73081525d7c0afea68cd6d058b",
|
|
3
|
-
"apps/vendor-aster/CHANGELOG.json": "
|
|
4
|
-
"apps/vendor-aster/CHANGELOG.md": "
|
|
3
|
+
"apps/vendor-aster/CHANGELOG.json": "46c0978373beb0a14b9df3c11cb3e15cc8bbe90d",
|
|
4
|
+
"apps/vendor-aster/CHANGELOG.md": "1bb2e5d84c160e6a9c3c79d664ac842fbcd6c50b",
|
|
5
5
|
"apps/vendor-aster/SESSION_NOTES.md": "f54c13cf4182d8a5e720f6db5d3acc323655ea49",
|
|
6
6
|
"apps/vendor-aster/config/jest.config.json": "4bb17bde3ee911163a3edb36a6eb71491d80b1bd",
|
|
7
7
|
"apps/vendor-aster/config/rig.json": "f6c7b5537dc77a3170ba9f008bae3b6c3ee11956",
|
|
8
8
|
"apps/vendor-aster/config/typescript.json": "854907e8a821f2050f6533368db160c649c25348",
|
|
9
|
-
"apps/vendor-aster/package.json": "
|
|
10
|
-
"apps/vendor-aster/src/api/private-api.ts": "
|
|
11
|
-
"apps/vendor-aster/src/api/public-api.ts": "
|
|
9
|
+
"apps/vendor-aster/package.json": "c1fee6f1921edf1ef6dc98248b218d5738ebce01",
|
|
10
|
+
"apps/vendor-aster/src/api/private-api.ts": "71f2f794377a45c64f688a663111318e36463bdb",
|
|
11
|
+
"apps/vendor-aster/src/api/public-api.ts": "052be628aec3a1bec00fa7da102c4932d74249a4",
|
|
12
12
|
"apps/vendor-aster/src/index.ts": "509ef4c18ec2deb8a6e11ed5682334433cb2bcb2",
|
|
13
13
|
"apps/vendor-aster/src/services/accounts/perp.ts": "4bdb41564394f1ddc9a1516a66a66c56d00d4581",
|
|
14
14
|
"apps/vendor-aster/src/services/accounts/profile.ts": "fc57e7d2c865790dd257c043c8dd5cf5c641b7fd",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"apps/vendor-aster/src/services/exchange.ts": "4cdd15bfff1d1e4b1aceda287af6b280d088ccee",
|
|
17
17
|
"apps/vendor-aster/src/services/markets/interest_rate.ts": "b8a43085be3632fe0afe00502c509b5984ab9cd3",
|
|
18
18
|
"apps/vendor-aster/src/services/markets/product.ts": "a0e5c02e9f99682cd2f4cb0a9e7a01747e540b4e",
|
|
19
|
-
"apps/vendor-aster/src/services/markets/quote.ts": "
|
|
19
|
+
"apps/vendor-aster/src/services/markets/quote.ts": "68bcc4255583a58529914742eaa39badef8993b5",
|
|
20
20
|
"apps/vendor-aster/src/services/orders/cancelOrder.ts": "09a6d3b10a218ad226346dd68d0ff0207083a7f1",
|
|
21
21
|
"apps/vendor-aster/src/services/orders/listOrders.ts": "579e83c45f6c4435ad3f5a2d3fe163a036bb9fd1",
|
|
22
22
|
"apps/vendor-aster/src/services/orders/submitOrder.ts": "9e99af753829d8f75a110cb29042ee3ebe6b724d",
|