@drift-labs/sdk 0.2.0-master.12 → 0.2.0-master.15

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 (117) hide show
  1. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  2. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  3. package/lib/accounts/bulkUserSubscription.js +0 -1
  4. package/lib/accounts/fetch.d.ts +2 -1
  5. package/lib/accounts/fetch.js +9 -1
  6. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  7. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  8. package/lib/accounts/types.d.ts +14 -2
  9. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  10. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  11. package/lib/addresses/pda.d.ts +1 -0
  12. package/lib/addresses/pda.js +8 -1
  13. package/lib/admin.d.ts +2 -0
  14. package/lib/admin.js +18 -0
  15. package/lib/clearingHouse.d.ts +17 -1
  16. package/lib/clearingHouse.js +195 -14
  17. package/lib/clearingHouseConfig.d.ts +1 -0
  18. package/lib/clearingHouseUser.d.ts +5 -0
  19. package/lib/clearingHouseUser.js +97 -3
  20. package/lib/clearingHouseUserStats.d.ts +17 -0
  21. package/lib/clearingHouseUserStats.js +36 -0
  22. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  23. package/{src/clearingHouseConfig.js → lib/clearingHouseUserStatsConfig.js} +0 -0
  24. package/lib/config.js +1 -1
  25. package/lib/factory/bigNum.js +7 -9
  26. package/lib/idl/clearing_house.json +620 -64
  27. package/lib/math/amm.js +2 -2
  28. package/lib/math/bankBalance.d.ts +4 -0
  29. package/lib/math/bankBalance.js +24 -2
  30. package/lib/math/oracles.d.ts +3 -0
  31. package/lib/math/oracles.js +25 -5
  32. package/lib/math/position.js +2 -1
  33. package/lib/math/trade.js +2 -2
  34. package/lib/types.d.ts +57 -9
  35. package/lib/types.js +6 -0
  36. package/package.json +1 -1
  37. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  38. package/src/accounts/bulkUserSubscription.ts +0 -1
  39. package/src/accounts/fetch.ts +27 -2
  40. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  41. package/src/accounts/types.ts +18 -0
  42. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  43. package/src/addresses/pda.ts +13 -0
  44. package/src/admin.ts +29 -1
  45. package/src/clearingHouse.ts +318 -15
  46. package/src/clearingHouseConfig.ts +1 -0
  47. package/src/clearingHouseUser.ts +113 -10
  48. package/src/clearingHouseUserStats.ts +53 -0
  49. package/src/clearingHouseUserStatsConfig.ts +18 -0
  50. package/src/config.ts +1 -1
  51. package/src/factory/bigNum.ts +6 -7
  52. package/src/idl/clearing_house.json +620 -64
  53. package/src/math/amm.ts +8 -5
  54. package/src/math/bankBalance.ts +50 -1
  55. package/src/math/oracles.ts +42 -5
  56. package/src/math/position.ts +2 -1
  57. package/src/math/trade.ts +2 -2
  58. package/src/types.ts +61 -9
  59. package/tests/bn/test.ts +8 -0
  60. package/src/accounts/bulkAccountLoader.js +0 -197
  61. package/src/accounts/bulkUserSubscription.js +0 -33
  62. package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
  63. package/src/accounts/pollingOracleSubscriber.js +0 -93
  64. package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
  65. package/src/accounts/pollingUserAccountSubscriber.js +0 -132
  66. package/src/accounts/types.js +0 -10
  67. package/src/accounts/utils.js +0 -7
  68. package/src/accounts/webSocketAccountSubscriber.js +0 -93
  69. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
  70. package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
  71. package/src/addresses/marketAddresses.js +0 -26
  72. package/src/assert/assert.js +0 -9
  73. package/src/clearingHouseUserConfig.js +0 -2
  74. package/src/constants/banks.js +0 -42
  75. package/src/constants/markets.js +0 -42
  76. package/src/constants/numericConstants.js +0 -41
  77. package/src/events/eventList.js +0 -77
  78. package/src/events/eventSubscriber.js +0 -139
  79. package/src/events/fetchLogs.js +0 -50
  80. package/src/events/pollingLogProvider.js +0 -64
  81. package/src/events/sort.js +0 -44
  82. package/src/events/txEventCache.js +0 -71
  83. package/src/events/types.js +0 -20
  84. package/src/events/webSocketLogProvider.js +0 -41
  85. package/src/examples/makeTradeExample.js +0 -80
  86. package/src/factory/bigNum.js +0 -390
  87. package/src/factory/oracleClient.js +0 -20
  88. package/src/index.js +0 -69
  89. package/src/math/amm.js +0 -369
  90. package/src/math/auction.js +0 -42
  91. package/src/math/conversion.js +0 -11
  92. package/src/math/funding.js +0 -248
  93. package/src/math/oracles.js +0 -26
  94. package/src/math/repeg.js +0 -128
  95. package/src/math/state.js +0 -15
  96. package/src/math/trade.js +0 -253
  97. package/src/math/utils.js +0 -26
  98. package/src/math/utils.js.map +0 -1
  99. package/src/mockUSDCFaucet.js +0 -280
  100. package/src/oracles/oracleClientCache.js +0 -19
  101. package/src/oracles/pythClient.js +0 -46
  102. package/src/oracles/quoteAssetOracleClient.js +0 -32
  103. package/src/oracles/switchboardClient.js +0 -69
  104. package/src/oracles/types.js +0 -2
  105. package/src/orderParams.js +0 -20
  106. package/src/slot/SlotSubscriber.js +0 -39
  107. package/src/token/index.js +0 -38
  108. package/src/tokenFaucet.js +0 -189
  109. package/src/tx/types.js +0 -2
  110. package/src/tx/utils.js +0 -17
  111. package/src/types.js +0 -125
  112. package/src/userName.js +0 -20
  113. package/src/util/computeUnits.js +0 -27
  114. package/src/util/getTokenAddress.js +0 -9
  115. package/src/util/promiseTimeout.js +0 -14
  116. package/src/util/tps.js +0 -27
  117. package/src/wallet.js +0 -35
