@yuants/vendor-binance 0.9.0 → 0.10.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.
Files changed (74) hide show
  1. package/dist/api/client.js +13 -2
  2. package/dist/api/client.js.map +1 -1
  3. package/dist/api/public-api.js +6 -0
  4. package/dist/api/public-api.js.map +1 -1
  5. package/dist/index.js +1 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/legacy_index.js +163 -197
  8. package/dist/legacy_index.js.map +1 -1
  9. package/dist/public-data/product.js +82 -3
  10. package/dist/public-data/product.js.map +1 -1
  11. package/dist/public-data/quote.js +2 -2
  12. package/dist/public-data/quote.js.map +1 -1
  13. package/dist/services/accounts/profile.js +4 -15
  14. package/dist/services/accounts/profile.js.map +1 -1
  15. package/dist/services/accounts/spot.js.map +1 -1
  16. package/dist/services/accounts/unified.js +1 -11
  17. package/dist/services/accounts/unified.js.map +1 -1
  18. package/dist/services/exchange.js +56 -0
  19. package/dist/services/exchange.js.map +1 -0
  20. package/dist/services/orders/listOrders.js +44 -35
  21. package/dist/services/orders/listOrders.js.map +1 -1
  22. package/lib/api/client.d.ts.map +1 -1
  23. package/lib/api/client.js +12 -1
  24. package/lib/api/client.js.map +1 -1
  25. package/lib/api/public-api.d.ts +41 -0
  26. package/lib/api/public-api.d.ts.map +1 -1
  27. package/lib/api/public-api.js +8 -1
  28. package/lib/api/public-api.js.map +1 -1
  29. package/lib/index.d.ts +1 -2
  30. package/lib/index.d.ts.map +1 -1
  31. package/lib/index.js +1 -2
  32. package/lib/index.js.map +1 -1
  33. package/lib/legacy_index.d.ts +0 -1
  34. package/lib/legacy_index.js +162 -198
  35. package/lib/legacy_index.js.map +1 -1
  36. package/lib/public-data/product.d.ts +2 -1
  37. package/lib/public-data/product.d.ts.map +1 -1
  38. package/lib/public-data/product.js +83 -2
  39. package/lib/public-data/product.js.map +1 -1
  40. package/lib/public-data/quote.js +2 -2
  41. package/lib/public-data/quote.js.map +1 -1
  42. package/lib/services/accounts/profile.d.ts +1 -5
  43. package/lib/services/accounts/profile.d.ts.map +1 -1
  44. package/lib/services/accounts/profile.js +6 -17
  45. package/lib/services/accounts/profile.js.map +1 -1
  46. package/lib/services/accounts/spot.d.ts +2 -2
  47. package/lib/services/accounts/spot.d.ts.map +1 -1
  48. package/lib/services/accounts/spot.js.map +1 -1
  49. package/lib/services/accounts/unified.d.ts +2 -2
  50. package/lib/services/accounts/unified.d.ts.map +1 -1
  51. package/lib/services/accounts/unified.js +1 -11
  52. package/lib/services/accounts/unified.js.map +1 -1
  53. package/lib/services/exchange.d.ts +2 -0
  54. package/lib/services/exchange.d.ts.map +1 -0
  55. package/lib/services/exchange.js +58 -0
  56. package/lib/services/exchange.js.map +1 -0
  57. package/lib/services/orders/listOrders.d.ts +4 -2
  58. package/lib/services/orders/listOrders.d.ts.map +1 -1
  59. package/lib/services/orders/listOrders.js +47 -36
  60. package/lib/services/orders/listOrders.js.map +1 -1
  61. package/package.json +2 -1
  62. package/temp/package-deps.json +17 -17
  63. package/dist/services/account-actions-with-credential.js +0 -34
  64. package/dist/services/account-actions-with-credential.js.map +0 -1
  65. package/dist/services/order-actions-with-credential.js +0 -21
  66. package/dist/services/order-actions-with-credential.js.map +0 -1
  67. package/lib/services/account-actions-with-credential.d.ts +0 -2
  68. package/lib/services/account-actions-with-credential.d.ts.map +0 -1
  69. package/lib/services/account-actions-with-credential.js +0 -36
  70. package/lib/services/account-actions-with-credential.js.map +0 -1
  71. package/lib/services/order-actions-with-credential.d.ts +0 -2
  72. package/lib/services/order-actions-with-credential.d.ts.map +0 -1
  73. package/lib/services/order-actions-with-credential.js +0 -23
  74. package/lib/services/order-actions-with-credential.js.map +0 -1
@@ -1,10 +1,9 @@
1
1
  import { provideQueryProductsService } from '@yuants/data-product';
2
2
  import { Terminal } from '@yuants/protocol';
3
3
  import { encodePath } from '@yuants/utils';
4
- import { getFutureExchangeInfo } from '../api/public-api';
4
+ import { getFutureExchangeInfo, getSpotExchangeInfo } from '../api/public-api';
5
5
  const terminal = Terminal.fromNodeEnv();
6
- // Provide QueryProducts service with the new design
7
- const cache = provideQueryProductsService(terminal, 'BINANCE', async (req) => {
6
+ export const listProducts = async () => {
8
7
  // Directly call the external API to get exchange info
9
8
  const exchangeInfo = await getFutureExchangeInfo();
10
9
  // Convert symbols to IProduct format
@@ -30,6 +29,86 @@ const cache = provideQueryProductsService(terminal, 'BINANCE', async (req) => {
30
29
  no_interest_rate: false,
31
30
  };
32
31
  });
32
+ };
33
+ // Provide QueryProducts service with the new design
34
+ const cache = provideQueryProductsService(terminal, 'BINANCE', async (req) => {
35
+ // Directly call the external API to get exchange info
36
+ const [futureExchangeInfo, spotExchangeInfo] = await Promise.all([
37
+ getFutureExchangeInfo(),
38
+ getSpotExchangeInfo(),
39
+ ]);
40
+ const products = [];
41
+ // Convert future symbols to IProduct format
42
+ for (const symbol of futureExchangeInfo.symbols) {
43
+ products.push({
44
+ datasource_id: 'BINANCE',
45
+ product_id: encodePath('BINANCE', 'USDT-FUTURE', symbol.symbol),
46
+ base_currency: symbol.baseAsset,
47
+ quote_currency: symbol.quoteAsset,
48
+ price_step: +`1e-${symbol.pricePrecision}`,
49
+ value_scale: 1,
50
+ volume_step: +`1e-${symbol.quantityPrecision}`,
51
+ name: `${symbol.baseAsset}/${symbol.quoteAsset} PERP`,
52
+ value_scale_unit: '',
53
+ margin_rate: +symbol.requiredMarginPercent / 100,
54
+ value_based_cost: 0,
55
+ volume_based_cost: 0,
56
+ max_position: 0,
57
+ max_volume: 0,
58
+ allow_long: true,
59
+ allow_short: true,
60
+ market_id: 'BINANCE/USDT-FUTURE',
61
+ no_interest_rate: false,
62
+ });
63
+ }
64
+ // Convert spot symbols to IProduct format
65
+ for (const symbol of spotExchangeInfo.symbols) {
66
+ if (symbol.isSpotTradingAllowed) {
67
+ products.push({
68
+ datasource_id: 'BINANCE',
69
+ product_id: encodePath('BINANCE', 'SPOT', symbol.symbol),
70
+ base_currency: symbol.baseAsset,
71
+ quote_currency: symbol.quoteAsset,
72
+ price_step: +`1e-${symbol.quotePrecision}`,
73
+ value_scale: 1,
74
+ volume_step: +`1e-${symbol.baseAssetPrecision}`,
75
+ name: `${symbol.baseAsset}/${symbol.quoteAsset} SPOT`,
76
+ value_scale_unit: '',
77
+ margin_rate: 1,
78
+ value_based_cost: 0,
79
+ volume_based_cost: 0,
80
+ max_position: 0,
81
+ max_volume: 0,
82
+ allow_long: true,
83
+ allow_short: false,
84
+ market_id: 'BINANCE/SPOT',
85
+ no_interest_rate: true,
86
+ });
87
+ }
88
+ if (symbol.isMarginTradingAllowed) {
89
+ products.push({
90
+ datasource_id: 'BINANCE',
91
+ product_id: encodePath('BINANCE', 'MARGIN', symbol.symbol),
92
+ base_currency: symbol.baseAsset,
93
+ quote_currency: symbol.quoteAsset,
94
+ price_step: +`1e-${symbol.quotePrecision}`,
95
+ value_scale: 1,
96
+ volume_step: +`1e-${symbol.baseAssetPrecision}`,
97
+ name: `${symbol.baseAsset}/${symbol.quoteAsset} MARGIN`,
98
+ value_scale_unit: '',
99
+ margin_rate: 1,
100
+ value_based_cost: 0,
101
+ volume_based_cost: 0,
102
+ max_position: 0,
103
+ max_volume: 0,
104
+ allow_long: true,
105
+ allow_short: true,
106
+ market_id: 'BINANCE/MARGIN',
107
+ no_interest_rate: false,
108
+ });
109
+ }
110
+ }
111
+ return products;
33
112
  }, {
34
113
  auto_refresh_interval: 3600000,
35
114
  });
@@ -1 +1 @@
1
- {"version":3,"file":"product.js","sourceRoot":"","sources":["../../src/public-data/product.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,oDAAoD;AACpD,MAAM,KAAK,GAAG,2BAA2B,CACvC,QAAQ,EACR,SAAS,EACT,KAAK,EAAE,GAA0B,EAAuB,EAAE;IACxD,sDAAsD;IACtD,MAAM,YAAY,GAAG,MAAM,qBAAqB,EAAE,CAAC;IAEnD,qCAAqC;IACrC,OAAO,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAY,EAAE;QACnD,OAAO;YACL,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC;YAC/D,aAAa,EAAE,MAAM,CAAC,SAAS;YAC/B,cAAc,EAAE,MAAM,CAAC,UAAU;YACjC,UAAU,EAAE,CAAC,MAAM,MAAM,CAAC,cAAc,EAAE;YAC1C,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,CAAC,MAAM,MAAM,CAAC,iBAAiB,EAAE;YAC9C,IAAI,EAAE,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,UAAU,OAAO;YACrD,gBAAgB,EAAE,EAAE;YACpB,WAAW,EAAE,CAAC,MAAM,CAAC,qBAAqB,GAAG,GAAG;YAChD,gBAAgB,EAAE,CAAC;YACnB,iBAAiB,EAAE,CAAC;YACpB,YAAY,EAAE,CAAC;YACf,UAAU,EAAE,CAAC;YACb,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,IAAI;YACjB,SAAS,EAAE,qBAAqB;YAChC,gBAAgB,EAAE,KAAK;SACxB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,EACD;IACE,qBAAqB,EAAE,OAAQ;CAChC,CACF,CAAC","sourcesContent":["import { IProduct, IQueryProductsRequest, provideQueryProductsService } from '@yuants/data-product';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { getFutureExchangeInfo } from '../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\n\n// Provide QueryProducts service with the new design\nconst cache = provideQueryProductsService(\n terminal,\n 'BINANCE',\n async (req: IQueryProductsRequest): Promise<IProduct[]> => {\n // Directly call the external API to get exchange info\n const exchangeInfo = await getFutureExchangeInfo();\n\n // Convert symbols to IProduct format\n return exchangeInfo.symbols.map((symbol): IProduct => {\n return {\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', symbol.symbol),\n base_currency: symbol.baseAsset,\n quote_currency: symbol.quoteAsset,\n price_step: +`1e-${symbol.pricePrecision}`,\n value_scale: 1,\n volume_step: +`1e-${symbol.quantityPrecision}`,\n name: `${symbol.baseAsset}/${symbol.quoteAsset} PERP`,\n value_scale_unit: '',\n margin_rate: +symbol.requiredMarginPercent / 100,\n value_based_cost: 0,\n volume_based_cost: 0,\n max_position: 0,\n max_volume: 0,\n allow_long: true,\n allow_short: true,\n market_id: 'BINANCE/USDT-FUTURE',\n no_interest_rate: false,\n };\n });\n },\n {\n auto_refresh_interval: 3600_000,\n },\n);\n"]}
1
+ {"version":3,"file":"product.js","sourceRoot":"","sources":["../../src/public-data/product.ts"],"names":[],"mappings":"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","sourcesContent":["import { IProduct, IQueryProductsRequest, provideQueryProductsService } from '@yuants/data-product';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { getFutureExchangeInfo, getSpotExchangeInfo } from '../api/public-api';\n\nconst terminal = Terminal.fromNodeEnv();\n\nexport const listProducts = async () => {\n // Directly call the external API to get exchange info\n const exchangeInfo = await getFutureExchangeInfo();\n\n // Convert symbols to IProduct format\n return exchangeInfo.symbols.map((symbol): IProduct => {\n return {\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', symbol.symbol),\n base_currency: symbol.baseAsset,\n quote_currency: symbol.quoteAsset,\n price_step: +`1e-${symbol.pricePrecision}`,\n value_scale: 1,\n volume_step: +`1e-${symbol.quantityPrecision}`,\n name: `${symbol.baseAsset}/${symbol.quoteAsset} PERP`,\n value_scale_unit: '',\n margin_rate: +symbol.requiredMarginPercent / 100,\n value_based_cost: 0,\n volume_based_cost: 0,\n max_position: 0,\n max_volume: 0,\n allow_long: true,\n allow_short: true,\n market_id: 'BINANCE/USDT-FUTURE',\n no_interest_rate: false,\n };\n });\n};\n\n// Provide QueryProducts service with the new design\nconst cache = provideQueryProductsService(\n terminal,\n 'BINANCE',\n async (req: IQueryProductsRequest): Promise<IProduct[]> => {\n // Directly call the external API to get exchange info\n const [futureExchangeInfo, spotExchangeInfo] = await Promise.all([\n getFutureExchangeInfo(),\n getSpotExchangeInfo(),\n ]);\n\n const products: IProduct[] = [];\n\n // Convert future symbols to IProduct format\n for (const symbol of futureExchangeInfo.symbols) {\n products.push({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', symbol.symbol),\n base_currency: symbol.baseAsset,\n quote_currency: symbol.quoteAsset,\n price_step: +`1e-${symbol.pricePrecision}`,\n value_scale: 1,\n volume_step: +`1e-${symbol.quantityPrecision}`,\n name: `${symbol.baseAsset}/${symbol.quoteAsset} PERP`,\n value_scale_unit: '',\n margin_rate: +symbol.requiredMarginPercent / 100,\n value_based_cost: 0,\n volume_based_cost: 0,\n max_position: 0,\n max_volume: 0,\n allow_long: true,\n allow_short: true,\n market_id: 'BINANCE/USDT-FUTURE',\n no_interest_rate: false,\n });\n }\n\n // Convert spot symbols to IProduct format\n for (const symbol of spotExchangeInfo.symbols) {\n if (symbol.isSpotTradingAllowed) {\n products.push({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', symbol.symbol),\n base_currency: symbol.baseAsset,\n quote_currency: symbol.quoteAsset,\n price_step: +`1e-${symbol.quotePrecision}`,\n value_scale: 1,\n volume_step: +`1e-${symbol.baseAssetPrecision}`,\n name: `${symbol.baseAsset}/${symbol.quoteAsset} SPOT`,\n value_scale_unit: '',\n margin_rate: 1,\n value_based_cost: 0,\n volume_based_cost: 0,\n max_position: 0,\n max_volume: 0,\n allow_long: true,\n allow_short: false,\n market_id: 'BINANCE/SPOT',\n no_interest_rate: true,\n });\n }\n\n if (symbol.isMarginTradingAllowed) {\n products.push({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'MARGIN', symbol.symbol),\n base_currency: symbol.baseAsset,\n quote_currency: symbol.quoteAsset,\n price_step: +`1e-${symbol.quotePrecision}`,\n value_scale: 1,\n volume_step: +`1e-${symbol.baseAssetPrecision}`,\n name: `${symbol.baseAsset}/${symbol.quoteAsset} MARGIN`,\n value_scale_unit: '',\n margin_rate: 1,\n value_based_cost: 0,\n volume_based_cost: 0,\n max_position: 0,\n max_volume: 0,\n allow_long: true,\n allow_short: true,\n market_id: 'BINANCE/MARGIN',\n no_interest_rate: false,\n });\n }\n }\n\n return products;\n },\n {\n auto_refresh_interval: 3600_000,\n },\n);\n"]}
@@ -50,7 +50,7 @@ const quoteFromOpenInterest$ = futureBookTicker$.pipe(mergeMap((entries) => from
50
50
  product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),
51
51
  open_interest: `${openInterest !== null && openInterest !== void 0 ? openInterest : 0}`,
52
52
  }))), 5));