package/src/math/amm.ts CHANGED
@@ -33,11 +33,14 @@ export function calculatePegFromTargetPrice(
33
33
  baseAssetReserve: BN,
34
34
  quoteAssetReserve: BN
35
35
  ): BN {
36
- return targetPrice
37
- .mul(baseAssetReserve)
38
- .div(quoteAssetReserve)
39
- .add(PRICE_DIV_PEG.div(new BN(2)))
40
- .div(PRICE_DIV_PEG);
36
+ return BN.max(
37
+ targetPrice
38
+ .mul(baseAssetReserve)
39
+ .div(quoteAssetReserve)
40
+ .add(PRICE_DIV_PEG.div(new BN(2)))
41
+ .div(PRICE_DIV_PEG),
42
+ ONE
43
+ );
41
44
  }
42
45
 
43
46
  export function calculateOptimalPegAndBudget(
@@ -187,7 +187,7 @@ export function calculateInterestAccumulated(
187
187
  .div(BANK_UTILIZATION_PRECISION);
188
188
  }
189
189
 
190
- const timeSinceLastUpdate = now.sub(bank.lastUpdated);
190
+ const timeSinceLastUpdate = now.sub(bank.lastInterestTs);
191
191
 
192
192
  const modifiedBorrowRate = interest_rate.mul(timeSinceLastUpdate);
193
193
 
@@ -207,3 +207,52 @@ export function calculateInterestAccumulated(
207
207
 
208
208
  return { borrowInterest, depositInterest };
209
209
  }
210
+
211
+ export function calculateWithdrawLimit(
212
+ bank: BankAccount,
213
+ now: BN
214
+ ): { borrowLimit: BN; withdrawLimit: BN } {
215
+ const bankDepositTokenAmount = getTokenAmount(
216
+ bank.depositBalance,
217
+ bank,
218
+ BankBalanceType.DEPOSIT
219
+ );
220
+ const bankBorrowTokenAmount = getTokenAmount(
221
+ bank.borrowBalance,
222
+ bank,
223
+ BankBalanceType.BORROW
224
+ );
225
+
226
+ const twentyFourHours = new BN(60 * 60 * 24);
227
+ const sinceLast = now.sub(bank.lastTwapTs);
228
+ const sinceStart = BN.max(ZERO, twentyFourHours.sub(sinceLast));
229
+ const borrowTokenTwapLive = bank.borrowTokenTwap
230
+ .mul(sinceStart)
231
+ .add(bankBorrowTokenAmount.mul(sinceLast))
232
+ .div(sinceLast.add(sinceLast));
233
+
234
+ const depositTokenTwapLive = bank.depositTokenTwap
235
+ .mul(sinceStart)
236
+ .add(bankDepositTokenAmount.mul(sinceLast))
237
+ .div(sinceLast.add(sinceLast));
238
+
239
+ const maxBorrowTokens = BN.min(
240
+ BN.max(
241
+ bankDepositTokenAmount.div(new BN(6)),
242
+ borrowTokenTwapLive.add(borrowTokenTwapLive.div(new BN(5)))
243
+ ),
244
+ bankDepositTokenAmount.sub(bankDepositTokenAmount.div(new BN(10)))
245
+ ); // between ~15-90% utilization with friction on twap
246
+
247
+ const minDepositTokens = depositTokenTwapLive.sub(
248
+ BN.min(
249
+ BN.max(depositTokenTwapLive.div(new BN(5)), bank.withdrawGuardThreshold),
250
+ depositTokenTwapLive
251
+ )
252
+ );
253
+
254
+ return {
255
+ borrowLimit: maxBorrowTokens.sub(bankBorrowTokenAmount),
256
+ withdrawLimit: bankDepositTokenAmount.sub(minDepositTokens),
257
+ };
258
+ }
@@ -1,6 +1,11 @@
1
1
  import { AMM, OracleGuardRails } from '../types';
2
2
  import { OraclePriceData } from '../oracles/types';
3
- import { ONE, ZERO } from '../constants/numericConstants';
3
+ import {
4
+ BID_ASK_SPREAD_PRECISION,
5
+ MARK_PRICE_PRECISION,
6
+ ONE,
7
+ ZERO,
8
+ } from '../constants/numericConstants';
4
9
  import { BN } from '../index';
5
10
 
6
11
  export function isOracleValid(
@@ -9,7 +14,7 @@ export function isOracleValid(
9
14
  oracleGuardRails: OracleGuardRails,
10
15
  slot: number
11
16
  ): boolean {
12
- const isOraclePriceNonPositive = oraclePriceData.price.lt(ZERO);
17
+ const isOraclePriceNonPositive = oraclePriceData.price.lte(ZERO);
13
18
  const isOraclePriceTooVolatile =
14
19
  oraclePriceData.price
15
20
  .div(BN.max(ONE, amm.lastOraclePriceTwap))
@@ -18,9 +23,11 @@ export function isOracleValid(
18
23
  .div(BN.max(ONE, oraclePriceData.price))
19
24
  .gt(oracleGuardRails.validity.tooVolatileRatio);
20
25
 
21
- const isConfidenceTooLarge = oraclePriceData.price
22
- .div(BN.max(ONE, oraclePriceData.confidence))
23
- .lt(oracleGuardRails.validity.confidenceIntervalMaxSize);
26
+ const isConfidenceTooLarge = new BN(amm.baseSpread)
27
+ .add(BN.max(ONE, oraclePriceData.confidence))
28
+ .mul(BID_ASK_SPREAD_PRECISION)
29
+ .div(oraclePriceData.price)
30
+ .gt(new BN(amm.maxSpread));
24
31
 
25
32
  const oracleIsStale = oraclePriceData.slot
26
33
  .sub(new BN(slot))
@@ -34,3 +41,33 @@ export function isOracleValid(
34
41
  isConfidenceTooLarge
35
42
  );
36
43
  }
44
+
45
+ export function isOracleTooDivergent(
46
+ amm: AMM,
47
+ oraclePriceData: OraclePriceData,
48
+ oracleGuardRails: OracleGuardRails,
49
+ now: BN
50
+ ): boolean {
51
+ const sinceLastUpdate = now.sub(amm.lastOraclePriceTwapTs);
52
+ const sinceStart = BN.max(ZERO, new BN(60 * 5).sub(sinceLastUpdate));
53
+ const oracleTwap5min = amm.lastOraclePriceTwap5min
54
+ .mul(sinceStart)
55
+ .add(oraclePriceData.price)
56
+ .mul(sinceLastUpdate)
57
+ .div(sinceStart.add(sinceLastUpdate));
58
+
59
+ const oracleSpread = oracleTwap5min.sub(oraclePriceData.price);
60
+ const oracleSpreadPct = oracleSpread
61
+ .mul(MARK_PRICE_PRECISION)
62
+ .div(oracleTwap5min);
63
+
64
+ const tooDivergent = oracleSpreadPct
65
+ .abs()
66
+ .gte(
67
+ BID_ASK_SPREAD_PRECISION.mul(
68
+ oracleGuardRails.priceDivergence.markOracleDivergenceNumerator
69
+ ).div(oracleGuardRails.priceDivergence.markOracleDivergenceDenominator)
70
+ );
71
+
72
+ return tooDivergent;
73
+ }
@@ -189,7 +189,8 @@ export function positionIsAvailable(position: UserPosition): boolean {
189
189
  return (
190
190
  position.baseAssetAmount.eq(ZERO) &&
191
191
  position.openOrders.eq(ZERO) &&
192
- position.quoteAssetAmount.eq(ZERO)
192
+ position.quoteAssetAmount.eq(ZERO) &&
193
+ position.lpShares.eq(ZERO)
193
194
  );
194
195
  }
195
196
 
package/src/math/trade.ts CHANGED
@@ -177,13 +177,13 @@ export function calculateTradeAcquiredAmounts(
177
177
 
178
178
  const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
179
179
  const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
180
- const acquiredQuoteAssetamount = calculateQuoteAssetAmountSwapped(
180
+ const acquiredQuoteAssetAmount = calculateQuoteAssetAmountSwapped(
181
181
  acquiredQuote.abs(),
182
182
  amm.pegMultiplier,
183
183
  swapDirection
184
184
  );
185
185
 
186
- return [acquiredBase, acquiredQuote, acquiredQuoteAssetamount];
186
+ return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
187
187
  }
188
188
 
189
189
  /**
package/src/types.ts CHANGED
@@ -177,6 +177,8 @@ export type LiquidationRecord = {
177
177
  liquidateBorrow: LiquidateBorrowRecord;
178
178
  liquidateBorrowForPerpPnl: LiquidateBorrowForPerpPnlRecord;
179
179
  liquidatePerpPnlForDeposit: LiquidatePerpPnlForDepositRecord;
180
+ perpBankruptcy: PerpBankruptcyRecord;
181
+ borrowBankruptcy: BorrowBankruptcyRecord;
180
182
  };
181
183
 
182
184
  export class LiquidationType {
@@ -188,6 +190,12 @@ export class LiquidationType {
188
190
  static readonly LIQUIDATE_PERP_PNL_FOR_DEPOSIT = {
189
191
  liquidatePerpPnlForDeposit: {},
190
192
  };
193
+ static readonly PERP_BANKRUPTCY = {
194
+ perpBankruptcy: {},
195
+ };
196
+ static readonly BORROW_BANKRUPTCY = {
197
+ borrowBankruptcy: {},
198
+ };
191
199
  }
192
200
 
193
201
  export type LiquidatePerpRecord = {
@@ -231,14 +239,27 @@ export type LiquidatePerpPnlForDepositRecord = {
231
239
  assetTransfer: BN;
232
240
  };
233
241
 
242
+ export type PerpBankruptcyRecord = {
243
+ marketIndex: BN;
244
+ pnl: BN;
245
+ cumulativeFundingRateDelta: BN;
246
+ };
247
+
248
+ export type BorrowBankruptcyRecord = {
249
+ bankIndex: BN;
250
+ borrowAmount: BN;
251
+ cumulativeDepositInterestDelta: BN;
252
+ };
253
+
234
254
  export type SettlePnlRecord = {
235
255
  ts: BN;
256
+ user: PublicKey;
236
257
  marketIndex: BN;
237
258
  pnl: BN;
238
259
  baseAssetAmount: BN;
239
260
  quoteAssetAmountAfter: BN;
240
261
  quoteEntryamount: BN;
241
- oraclePrice: BN;
262
+ settlePrice: BN;
242
263
  };
243
264
 
244
265
  export type OrderRecord = {
@@ -329,7 +350,8 @@ export type BankAccount = {
329
350
  cumulativeBorrowInterest: BN;
330
351
  depositBalance: BN;
331
352
  borrowBalance: BN;
332
- lastUpdated: BN;
353
+ lastInterestTs: BN;
354
+ lastTwapTs: BN;
333
355
  oracle: PublicKey;
334
356
  initialAssetWeight: BN;
335
357
  maintenanceAssetWeight: BN;
@@ -337,6 +359,11 @@ export type BankAccount = {
337
359
  maintenanceLiabilityWeight: BN;
338
360
  liquidationFee: BN;
339
361
  imfFactor: BN;
362
+
363
+ withdrawGuardThreshold: BN;
364
+ depositTokenTwap: BN;
365
+ borrowTokenTwap: BN;
366
+ utilizationTwap: BN;
340
367
  };
341
368
 
342
369
  export type PoolBalance = {
@@ -350,8 +377,10 @@ export type AMM = {
350
377
  lastFundingRate: BN;
351
378
  lastFundingRateTs: BN;
352
379
  lastMarkPriceTwap: BN;
380
+ lastMarkPriceTwap5min: BN;
353
381
  lastMarkPriceTwapTs: BN;
354
382
  lastOraclePriceTwap: BN;
383
+ lastOraclePriceTwap5min: BN;
355
384
  lastOraclePriceTwapTs: BN;
356
385
  lastOracleMarkSpreadPct: BN;
357
386
  lastOracleConfPct: BN;
@@ -362,11 +391,16 @@ export type AMM = {
362
391
  pegMultiplier: BN;
363
392
  cumulativeFundingRateLong: BN;
364
393
  cumulativeFundingRateShort: BN;
394
+ cumulativeFundingRateLp: BN;
365
395
  cumulativeRepegRebateLong: BN;
366
396
  cumulativeRepegRebateShort: BN;
367
397
  totalFeeMinusDistributions: BN;
368
398
  totalFeeWithdrawn: BN;
369
399
  totalFee: BN;
400
+ cumulativeFundingPaymentPerLp: BN;
401
+ cumulativeFeePerLp: BN;
402
+ cumulativeNetBaseAssetAmountPerLp: BN;
403
+ userLpShares: BN;
370
404
  minimumQuoteAssetTradeSize: BN;
371
405
  baseAssetAmountStepSize: BN;
372
406
  maxBaseAssetAmountRatio: number;
@@ -388,6 +422,8 @@ export type AMM = {
388
422
  longSpread: BN;
389
423
  shortSpread: BN;
390
424
  maxSpread: number;
425
+ marketPosition: UserPosition;
426
+ marketPositionPerLp: UserPosition;
391
427
  };
392
428
 
393
429
  // # User Account Types
@@ -400,15 +436,21 @@ export type UserPosition = {
400
436
  openOrders: BN;
401
437
  openBids: BN;
402
438
  openAsks: BN;
439
+ realizedPnl: BN;
440
+ lpShares: BN;
441
+ lastFeePerLp: BN;
442
+ lastNetBaseAssetAmountPerLp: BN;
443
+ lastNetQuoteAssetAmountPerLp: BN;
403
444
  };
404
445
 
405
- export type UserAccount = {
406
- authority: PublicKey;
407
- name: number[];
408
- userId: number;
409
- bankBalances: UserBankBalance[];
410
- collateral: BN;
411
- cumulativeDeposits: BN;
446
+ export type UserStatsAccount = {
447
+ numberOfUsers: number;
448
+ makerVolume30D: BN;
449
+ takerVolume30D: BN;
450
+ fillerVolume30D: BN;
451
+ lastMakerVolume30DTs: BN;
452
+ lastTakerVolume30DTs: BN;
453
+ lastFillerVolume30DTs: BN;
412
454
  fees: {
413
455
  totalFeePaid: BN;
414
456
  totalFeeRebate: BN;
@@ -416,9 +458,17 @@ export type UserAccount = {
416
458
  totalReferralReward: BN;
417
459
  totalRefereeDiscount: BN;
418
460
  };
461
+ };
462
+
463
+ export type UserAccount = {
464
+ authority: PublicKey;
465
+ name: number[];
466
+ userId: number;
467
+ bankBalances: UserBankBalance[];
419
468
  positions: UserPosition[];
420
469
  orders: Order[];
421
470
  beingLiquidated: boolean;
471
+ bankrupt: boolean;
422
472
  nextLiquidationId: number;
423
473
  };
424
474
 
@@ -515,11 +565,13 @@ export const DefaultOrderParams = {
515
565
 
516
566
  export type MakerInfo = {
517
567
  maker: PublicKey;
568
+ makerStats: PublicKey;
518
569
  order: Order;
519
570
  };
520
571
 
521
572
  export type TakerInfo = {
522
573
  taker: PublicKey;
574
+ takerStats: PublicKey;
523
575
  order: Order;
524
576
  };
525
577
 
package/tests/bn/test.ts CHANGED
@@ -127,6 +127,14 @@ describe('BigNum Tests', () => {
127
127
  expect(BigNum.fromPrint('123456789').toMillified(5)).to.equal('123.45M');
128
128
 
129
129
  expect(BigNum.from(-95, 2).print()).to.equal('-0.95');
130
+
131
+ // Case 6 strange numbers
132
+ expect(BigNum.from('-100', 2).print()).to.equal('-1.00');
133
+ expect(BigNum.from('-8402189', 13).print()).to.equal('-0.0000008402189');
134
+ expect(BigNum.from('-10000000000000', 13).print()).to.equal(
135
+ '-1.0000000000000'
136
+ );
137
+ expect(BigNum.from('-100', 6).print()).to.equal('-0.000100');
130
138
  });
131
139
 
132
140
  it('can initialise from string values correctly', () => {
@@ -1,197 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.BulkAccountLoader = void 0;
13
- const uuid_1 = require("uuid");
14
- const promiseTimeout_1 = require("../util/promiseTimeout");
15
- const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
16
- const oneMinute = 60 * 1000;
17
- class BulkAccountLoader {
18
- constructor(connection, commitment, pollingFrequency) {
19
- this.accountsToLoad = new Map();
20
- this.bufferAndSlotMap = new Map();
21
- this.errorCallbacks = new Map();
22
- this.lastTimeLoadingPromiseCleared = Date.now();
23
- this.mostRecentSlot = 0;
24
- this.connection = connection;
25
- this.commitment = commitment;
26
- this.pollingFrequency = pollingFrequency;
27
- }
28
- addAccount(publicKey, callback) {
29
- const existingSize = this.accountsToLoad.size;
30
- const callbackId = uuid_1.v4();
31
- const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
32
- if (existingAccountToLoad) {
33
- existingAccountToLoad.callbacks.set(callbackId, callback);
34
- }
35
- else {
36
- const callbacks = new Map();
37
- callbacks.set(callbackId, callback);
38
- const newAccountToLoad = {
39
- publicKey,
40
- callbacks,
41
- };
42
- this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
43
- }
44
- if (existingSize === 0) {
45
- this.startPolling();
46
- }
47
- // if a new account needs to be polled, remove the cached loadPromise in case client calls load immediately after
48
- this.loadPromise = undefined;
49
- return callbackId;
50
- }
51
- removeAccount(publicKey, callbackId) {
52
- const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
53
- if (existingAccountToLoad) {
54
- existingAccountToLoad.callbacks.delete(callbackId);
55
- if (existingAccountToLoad.callbacks.size === 0) {
56
- this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
57
- }
58
- }
59
- if (this.accountsToLoad.size === 0) {
60
- this.stopPolling();
61
- }
62
- }
63
- addErrorCallbacks(callback) {
64
- const callbackId = uuid_1.v4();
65
- this.errorCallbacks.set(callbackId, callback);
66
- return callbackId;
67
- }
68
- removeErrorCallbacks(callbackId) {
69
- this.errorCallbacks.delete(callbackId);
70
- }
71
- chunks(array, size) {
72
- return new Array(Math.ceil(array.length / size))
73
- .fill(null)
74
- .map((_, index) => index * size)
75
- .map((begin) => array.slice(begin, begin + size));
76
- }
77
- load() {
78
- return __awaiter(this, void 0, void 0, function* () {
79
- if (this.loadPromise) {
80
- const now = Date.now();
81
- if (now - this.lastTimeLoadingPromiseCleared > oneMinute) {
82
- this.loadPromise = undefined;
83
- }
84
- else {
85
- return this.loadPromise;
86
- }
87
- }
88
- this.loadPromise = new Promise((resolver) => {
89
- this.loadPromiseResolver = resolver;
90
- });
91
- this.lastTimeLoadingPromiseCleared = Date.now();
92
- try {
93
- const chunks = this.chunks(Array.from(this.accountsToLoad.values()), GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE);
94
- yield Promise.all(chunks.map((chunk) => {
95
- return this.loadChunk(chunk);
96
- }));
97
- }
98
- catch (e) {
99
- console.error(`Error in bulkAccountLoader.load()`);
100
- console.error(e);
101
- for (const [_, callback] of this.errorCallbacks) {
102
- callback(e);
103
- }
104
- }
105
- finally {
106
- this.loadPromiseResolver();
107
- this.loadPromise = undefined;
108
- }
109
- });
110
- }
111
- loadChunk(accountsToLoad) {
112
- return __awaiter(this, void 0, void 0, function* () {
113
- if (accountsToLoad.length === 0) {
114
- return;
115
- }
116
- const args = [
117
- accountsToLoad.map((accountToLoad) => {
118
- return accountToLoad.publicKey.toBase58();
119
- }),
120
- { commitment: this.commitment },
121
- ];
122
- const rpcResponse = yield promiseTimeout_1.promiseTimeout(
123
- // @ts-ignore
124
- this.connection._rpcRequest('getMultipleAccounts', args), 10 * 1000 // 30 second timeout
125
- );
126
- if (rpcResponse === null) {
127
- this.log('request to rpc timed out');
128
- return;
129
- }
130
- const newSlot = rpcResponse.result.context.slot;
131
- if (newSlot > this.mostRecentSlot) {
132
- this.mostRecentSlot = newSlot;
133
- }
134
- for (const i in accountsToLoad) {
135
- const accountToLoad = accountsToLoad[i];
136
- const key = accountToLoad.publicKey.toString();
137
- const oldRPCResponse = this.bufferAndSlotMap.get(key);
138
- let newBuffer = undefined;
139
- if (rpcResponse.result.value[i]) {
140
- const raw = rpcResponse.result.value[i].data[0];
141
- const dataType = rpcResponse.result.value[i].data[1];
142
- newBuffer = Buffer.from(raw, dataType);
143
- }
144
- if (!oldRPCResponse) {
145
- this.bufferAndSlotMap.set(key, {
146
- slot: newSlot,
147
- buffer: newBuffer,
148
- });
149
- this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
150
- continue;
151
- }
152
- if (newSlot <= oldRPCResponse.slot) {
153
- continue;
154
- }
155
- const oldBuffer = oldRPCResponse.buffer;
156
- if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
157
- this.bufferAndSlotMap.set(key, {
158
- slot: newSlot,
159
- buffer: newBuffer,
160
- });
161
- this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
162
- }
163
- }
164
- });
165
- }
166
- handleAccountCallbacks(accountToLoad, buffer, slot) {
167
- for (const [_, callback] of accountToLoad.callbacks) {
168
- callback(buffer, slot);
169
- }
170
- }
171
- getBufferAndSlot(publicKey) {
172
- return this.bufferAndSlotMap.get(publicKey.toString());
173
- }
174
- startPolling() {
175
- if (this.intervalId) {
176
- return;
177
- }
178
- this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
179
- }
180
- stopPolling() {
181
- if (this.intervalId) {
182
- clearInterval(this.intervalId);
183
- this.intervalId = undefined;
184
- }
185
- }
186
- log(msg) {
187
- console.log(msg);
188
- }
189
- updatePollingFrequency(pollingFrequency) {
190
- this.stopPolling();
191
- this.pollingFrequency = pollingFrequency;
192
- if (this.accountsToLoad.size > 0) {
193
- this.startPolling();
194
- }
195
- }
196
- }
197
- exports.BulkAccountLoader = BulkAccountLoader;
@@ -1,33 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.bulkPollingUserSubscribe = void 0;
13
- /**
14
- * @param users
15
- * @param accountLoader
16
- */
17
- function bulkPollingUserSubscribe(users, accountLoader) {
18
- return __awaiter(this, void 0, void 0, function* () {
19
- if (users.length === 0) {
20
- yield accountLoader.load();
21
- return;
22
- }
23
- yield Promise.all(users.map((user) => {
24
- // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
25
- return user.accountSubscriber.addToAccountLoader();
26
- }));
27
- yield accountLoader.load();
28
- yield Promise.all(users.map((user) => __awaiter(this, void 0, void 0, function* () {
29
- return user.subscribe();
30
- })));
31
- });
32
- }
33
- exports.bulkPollingUserSubscribe = bulkPollingUserSubscribe;