53
- const quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(repeat({ delay: 1000 }), retry({ delay: 30000 }), shareReplay({ bufferSize: 1, refCount: true }), mergeMap((entries) => from(entries || [])), map((entry) => ({
53
+ const quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(mergeMap((entries) => from(entries || [])), map((entry) => ({
54
54
  datasource_id: 'BINANCE',
55
55
  product_id: encodePath('BINANCE', 'SPOT', entry.symbol),
56
56
  bid_price: entry.bidPrice,
@@ -58,7 +58,7 @@ const quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(repeat(
58
58
  bid_volume: entry.bidQty,
59
59
  ask_volume: entry.askQty,
60
60
  updated_at: formatTime(Date.now()),
61
- })));
61
+ })), repeat({ delay: 1000 }), retry({ delay: 30000 }), shareReplay({ bufferSize: 1, refCount: true }));
62
62
  const marginInterestRateCache = createCache(async (asset) => {
63
63
  var _a;
64
64
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/public-data/quote.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { writeToSQL } from '@yuants/sql';\nimport { decodePath, encodePath, formatTime } from '@yuants/utils';\nimport {\n defer,\n filter,\n from,\n groupBy,\n map,\n merge,\n mergeMap,\n repeat,\n retry,\n scan,\n share,\n shareReplay,\n} from 'rxjs';\nimport { getMarginAllPairs, getMarginNextHourlyInterestRate, IMarginPair } from '../api/private-api';\nimport {\n getFutureBookTicker,\n getFutureOpenInterest,\n getFuturePremiumIndex,\n getSpotBookTicker,\n} 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<number>(\n async (symbol: string) => {\n try {\n const data = await getFutureOpenInterest({ symbol });\n return Number(data.openInterest ?? 0);\n } catch (err) {\n console.warn('getFutureOpenInterest failed', symbol, err);\n return undefined;\n }\n },\n {\n expire: OPEN_INTEREST_TTL,\n },\n);\n\nconst futurePremiumIndex$ = defer(() => getFuturePremiumIndex({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst futureBookTicker$ = defer(() => getFutureBookTicker({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst quoteFromPremiumIndex$ = futurePremiumIndex$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n last_price: entry.markPrice,\n // Use the latest funding rate so that long pays when fundingRate > 0\n interest_rate_long: `${-Number(entry.lastFundingRate)}`,\n interest_rate_short: entry.lastFundingRate,\n interest_rate_next_settled_at: formatTime(entry.nextFundingTime),\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromBookTicker$ = futureBookTicker$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromOpenInterest$ = futureBookTicker$.pipe(\n mergeMap((entries) => from(entries || [])),\n mergeMap(\n (entry) =>\n from(openInterestCache.query(entry.symbol)).pipe(\n map(\n (openInterest): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n open_interest: `${openInterest ?? 0}`,\n }),\n ),\n ),\n 5,\n ),\n);\n\nconst quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n bid_volume: entry.bidQty,\n ask_volume: entry.askQty,\n updated_at: formatTime(Date.now()),\n }),\n ),\n);\n\nconst marginInterestRateCache = createCache<string>(\n async (asset: string) => {\n try {\n const data = await getMarginNextHourlyInterestRate({\n assets: asset,\n isIsolated: false,\n });\n return data[0]?.nextHourlyInterestRate;\n } catch (err) {\n return undefined;\n }\n },\n {\n expire: 60_000,\n },\n);\n\nconst marginPairs$ = defer(() => getMarginAllPairs()).pipe(\n repeat({ delay: 3600_000 }), // Refresh pair list hourly\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst quoteFromMarginRates$ = marginPairs$.pipe(\n mergeMap((pairs: IMarginPair[]) =>\n from(pairs).pipe(\n mergeMap(\n (pair) =>\n defer(async () => {\n const [baseRate, quoteRate] = await Promise.all([\n marginInterestRateCache.query(pair.base),\n marginInterestRateCache.query(pair.quote),\n ]);\n return {\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', pair.symbol),\n // User instruction: Long = Quote Rate, Short = Base Rate\n interest_rate_long: quoteRate,\n interest_rate_short: baseRate,\n updated_at: formatTime(Date.now()),\n } as Partial<IQuote>;\n }),\n 5, // Concurrency\n ),\n ),\n ),\n repeat({ delay: 60_000 }),\n);\n\nconst quote$ = merge(\n quoteFromPremiumIndex$,\n quoteFromBookTicker$,\n quoteFromOpenInterest$,\n quoteFromSpotBookTicker$,\n quoteFromMarginRates$,\n).pipe(\n groupBy((quote) => quote.product_id),\n mergeMap((group$) =>\n group$.pipe(\n scan(\n (acc, cur) =>\n Object.assign(acc, cur, {\n datasource_id: 'BINANCE',\n product_id: group$.key,\n }),\n {} as Partial<IQuote>,\n ),\n ),\n ),\n share(),\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: 1_000,\n conflictKeys: ['datasource_id', 'product_id'],\n }),\n )\n .subscribe();\n\n terminal.channel.publishChannel('quote', { pattern: '^BINANCE/' }, (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
+ {"version":3,"file":"quote.js","sourceRoot":"","sources":["../../src/public-data/quote.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { IQuote } from '@yuants/data-quote';\nimport { Terminal } from '@yuants/protocol';\nimport { writeToSQL } from '@yuants/sql';\nimport { decodePath, encodePath, formatTime } from '@yuants/utils';\nimport {\n defer,\n filter,\n from,\n groupBy,\n map,\n merge,\n mergeMap,\n repeat,\n retry,\n scan,\n share,\n shareReplay,\n} from 'rxjs';\nimport { getMarginAllPairs, getMarginNextHourlyInterestRate, IMarginPair } from '../api/private-api';\nimport {\n getFutureBookTicker,\n getFutureOpenInterest,\n getFuturePremiumIndex,\n getSpotBookTicker,\n} 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<number>(\n async (symbol: string) => {\n try {\n const data = await getFutureOpenInterest({ symbol });\n return Number(data.openInterest ?? 0);\n } catch (err) {\n console.warn('getFutureOpenInterest failed', symbol, err);\n return undefined;\n }\n },\n {\n expire: OPEN_INTEREST_TTL,\n },\n);\n\nconst futurePremiumIndex$ = defer(() => getFuturePremiumIndex({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst futureBookTicker$ = defer(() => getFutureBookTicker({})).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst quoteFromPremiumIndex$ = futurePremiumIndex$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n last_price: entry.markPrice,\n // Use the latest funding rate so that long pays when fundingRate > 0\n interest_rate_long: `${-Number(entry.lastFundingRate)}`,\n interest_rate_short: entry.lastFundingRate,\n interest_rate_next_settled_at: formatTime(entry.nextFundingTime),\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromBookTicker$ = futureBookTicker$.pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n updated_at: formatTime(entry.time ?? Date.now()),\n }),\n ),\n);\n\nconst quoteFromOpenInterest$ = futureBookTicker$.pipe(\n mergeMap((entries) => from(entries || [])),\n mergeMap(\n (entry) =>\n from(openInterestCache.query(entry.symbol)).pipe(\n map(\n (openInterest): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', entry.symbol),\n open_interest: `${openInterest ?? 0}`,\n }),\n ),\n ),\n 5,\n ),\n);\n\nconst quoteFromSpotBookTicker$ = defer(() => getSpotBookTicker({})).pipe(\n mergeMap((entries) => from(entries || [])),\n map(\n (entry): Partial<IQuote> => ({\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', entry.symbol),\n bid_price: entry.bidPrice,\n ask_price: entry.askPrice,\n bid_volume: entry.bidQty,\n ask_volume: entry.askQty,\n updated_at: formatTime(Date.now()),\n }),\n ),\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst marginInterestRateCache = createCache<string>(\n async (asset: string) => {\n try {\n const data = await getMarginNextHourlyInterestRate({\n assets: asset,\n isIsolated: false,\n });\n return data[0]?.nextHourlyInterestRate;\n } catch (err) {\n return undefined;\n }\n },\n {\n expire: 60_000,\n },\n);\n\nconst marginPairs$ = defer(() => getMarginAllPairs()).pipe(\n repeat({ delay: 3600_000 }), // Refresh pair list hourly\n retry({ delay: 60_000 }),\n shareReplay({ bufferSize: 1, refCount: true }),\n);\n\nconst quoteFromMarginRates$ = marginPairs$.pipe(\n mergeMap((pairs: IMarginPair[]) =>\n from(pairs).pipe(\n mergeMap(\n (pair) =>\n defer(async () => {\n const [baseRate, quoteRate] = await Promise.all([\n marginInterestRateCache.query(pair.base),\n marginInterestRateCache.query(pair.quote),\n ]);\n return {\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', pair.symbol),\n // User instruction: Long = Quote Rate, Short = Base Rate\n interest_rate_long: quoteRate,\n interest_rate_short: baseRate,\n updated_at: formatTime(Date.now()),\n } as Partial<IQuote>;\n }),\n 5, // Concurrency\n ),\n ),\n ),\n repeat({ delay: 60_000 }),\n);\n\nconst quote$ = merge(\n quoteFromPremiumIndex$,\n quoteFromBookTicker$,\n quoteFromOpenInterest$,\n quoteFromSpotBookTicker$,\n quoteFromMarginRates$,\n).pipe(\n groupBy((quote) => quote.product_id),\n mergeMap((group$) =>\n group$.pipe(\n scan(\n (acc, cur) =>\n Object.assign(acc, cur, {\n datasource_id: 'BINANCE',\n product_id: group$.key,\n }),\n {} as Partial<IQuote>,\n ),\n ),\n ),\n share(),\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: 1_000,\n conflictKeys: ['datasource_id', 'product_id'],\n }),\n )\n .subscribe();\n\n terminal.channel.publishChannel('quote', { pattern: '^BINANCE/' }, (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,22 +1,11 @@
1
- import { createCache } from '@yuants/cache';
1
+ import { encodePath } from '@yuants/utils';
2
2
  import { isApiError } from '../../api/client';
3
3
  import { getSpotAccountInfo } from '../../api/private-api';
4
- const PROFILE_TTL = 60000;
5
- const serializeCredential = (credential) => JSON.stringify(credential);
6
- const deserializeCredential = (key) => JSON.parse(key);
7
- const accountProfileCache = createCache(async (key) => {
8
- const spotAccountInfo = await getSpotAccountInfo(deserializeCredential(key));
4
+ export const getCredentialId = async (credential) => {
5
+ const spotAccountInfo = await getSpotAccountInfo(credential);
9
6
  if (isApiError(spotAccountInfo)) {
10
7
  throw new Error(spotAccountInfo.msg);
11
8
  }
12
- return { uid: `${spotAccountInfo.uid}` };
13
- }, { expire: PROFILE_TTL });
14
- export const resolveAccountProfile = async (credential) => {
15
- const key = serializeCredential(credential);
16
- const profile = await accountProfileCache.query(key);
17
- if (!profile) {
18
- throw new Error('Unable to resolve Binance account profile');
19
- }
20
- return profile;
9
+ return encodePath('BINANCE', spotAccountInfo.uid);
21
10
  };
22
11
  //# sourceMappingURL=profile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/services/accounts/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAe,MAAM,uBAAuB,CAAC;AAMxE,MAAM,WAAW,GAAG,KAAM,CAAC;AAC3B,MAAM,mBAAmB,GAAG,CAAC,UAAuB,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACpF,MAAM,qBAAqB,GAAG,CAAC,GAAW,EAAe,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;AAE3F,MAAM,mBAAmB,GAAG,WAAW,CACrC,KAAK,EAAE,GAAG,EAAE,EAAE;IACZ,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;KACtC;IACD,OAAO,EAAE,GAAG,EAAE,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,CAAC;AAC3C,CAAC,EACD,EAAE,MAAM,EAAE,WAAW,EAAE,CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,UAAuB,EAA4B,EAAE;IAC/F,MAAM,GAAG,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;KAC9D;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import { createCache } from '@yuants/cache';\nimport { isApiError } from '../../api/client';\nimport { getSpotAccountInfo, ICredential } from '../../api/private-api';\n\ninterface IAccountProfile {\n uid: string;\n}\n\nconst PROFILE_TTL = 60_000;\nconst serializeCredential = (credential: ICredential) => JSON.stringify(credential);\nconst deserializeCredential = (key: string): ICredential => JSON.parse(key) as ICredential;\n\nconst accountProfileCache = createCache<IAccountProfile>(\n async (key) => {\n const spotAccountInfo = await getSpotAccountInfo(deserializeCredential(key));\n if (isApiError(spotAccountInfo)) {\n throw new Error(spotAccountInfo.msg);\n }\n return { uid: `${spotAccountInfo.uid}` };\n },\n { expire: PROFILE_TTL },\n);\n\nexport const resolveAccountProfile = async (credential: ICredential): Promise<IAccountProfile> => {\n const key = serializeCredential(credential);\n const profile = await accountProfileCache.query(key);\n if (!profile) {\n throw new Error('Unable to resolve Binance account profile');\n }\n return profile;\n};\n"]}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/services/accounts/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAe,MAAM,uBAAuB,CAAC;AAExE,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,UAAuB,EAAmB,EAAE;IAChF,MAAM,eAAe,GAAG,MAAM,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;KACtC;IACD,OAAO,UAAU,CAAC,SAAS,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC,CAAC","sourcesContent":["import { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getSpotAccountInfo, ICredential } from '../../api/private-api';\n\nexport const getCredentialId = async (credential: ICredential): Promise<string> => {\n const spotAccountInfo = await getSpotAccountInfo(credential);\n if (isApiError(spotAccountInfo)) {\n throw new Error(spotAccountInfo.msg);\n }\n return encodePath('BINANCE', spotAccountInfo.uid);\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"spot.js","sourceRoot":"","sources":["../../../src/services/accounts/spot.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6C,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAe,MAAM,uBAAuB,CAAC;AAExE,MAAM,CAAC,MAAM,0BAA0B,GAAgD,KAAK,EAAE,UAAU,EAAE,EAAE;IAC1G,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,UAAU,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;KAC1B;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ;SAC3B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAC/C,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAC9B,MAAM,QAAQ,GAAc,gBAAgB,CAAC;YAC3C,WAAW,EAAE,QAAQ,OAAO,CAAC,KAAK,EAAE;YACpC,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,MAAM,CAAC;YACjE,MAAM;YACN,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI;YAC1B,cAAc,EAAE,CAAC,EAAE,0BAA0B;SAC9C,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,QAAQ,EAAyB,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClE,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { IActionHandlerOfGetAccountInfo, IPosition, makeSpotPosition } from '@yuants/data-account';\nimport { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getSpotAccountInfo, ICredential } from '../../api/private-api';\n\nexport const getSpotAccountInfoSnapshot: IActionHandlerOfGetAccountInfo<ICredential> = async (credential) => {\n const res = await getSpotAccountInfo(credential, { omitZeroBalances: true });\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n const positions = res.balances\n .map((balance) => {\n const volume = +balance.free + +balance.locked;\n if (!volume) return undefined;\n const position: IPosition = makeSpotPosition({\n position_id: `spot/${balance.asset}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', `${balance.asset}USDT`),\n volume,\n free_volume: +balance.free,\n closable_price: 0, // TODO: fetch price later\n });\n return position;\n })\n .filter((position): position is IPosition => Boolean(position));\n return positions;\n};\n"]}
1
+ {"version":3,"file":"spot.js","sourceRoot":"","sources":["../../../src/services/accounts/spot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAe,MAAM,uBAAuB,CAAC;AAExE,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,EAAE,UAAuB,EAAwB,EAAE;IAChG,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,UAAU,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE;QACnB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;KAC1B;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ;SAC3B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACf,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAC/C,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAC9B,MAAM,QAAQ,GAAc,gBAAgB,CAAC;YAC3C,WAAW,EAAE,QAAQ,OAAO,CAAC,KAAK,EAAE;YACpC,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,MAAM,CAAC;YACjE,MAAM;YACN,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI;YAC1B,cAAc,EAAE,CAAC,EAAE,0BAA0B;SAC9C,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,QAAQ,EAAyB,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClE,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { IPosition, makeSpotPosition } from '@yuants/data-account';\nimport { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getSpotAccountInfo, ICredential } from '../../api/private-api';\n\nexport const getSpotAccountInfoSnapshot = async (credential: ICredential): Promise<IPosition[]> => {\n const res = await getSpotAccountInfo(credential, { omitZeroBalances: true });\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n const positions = res.balances\n .map((balance) => {\n const volume = +balance.free + +balance.locked;\n if (!volume) return undefined;\n const position: IPosition = makeSpotPosition({\n position_id: `spot/${balance.asset}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'SPOT', `${balance.asset}USDT`),\n volume,\n free_volume: +balance.free,\n closable_price: 0, // TODO: fetch price later\n });\n return position;\n })\n .filter((position): position is IPosition => Boolean(position));\n return positions;\n};\n"]}
@@ -1,7 +1,7 @@
1
1
  import { encodePath } from '@yuants/utils';
2
2
  import { isApiError } from '../../api/client';
3
3
  import { getUnifiedAccountBalance, getUnifiedUmAccount } from '../../api/private-api';
4
- export const getUnifiedAccountInfo = async (credential, _accountId) => {
4
+ export const getUnifiedAccountInfo = async (credential) => {
5
5
  const [balanceRes, umAccountRes] = await Promise.all([
6
6
  getUnifiedAccountBalance(credential),
7
7
  getUnifiedUmAccount(credential),
@@ -12,16 +12,6 @@ export const getUnifiedAccountInfo = async (credential, _accountId) => {
12
12
  if (isApiError(umAccountRes)) {
13
13
  throw new Error(umAccountRes.msg);
14
14
  }
15
- const usdtBalance = balanceRes.find((item) => item.asset === 'USDT');
16
- if (!usdtBalance) {
17
- throw new Error('USDT balance not found');
18
- }
19
- const usdtAsset = umAccountRes.assets.find((item) => item.asset === 'USDT');
20
- if (!usdtAsset) {
21
- throw new Error('USDT asset not found in UM account');
22
- }
23
- const equity = +usdtBalance.totalWalletBalance + +usdtBalance.umUnrealizedPNL;
24
- const free = equity - +usdtAsset.initialMargin;
25
15
  const positions = umAccountRes.positions
26
16
  .filter((position) => +position.positionAmt !== 0)
27
17
  .map((position) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"unified.js","sourceRoot":"","sources":["../../../src/services/accounts/unified.ts"],"names":[],"mappings":"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","sourcesContent":["import { IActionHandlerOfGetAccountInfo, IPosition } from '@yuants/data-account';\nimport { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getUnifiedAccountBalance, getUnifiedUmAccount, ICredential } from '../../api/private-api';\n\nexport const getUnifiedAccountInfo: IActionHandlerOfGetAccountInfo<ICredential> = async (\n credential,\n _accountId,\n) => {\n const [balanceRes, umAccountRes] = await Promise.all([\n getUnifiedAccountBalance(credential),\n getUnifiedUmAccount(credential),\n ]);\n if (isApiError(balanceRes)) {\n throw new Error(balanceRes.msg);\n }\n if (isApiError(umAccountRes)) {\n throw new Error(umAccountRes.msg);\n }\n const usdtBalance = balanceRes.find((item) => item.asset === 'USDT');\n if (!usdtBalance) {\n throw new Error('USDT balance not found');\n }\n const usdtAsset = umAccountRes.assets.find((item) => item.asset === 'USDT');\n if (!usdtAsset) {\n throw new Error('USDT asset not found in UM account');\n }\n\n const equity = +usdtBalance.totalWalletBalance + +usdtBalance.umUnrealizedPNL;\n const free = equity - +usdtAsset.initialMargin;\n\n const positions: IPosition[] = umAccountRes.positions\n .filter((position) => +position.positionAmt !== 0)\n .map((position) => ({\n position_id: `${position.symbol}/${position.positionSide}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', position.symbol),\n direction:\n position.positionSide === 'LONG'\n ? 'LONG'\n : position.positionSide === 'SHORT'\n ? 'SHORT'\n : position.positionSide === 'BOTH'\n ? 'BOTH'\n : 'UNKNOWN',\n volume: +position.positionAmt,\n free_volume: +position.positionAmt,\n position_price: +position.entryPrice,\n closable_price: +position.entryPrice + +position.unrealizedProfit / +position.positionAmt,\n floating_profit: +position.unrealizedProfit,\n valuation:\n +position.positionAmt *\n (+position.entryPrice +\n (+position.positionAmt === 0 ? 0 : +position.unrealizedProfit / +position.positionAmt)),\n }));\n\n return positions;\n};\n"]}
1
+ {"version":3,"file":"unified.js","sourceRoot":"","sources":["../../../src/services/accounts/unified.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAe,MAAM,uBAAuB,CAAC;AAEnG,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,UAAuB,EAAwB,EAAE;IAC3F,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnD,wBAAwB,CAAC,UAAU,CAAC;QACpC,mBAAmB,CAAC,UAAU,CAAC;KAChC,CAAC,CAAC;IACH,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;KACjC;IACD,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE;QAC5B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;KACnC;IAED,MAAM,SAAS,GAAgB,YAAY,CAAC,SAAS;SAClD,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,KAAK,CAAC,CAAC;SACjD,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClB,WAAW,EAAE,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,YAAY,EAAE;QAC1D,aAAa,EAAE,SAAS;QACxB,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC;QACjE,SAAS,EACP,QAAQ,CAAC,YAAY,KAAK,MAAM;YAC9B,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,OAAO;gBACnC,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,MAAM;oBAClC,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW;QAC7B,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW;QAClC,cAAc,EAAE,CAAC,QAAQ,CAAC,UAAU;QACpC,cAAc,EAAE,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,QAAQ,CAAC,gBAAgB,GAAG,CAAC,QAAQ,CAAC,WAAW;QACzF,eAAe,EAAE,CAAC,QAAQ,CAAC,gBAAgB;QAC3C,SAAS,EACP,CAAC,QAAQ,CAAC,WAAW;YACrB,CAAC,CAAC,QAAQ,CAAC,UAAU;gBACnB,CAAC,CAAC,QAAQ,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;KAC5F,CAAC,CAAC,CAAC;IAEN,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { IPosition } from '@yuants/data-account';\nimport { encodePath } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getUnifiedAccountBalance, getUnifiedUmAccount, ICredential } from '../../api/private-api';\n\nexport const getUnifiedAccountInfo = async (credential: ICredential): Promise<IPosition[]> => {\n const [balanceRes, umAccountRes] = await Promise.all([\n getUnifiedAccountBalance(credential),\n getUnifiedUmAccount(credential),\n ]);\n if (isApiError(balanceRes)) {\n throw new Error(balanceRes.msg);\n }\n if (isApiError(umAccountRes)) {\n throw new Error(umAccountRes.msg);\n }\n\n const positions: IPosition[] = umAccountRes.positions\n .filter((position) => +position.positionAmt !== 0)\n .map((position) => ({\n position_id: `${position.symbol}/${position.positionSide}`,\n datasource_id: 'BINANCE',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', position.symbol),\n direction:\n position.positionSide === 'LONG'\n ? 'LONG'\n : position.positionSide === 'SHORT'\n ? 'SHORT'\n : position.positionSide === 'BOTH'\n ? 'BOTH'\n : 'UNKNOWN',\n volume: +position.positionAmt,\n free_volume: +position.positionAmt,\n position_price: +position.entryPrice,\n closable_price: +position.entryPrice + +position.unrealizedProfit / +position.positionAmt,\n floating_profit: +position.unrealizedProfit,\n valuation:\n +position.positionAmt *\n (+position.entryPrice +\n (+position.positionAmt === 0 ? 0 : +position.unrealizedProfit / +position.positionAmt)),\n }));\n\n return positions;\n};\n"]}
@@ -0,0 +1,56 @@
1
+ import { provideExchangeServices } from '@yuants/exchange';
2
+ import { Terminal } from '@yuants/protocol';
3
+ import { decodePath } from '@yuants/utils';
4
+ import { listProducts } from '../public-data/product';
5
+ import { getCredentialId } from './accounts/profile';
6
+ import { getSpotAccountInfoSnapshot } from './accounts/spot';
7
+ import { getUnifiedAccountInfo } from './accounts/unified';
8
+ import { cancelOrder } from './orders/cancelOrder';
9
+ import { getOrdersByProductId, listSpotOrders, listUnifiedUmOrders } from './orders/listOrders';
10
+ import { modifyOrder } from './orders/modifyOrder';
11
+ import { submitOrder } from './orders/submitOrder';
12
+ const terminal = Terminal.fromNodeEnv();
13
+ provideExchangeServices(terminal, {
14
+ name: 'BINANCE',
15
+ credentialSchema: {
16
+ type: 'object',
17
+ required: ['access_key', 'secret_key'],
18
+ properties: {
19
+ access_key: { type: 'string' },
20
+ secret_key: { type: 'string' },
21
+ },
22
+ },
23
+ getCredentialId,
24
+ listProducts,
25
+ getPositions: async function (credential) {
26
+ const [uFuturePositions, spotPositions] = await Promise.all([
27
+ getUnifiedAccountInfo(credential),
28
+ getSpotAccountInfoSnapshot(credential),
29
+ ]);
30
+ return [...uFuturePositions, ...spotPositions];
31
+ },
32
+ getOrders: async function (credential) {
33
+ const [umOrders, spotOrders] = await Promise.all([
34
+ listUnifiedUmOrders(credential),
35
+ listSpotOrders(credential),
36
+ ]);
37
+ return [...umOrders, ...spotOrders];
38
+ },
39
+ getPositionsByProductId: async function (credential, product_id) {
40
+ const [_, instType] = decodePath(product_id); // BINANCE/USDT-FUTURE/ADAUSDT
41
+ if (instType === 'SPOT') {
42
+ const positions = await getSpotAccountInfoSnapshot(credential);
43
+ return positions.filter((position) => position.product_id === product_id);
44
+ }
45
+ if (instType === 'USDT-FUTURE') {
46
+ const positions = await getUnifiedAccountInfo(credential);
47
+ return positions.filter((position) => position.product_id === product_id);
48
+ }
49
+ throw new Error(`Unsupported instType: ${instType}`);
50
+ },
51
+ getOrdersByProductId,
52
+ submitOrder,
53
+ modifyOrder,
54
+ cancelOrder,
55
+ });
56
+ //# sourceMappingURL=exchange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/services/exchange.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,uBAAuB,CAAc,QAAQ,EAAE;IAC7C,IAAI,EAAE,SAAS;IACf,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;IACf,YAAY;IACZ,YAAY,EAAE,KAAK,WAAW,UAAuB;QACnD,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1D,qBAAqB,CAAC,UAAU,CAAC;YACjC,0BAA0B,CAAC,UAAU,CAAC;SACvC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,gBAAgB,EAAE,GAAG,aAAa,CAAC,CAAC;IACjD,CAAC;IACD,SAAS,EAAE,KAAK,WAAW,UAAuB;QAChD,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC/C,mBAAmB,CAAC,UAAU,CAAC;YAC/B,cAAc,CAAC,UAAU,CAAC;SAC3B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,UAAU,CAAC,CAAC;IACtC,CAAC;IACD,uBAAuB,EAAE,KAAK,WAC5B,UAAuB,EACvB,UAAkB;QAElB,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,8BAA8B;QAC5E,IAAI,QAAQ,KAAK,MAAM,EAAE;YACvB,MAAM,SAAS,GAAG,MAAM,0BAA0B,CAAC,UAAU,CAAC,CAAC;YAC/D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;SAC3E;QACD,IAAI,QAAQ,KAAK,aAAa,EAAE;YAC9B,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC;YAC1D,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;SAC3E;QACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,oBAAoB;IACpB,WAAW;IACX,WAAW;IACX,WAAW;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 { decodePath } from '@yuants/utils';\nimport { ICredential } from '../api/client';\nimport { listProducts } from '../public-data/product';\nimport { getCredentialId } from './accounts/profile';\nimport { getSpotAccountInfoSnapshot } from './accounts/spot';\nimport { getUnifiedAccountInfo } from './accounts/unified';\nimport { cancelOrder } from './orders/cancelOrder';\nimport { getOrdersByProductId, listSpotOrders, listUnifiedUmOrders } from './orders/listOrders';\nimport { modifyOrder } from './orders/modifyOrder';\nimport { submitOrder } from './orders/submitOrder';\n\nconst terminal = Terminal.fromNodeEnv();\n\nprovideExchangeServices<ICredential>(terminal, {\n name: 'BINANCE',\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: async function (credential: ICredential): Promise<IPosition[]> {\n const [uFuturePositions, spotPositions] = await Promise.all([\n getUnifiedAccountInfo(credential),\n getSpotAccountInfoSnapshot(credential),\n ]);\n return [...uFuturePositions, ...spotPositions];\n },\n getOrders: async function (credential: ICredential): Promise<IOrder[]> {\n const [umOrders, spotOrders] = await Promise.all([\n listUnifiedUmOrders(credential),\n listSpotOrders(credential),\n ]);\n return [...umOrders, ...spotOrders];\n },\n getPositionsByProductId: async function (\n credential: ICredential,\n product_id: string,\n ): Promise<IPosition[]> {\n const [_, instType] = decodePath(product_id); // BINANCE/USDT-FUTURE/ADAUSDT\n if (instType === 'SPOT') {\n const positions = await getSpotAccountInfoSnapshot(credential);\n return positions.filter((position) => position.product_id === product_id);\n }\n if (instType === 'USDT-FUTURE') {\n const positions = await getUnifiedAccountInfo(credential);\n return positions.filter((position) => position.product_id === product_id);\n }\n throw new Error(`Unsupported instType: ${instType}`);\n },\n getOrdersByProductId,\n submitOrder,\n modifyOrder,\n cancelOrder,\n});\n"]}
@@ -1,49 +1,58 @@
1
- import { encodePath, formatTime } from '@yuants/utils';
1
+ import { decodePath, encodePath, formatTime } from '@yuants/utils';
2
2
  import { isApiError } from '../../api/client';
3
3
  import { getSpotOpenOrders, getUnifiedUmOpenOrders } from '../../api/private-api';
4
4
  import { mapBinanceOrderStatus, mapBinanceOrderTypeToYuants, mapBinanceSideToYuantsDirection, mapSpotSideToOrderDirection, } from './order-utils';
5
- export const listOrders = async (credential, account_id) => {
6
- if (account_id.includes('/unified/')) {
7
- const res = await getUnifiedUmOpenOrders(credential);
8
- if (isApiError(res)) {
9
- throw new Error(res.msg);
10
- }
11
- return res.map((order) => {
12
- var _a;
13
- return ({
14
- order_id: `${order.orderId}`,
15
- account_id,
16
- product_id: encodePath('BINANCE', 'USDT-FUTURE', order.symbol),
17
- order_type: mapBinanceOrderTypeToYuants(order.type),
18
- order_direction: (_a = mapBinanceSideToYuantsDirection(order.side, order.positionSide)) !== null && _a !== void 0 ? _a : (order.side === 'BUY' ? 'OPEN_LONG' : 'OPEN_SHORT'),
19
- volume: +order.origQty,
20
- traded_volume: +order.executedQty,
21
- price: order.price === undefined ? undefined : +order.price,
22
- submit_at: order.time,
23
- updated_at: formatTime(order.updateTime),
24
- order_status: mapBinanceOrderStatus(order.status),
25
- });
26
- });
5
+ export const listUnifiedUmOrders = async (credential) => {
6
+ const res = await getUnifiedUmOpenOrders(credential);
7
+ if (isApiError(res)) {
8
+ throw new Error(res.msg);
27
9
  }
28
- if (account_id.includes('/spot/')) {
29
- const res = await getSpotOpenOrders(credential);
30
- if (isApiError(res)) {
31
- throw new Error(res.msg);
32
- }
33
- return res.map((order) => ({
10
+ return res.map((order) => {
11
+ var _a;
12
+ return ({
34
13
  order_id: `${order.orderId}`,
35
- account_id,
36
- product_id: encodePath('BINANCE', 'SPOT', order.symbol),
14
+ account_id: '',
15
+ product_id: encodePath('BINANCE', 'USDT-FUTURE', order.symbol),
37
16
  order_type: mapBinanceOrderTypeToYuants(order.type),
38
- order_direction: mapSpotSideToOrderDirection(order.side),
17
+ order_direction: (_a = mapBinanceSideToYuantsDirection(order.side, order.positionSide)) !== null && _a !== void 0 ? _a : (order.side === 'BUY' ? 'OPEN_LONG' : 'OPEN_SHORT'),
39
18
  volume: +order.origQty,
40
19
  traded_volume: +order.executedQty,
41
- price: order.price ? +order.price : undefined,
20
+ price: order.price === undefined ? undefined : +order.price,
42
21
  submit_at: order.time,
43
22
  updated_at: formatTime(order.updateTime),
44
23
  order_status: mapBinanceOrderStatus(order.status),
45
- }));
24
+ });
25
+ });
26
+ };
27
+ export const listSpotOrders = async (credential) => {
28
+ const res = await getSpotOpenOrders(credential);
29
+ if (isApiError(res)) {
30
+ throw new Error(res.msg);
31
+ }
32
+ return res.map((order) => ({
33
+ order_id: `${order.orderId}`,
34
+ account_id: '',
35
+ product_id: encodePath('BINANCE', 'SPOT', order.symbol),
36
+ order_type: mapBinanceOrderTypeToYuants(order.type),
37
+ order_direction: mapSpotSideToOrderDirection(order.side),
38
+ volume: +order.origQty,
39
+ traded_volume: +order.executedQty,
40
+ price: order.price === undefined ? undefined : +order.price,
41
+ submit_at: order.time,
42
+ updated_at: formatTime(order.updateTime),
43
+ order_status: mapBinanceOrderStatus(order.status),
44
+ }));
45
+ };
46
+ export const getOrdersByProductId = async function (credential, product_id) {
47
+ const [_, instType] = decodePath(product_id); // BINANCE/USDT-FUTURE/ADAUSDT
48
+ if (instType === 'SPOT') {
49
+ const orders = await listSpotOrders(credential);
50
+ return orders.filter((order) => order.product_id === product_id);
51
+ }
52
+ if (instType === 'USDT-FUTURE') {
53
+ const orders = await listUnifiedUmOrders(credential);
54
+ return orders.filter((order) => order.product_id === product_id);
46
55
  }
47
- throw new Error(`Unsupported account_id for listOrders: ${account_id}`);
56
+ throw new Error(`Unsupported instType: ${instType}`);
48
57
  };
49
58
  //# 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 { isApiError } from '../../api/client';\nimport { getSpotOpenOrders, getUnifiedUmOpenOrders, ICredential } from '../../api/private-api';\nimport {\n mapBinanceOrderStatus,\n mapBinanceOrderTypeToYuants,\n mapBinanceSideToYuantsDirection,\n mapSpotSideToOrderDirection,\n} from './order-utils';\n\nexport const listOrders: IActionHandlerOfListOrders<ICredential> = async (credential, account_id) => {\n if (account_id.includes('/unified/')) {\n const res = await getUnifiedUmOpenOrders(credential);\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n return res.map(\n (order): IOrder => ({\n order_id: `${order.orderId}`,\n account_id,\n product_id: encodePath('BINANCE', 'USDT-FUTURE', order.symbol),\n order_type: mapBinanceOrderTypeToYuants(order.type),\n order_direction:\n mapBinanceSideToYuantsDirection(order.side, order.positionSide) ??\n (order.side === 'BUY' ? 'OPEN_LONG' : 'OPEN_SHORT'),\n volume: +order.origQty,\n traded_volume: +order.executedQty,\n price: order.price === undefined ? undefined : +order.price,\n submit_at: order.time,\n updated_at: formatTime(order.updateTime),\n order_status: mapBinanceOrderStatus(order.status),\n }),\n );\n }\n if (account_id.includes('/spot/')) {\n const res = await getSpotOpenOrders(credential);\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n return res.map(\n (order): IOrder => ({\n order_id: `${order.orderId}`,\n account_id,\n product_id: encodePath('BINANCE', 'SPOT', order.symbol),\n order_type: mapBinanceOrderTypeToYuants(order.type),\n order_direction: mapSpotSideToOrderDirection(order.side),\n volume: +order.origQty,\n traded_volume: +order.executedQty,\n price: order.price ? +order.price : undefined,\n submit_at: order.time,\n updated_at: formatTime(order.updateTime),\n order_status: mapBinanceOrderStatus(order.status),\n }),\n );\n }\n throw new Error(`Unsupported account_id for listOrders: ${account_id}`);\n};\n"]}
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 { decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { isApiError } from '../../api/client';\nimport { getSpotOpenOrders, getUnifiedUmOpenOrders, ICredential } from '../../api/private-api';\nimport {\n mapBinanceOrderStatus,\n mapBinanceOrderTypeToYuants,\n mapBinanceSideToYuantsDirection,\n mapSpotSideToOrderDirection,\n} from './order-utils';\n\nexport const listUnifiedUmOrders = async (credential: ICredential): Promise<IOrder[]> => {\n const res = await getUnifiedUmOpenOrders(credential);\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n return res.map(\n (order): IOrder => ({\n order_id: `${order.orderId}`,\n account_id: '',\n product_id: encodePath('BINANCE', 'USDT-FUTURE', order.symbol),\n order_type: mapBinanceOrderTypeToYuants(order.type),\n order_direction:\n mapBinanceSideToYuantsDirection(order.side, order.positionSide) ??\n (order.side === 'BUY' ? 'OPEN_LONG' : 'OPEN_SHORT'),\n volume: +order.origQty,\n traded_volume: +order.executedQty,\n price: order.price === undefined ? undefined : +order.price,\n submit_at: order.time,\n updated_at: formatTime(order.updateTime),\n order_status: mapBinanceOrderStatus(order.status),\n }),\n );\n};\n\nexport const listSpotOrders = async (credential: ICredential): Promise<IOrder[]> => {\n const res = await getSpotOpenOrders(credential);\n if (isApiError(res)) {\n throw new Error(res.msg);\n }\n return res.map(\n (order): IOrder => ({\n order_id: `${order.orderId}`,\n account_id: '',\n product_id: encodePath('BINANCE', 'SPOT', order.symbol),\n order_type: mapBinanceOrderTypeToYuants(order.type),\n order_direction: mapSpotSideToOrderDirection(order.side),\n volume: +order.origQty,\n traded_volume: +order.executedQty,\n price: order.price === undefined ? undefined : +order.price,\n submit_at: order.time,\n updated_at: formatTime(order.updateTime),\n order_status: mapBinanceOrderStatus(order.status),\n }),\n );\n};\n\nexport const getOrdersByProductId = async function (\n credential: ICredential,\n product_id: string,\n): Promise<IOrder[]> {\n const [_, instType] = decodePath(product_id); // BINANCE/USDT-FUTURE/ADAUSDT\n if (instType === 'SPOT') {\n const orders = await listSpotOrders(credential);\n return orders.filter((order) => order.product_id === product_id);\n }\n if (instType === 'USDT-FUTURE') {\n const orders = await listUnifiedUmOrders(credential);\n return orders.filter((order) => order.product_id === product_id);\n }\n throw new Error(`Unsupported instType: ${instType}`);\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAKA,aAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,aAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,UAAU,iDAC0E,CAAC;AA+ElG,eAAO,MAAM,aAAa,cAAe,UAAU,YAAY,MAAM,WAAW,aAAa,eACvD,CAAC;AAEvC,eAAO,MAAM,cAAc,kBACb,WAAW,UACf,UAAU,YACR,MAAM,WACP,aAAa,eAC6B,CAAC;AAEtD,eAAO,MAAM,oBAAoB,QAAO,WAOvC,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAKA,aAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,aAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAE3E,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAID,eAAO,MAAM,UAAU,iDAC0E,CAAC;AA2FlG,eAAO,MAAM,aAAa,cAAe,UAAU,YAAY,MAAM,WAAW,aAAa,eACvD,CAAC;AAEvC,eAAO,MAAM,cAAc,kBACb,WAAW,UACf,UAAU,YACR,MAAM,WACP,aAAa,eAC6B,CAAC;AAEtD,eAAO,MAAM,oBAAoB,QAAO,WAOvC,CAAC"}
package/lib/api/client.js CHANGED
@@ -4,6 +4,7 @@ exports.getDefaultCredential = exports.requestPrivate = exports.requestPublic =
4
4
  const protocol_1 = require("@yuants/protocol");
5
5
  const utils_1 = require("@yuants/utils");
6
6
  const MetricBinanceApiUsedWeight = protocol_1.GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');
7
+ let retryAfterUntil = null;
7
8
  const isApiError = (value) => typeof (value === null || value === void 0 ? void 0 : value.code) === 'number' && typeof (value === null || value === void 0 ? void 0 : value.msg) === 'string';
8
9
  exports.isApiError = isApiError;
9
10
  const appendParams = (url, params) => {
@@ -48,12 +49,22 @@ const callApi = async (method, endpoint, params, credential) => {
48
49
  else {
49
50
  console.info((0, utils_1.formatTime)(Date.now()), method, url.href);
50
51
  }
52
+ if (retryAfterUntil) {
53
+ if (Date.now() <= retryAfterUntil) {
54
+ throw (0, utils_1.newError)('ACTIVE_RATE_LIMIT', { retryAfterUntil, now: Date.now(), url: url.href });
55
+ }
56
+ retryAfterUntil = null;
57
+ }
51
58
  const res = await fetch(url.href, {
52
59
  method,
53
60
  headers,
54
61
  });
55
62
  const usedWeight1M = res.headers.get('x-mbx-used-weight-1m');
56
- console.info((0, utils_1.formatTime)(Date.now()), 'response', method, url.href, res.status, `usedWeight1M=${usedWeight1M !== null && usedWeight1M !== void 0 ? usedWeight1M : 'N/A'}`);
63
+ const retryAfter = res.headers.get('Retry-After');
64
+ if (retryAfter) {
65
+ retryAfterUntil = Date.now() + parseInt(retryAfter, 10) * 1000;
66
+ }
67
+ console.info((0, utils_1.formatTime)(Date.now()), 'response', method, url.href, `status=${res.status}`, retryAfter ? `retryAfter=${retryAfter}` : '', `usedWeight1M=${usedWeight1M !== null && usedWeight1M !== void 0 ? usedWeight1M : 'N/A'}`);
57
68
  if (usedWeight1M) {
58
69
  MetricBinanceApiUsedWeight.set(+usedWeight1M);
59
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { GlobalPrometheusRegistry } from '@yuants/protocol';\nimport { formatTime, HmacSHA256 } from '@yuants/utils';\n\nconst MetricBinanceApiUsedWeight = GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');\n\ntype HttpMethod = 'GET' | 'POST' | 'DELETE' | 'PUT';\n\ntype RequestParams = Record<string, string | number | boolean | undefined>;\n\nexport interface ICredential {\n access_key: string;\n secret_key: string;\n}\n\nexport interface IApiError {\n code: number;\n msg: string;\n}\n\nexport const isApiError = <T>(value: T | IApiError): value is IApiError =>\n typeof (value as IApiError)?.code === 'number' && typeof (value as IApiError)?.msg === 'string';\n\nconst appendParams = (url: URL, params?: RequestParams) => {\n if (!params) return;\n const entries = Object.entries(params).filter(([, value]) => value !== undefined);\n const timestampEntry = entries.find(([key]) => key === 'timestamp');\n const restEntries = entries.filter(([key]) => key !== 'timestamp');\n restEntries\n .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))\n .forEach(([key, value]) => {\n url.searchParams.set(key, String(value));\n });\n if (timestampEntry) {\n url.searchParams.set(timestampEntry[0], String(timestampEntry[1]));\n }\n};\n\nconst callApi = async <T>(\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n credential?: ICredential,\n): Promise<T> => {\n const url = new URL(endpoint);\n const normalizedParams: RequestParams = { ...params };\n if (credential) {\n if (normalizedParams.recvWindow === undefined) {\n // FYI https://developers.binance.com/docs/derivatives/usds-margined-futures/general-info#timing-security\n normalizedParams.recvWindow = 5000;\n }\n if (normalizedParams.timestamp === undefined) {\n normalizedParams.timestamp = Date.now();\n }\n }\n appendParams(url, normalizedParams);\n\n let headers: Record<string, string> | undefined;\n if (credential) {\n const signData = url.search.slice(1);\n\n const signature = Buffer.from(\n await HmacSHA256(new TextEncoder().encode(signData), new TextEncoder().encode(credential.secret_key)),\n ).toString('hex');\n url.searchParams.set('signature', signature);\n headers = {\n 'Content-Type': 'application/json;charset=utf-8',\n 'X-MBX-APIKEY': credential.access_key,\n };\n console.info(\n formatTime(Date.now()),\n method,\n url.href,\n JSON.stringify(headers),\n url.searchParams.toString(),\n signData,\n );\n } else {\n console.info(formatTime(Date.now()), method, url.href);\n }\n\n const res = await fetch(url.href, {\n method,\n headers,\n });\n const usedWeight1M = res.headers.get('x-mbx-used-weight-1m');\n console.info(\n formatTime(Date.now()),\n 'response',\n method,\n url.href,\n res.status,\n `usedWeight1M=${usedWeight1M ?? 'N/A'}`,\n );\n if (usedWeight1M) {\n MetricBinanceApiUsedWeight.set(+usedWeight1M);\n }\n return res.json() as Promise<T>;\n};\n\nexport const requestPublic = <T>(method: HttpMethod, endpoint: string, params?: RequestParams) =>\n callApi<T>(method, endpoint, params);\n\nexport const requestPrivate = <T>(\n credential: ICredential,\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n) => callApi<T>(method, endpoint, params, credential);\n\nexport const getDefaultCredential = (): ICredential => {\n const access_key = process.env.ACCESS_KEY;\n const secret_key = process.env.SECRET_KEY;\n if (!access_key || !secret_key) {\n throw new Error('Missing Binance credential: ACCESS_KEY and SECRET_KEY must be set');\n }\n return { access_key, secret_key };\n};\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { GlobalPrometheusRegistry } from '@yuants/protocol';\nimport { formatTime, HmacSHA256, newError } from '@yuants/utils';\n\nconst MetricBinanceApiUsedWeight = GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');\n\ntype HttpMethod = 'GET' | 'POST' | 'DELETE' | 'PUT';\n\ntype RequestParams = Record<string, string | number | boolean | undefined>;\n\nexport interface ICredential {\n access_key: string;\n secret_key: string;\n}\n\nexport interface IApiError {\n code: number;\n msg: string;\n}\n\nlet retryAfterUntil: number | null = null;\n\nexport const isApiError = <T>(value: T | IApiError): value is IApiError =>\n typeof (value as IApiError)?.code === 'number' && typeof (value as IApiError)?.msg === 'string';\n\nconst appendParams = (url: URL, params?: RequestParams) => {\n if (!params) return;\n const entries = Object.entries(params).filter(([, value]) => value !== undefined);\n const timestampEntry = entries.find(([key]) => key === 'timestamp');\n const restEntries = entries.filter(([key]) => key !== 'timestamp');\n restEntries\n .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))\n .forEach(([key, value]) => {\n url.searchParams.set(key, String(value));\n });\n if (timestampEntry) {\n url.searchParams.set(timestampEntry[0], String(timestampEntry[1]));\n }\n};\n\nconst callApi = async <T>(\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n credential?: ICredential,\n): Promise<T> => {\n const url = new URL(endpoint);\n const normalizedParams: RequestParams = { ...params };\n if (credential) {\n if (normalizedParams.recvWindow === undefined) {\n // FYI https://developers.binance.com/docs/derivatives/usds-margined-futures/general-info#timing-security\n normalizedParams.recvWindow = 5000;\n }\n if (normalizedParams.timestamp === undefined) {\n normalizedParams.timestamp = Date.now();\n }\n }\n appendParams(url, normalizedParams);\n\n let headers: Record<string, string> | undefined;\n if (credential) {\n const signData = url.search.slice(1);\n\n const signature = Buffer.from(\n await HmacSHA256(new TextEncoder().encode(signData), new TextEncoder().encode(credential.secret_key)),\n ).toString('hex');\n url.searchParams.set('signature', signature);\n headers = {\n 'Content-Type': 'application/json;charset=utf-8',\n 'X-MBX-APIKEY': credential.access_key,\n };\n console.info(\n formatTime(Date.now()),\n method,\n url.href,\n JSON.stringify(headers),\n url.searchParams.toString(),\n signData,\n );\n } else {\n console.info(formatTime(Date.now()), method, url.href);\n }\n\n if (retryAfterUntil) {\n if (Date.now() <= retryAfterUntil) {\n throw newError('ACTIVE_RATE_LIMIT', { retryAfterUntil, now: Date.now(), url: url.href });\n }\n retryAfterUntil = null;\n }\n\n const res = await fetch(url.href, {\n method,\n headers,\n });\n const usedWeight1M = res.headers.get('x-mbx-used-weight-1m');\n const retryAfter = res.headers.get('Retry-After');\n if (retryAfter) {\n retryAfterUntil = Date.now() + parseInt(retryAfter, 10) * 1000;\n }\n console.info(\n formatTime(Date.now()),\n 'response',\n method,\n url.href,\n `status=${res.status}`,\n retryAfter ? `retryAfter=${retryAfter}` : '',\n `usedWeight1M=${usedWeight1M ?? 'N/A'}`,\n );\n if (usedWeight1M) {\n MetricBinanceApiUsedWeight.set(+usedWeight1M);\n }\n return res.json() as Promise<T>;\n};\n\nexport const requestPublic = <T>(method: HttpMethod, endpoint: string, params?: RequestParams) =>\n callApi<T>(method, endpoint, params);\n\nexport const requestPrivate = <T>(\n credential: ICredential,\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n) => callApi<T>(method, endpoint, params, credential);\n\nexport const getDefaultCredential = (): ICredential => {\n const access_key = process.env.ACCESS_KEY;\n const secret_key = process.env.SECRET_KEY;\n if (!access_key || !secret_key) {\n throw new Error('Missing Binance credential: ACCESS_KEY and SECRET_KEY must be set');\n }\n return { access_key, secret_key };\n};\n"]}