@drift-labs/sdk 0.2.0-master.1 → 0.2.0-master.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accounts/types.d.ts +1 -0
- package/lib/admin.d.ts +6 -3
- package/lib/admin.js +39 -7
- package/lib/clearingHouse.d.ts +13 -14
- package/lib/clearingHouse.js +166 -106
- package/lib/config.js +1 -1
- package/lib/constants/banks.js +8 -1
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.js +2 -1
- package/lib/factory/bigNum.d.ts +8 -2
- package/lib/factory/bigNum.js +14 -6
- package/lib/idl/clearing_house.json +277 -55
- package/lib/index.d.ts +2 -1
- package/lib/index.js +6 -1
- package/lib/math/amm.d.ts +6 -1
- package/lib/math/amm.js +124 -41
- package/lib/math/auction.js +4 -1
- package/lib/math/orders.d.ts +2 -2
- package/lib/math/orders.js +18 -11
- package/lib/math/position.js +3 -1
- package/lib/math/repeg.js +1 -1
- package/lib/math/trade.d.ts +1 -1
- package/lib/math/trade.js +7 -10
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +8 -96
- package/lib/orders.d.ts +1 -2
- package/lib/orders.js +6 -85
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +75 -1
- package/lib/types.js +42 -1
- package/package.json +3 -3
- package/src/accounts/bulkAccountLoader.js +197 -0
- package/src/accounts/bulkUserSubscription.js +33 -0
- package/src/accounts/fetch.js +29 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
- package/src/accounts/pollingOracleSubscriber.js +93 -0
- package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
- package/src/accounts/pollingUserAccountSubscriber.js +132 -0
- package/src/accounts/types.js +10 -0
- package/src/accounts/utils.js +7 -0
- package/src/accounts/webSocketAccountSubscriber.js +93 -0
- package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
- package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
- package/src/addresses/marketAddresses.js +26 -0
- package/src/addresses/pda.js +104 -0
- package/src/admin.ts +60 -8
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +223 -183
- package/src/config.ts +1 -1
- package/src/constants/banks.ts +8 -1
- package/src/constants/numericConstants.ts +1 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventSubscriber.js +139 -0
- package/src/events/fetchLogs.js +50 -0
- package/src/events/pollingLogProvider.js +64 -0
- package/src/events/sort.js +44 -0
- package/src/events/txEventCache.js +71 -0
- package/src/events/types.js +20 -0
- package/src/events/webSocketLogProvider.js +41 -0
- package/src/examples/makeTradeExample.js +80 -0
- package/src/factory/bigNum.js +364 -0
- package/src/factory/bigNum.ts +26 -9
- package/src/factory/oracleClient.js +20 -0
- package/src/idl/clearing_house.json +277 -55
- package/src/index.js +69 -0
- package/src/index.ts +2 -1
- package/src/math/amm.js +369 -0
- package/src/math/amm.ts +207 -52
- package/src/math/auction.js +42 -0
- package/src/math/auction.ts +5 -1
- package/src/math/bankBalance.js +75 -0
- package/src/math/conversion.js +11 -0
- package/src/math/funding.js +248 -0
- package/src/math/market.js +57 -0
- package/src/math/oracles.js +26 -0
- package/src/math/orders.js +110 -0
- package/src/math/orders.ts +17 -13
- package/src/math/position.js +140 -0
- package/src/math/position.ts +5 -1
- package/src/math/repeg.js +128 -0
- package/src/math/repeg.ts +2 -1
- package/src/math/state.js +15 -0
- package/src/math/trade.js +253 -0
- package/src/math/trade.ts +23 -25
- package/src/math/utils.js +0 -1
- package/src/mockUSDCFaucet.js +171 -0
- package/src/oracles/oracleClientCache.js +19 -0
- package/src/oracles/pythClient.js +46 -0
- package/src/oracles/quoteAssetOracleClient.js +32 -0
- package/src/oracles/switchboardClient.js +69 -0
- package/src/oracles/types.js +2 -0
- package/src/orderParams.js +20 -0
- package/src/orderParams.ts +20 -141
- package/src/orders.js +134 -0
- package/src/orders.ts +7 -131
- package/src/slot/SlotSubscriber.js +39 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/tx/retryTxSender.js +188 -0
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.js +114 -0
- package/src/types.ts +69 -3
- package/src/userName.js +20 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.js +35 -0
- package/src/util/computeUnits.js +0 -17
- package/src/util/computeUnits.js.map +0 -1
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SlotSubscriber = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
4
5
|
class SlotSubscriber {
|
|
5
6
|
constructor(connection, _config) {
|
|
6
7
|
this.connection = connection;
|
|
8
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
7
9
|
}
|
|
8
10
|
async subscribe() {
|
|
9
11
|
this.currentSlot = await this.connection.getSlot('confirmed');
|
|
10
12
|
this.subscriptionId = this.connection.onSlotChange((slotInfo) => {
|
|
11
13
|
this.currentSlot = slotInfo.slot;
|
|
14
|
+
this.eventEmitter.emit('newSlot', slotInfo.slot);
|
|
12
15
|
});
|
|
13
16
|
}
|
|
14
17
|
getSlot() {
|
package/lib/tx/utils.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.wrapInTx = void 0;
|
|
4
4
|
const web3_js_1 = require("@solana/web3.js");
|
|
5
5
|
const COMPUTE_UNITS_DEFAULT = 200000;
|
|
6
|
-
function wrapInTx(instruction, computeUnits =
|
|
6
|
+
function wrapInTx(instruction, computeUnits = 600000 // TODO, requires less code change
|
|
7
7
|
) {
|
|
8
8
|
const tx = new web3_js_1.Transaction();
|
|
9
9
|
if (computeUnits != COMPUTE_UNITS_DEFAULT) {
|
package/lib/types.d.ts
CHANGED
|
@@ -25,6 +25,14 @@ export declare class PositionDirection {
|
|
|
25
25
|
short: {};
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
+
export declare class DepositDirection {
|
|
29
|
+
static readonly DEPOSIT: {
|
|
30
|
+
deposit: {};
|
|
31
|
+
};
|
|
32
|
+
static readonly WITHDRAW: {
|
|
33
|
+
withdraw: {};
|
|
34
|
+
};
|
|
35
|
+
}
|
|
28
36
|
export declare class OracleSource {
|
|
29
37
|
static readonly PYTH: {
|
|
30
38
|
pyth: {};
|
|
@@ -88,6 +96,23 @@ export declare class OrderAction {
|
|
|
88
96
|
static readonly FILL: {
|
|
89
97
|
fill: {};
|
|
90
98
|
};
|
|
99
|
+
static readonly TRIGGER: {
|
|
100
|
+
trigger: {};
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export declare class OrderActionExplanation {
|
|
104
|
+
static readonly NONE: {
|
|
105
|
+
none: {};
|
|
106
|
+
};
|
|
107
|
+
static readonly BREACHED_MARGIN_REQUIREMENT: {
|
|
108
|
+
breachedMarginRequirement: {};
|
|
109
|
+
};
|
|
110
|
+
static readonly ORACLE_PRICE_BREACHED_LIMIT_PRICE: {
|
|
111
|
+
oraclePriceBreachedLimitPrice: {};
|
|
112
|
+
};
|
|
113
|
+
static readonly MARKET_ORDER_FILLED_TO_LIMIT_PRICE: {
|
|
114
|
+
marketOrderFilledToLimitPrice: {};
|
|
115
|
+
};
|
|
91
116
|
}
|
|
92
117
|
export declare class OrderTriggerCondition {
|
|
93
118
|
static readonly ABOVE: {
|
|
@@ -115,6 +140,7 @@ export declare type DepositRecord = {
|
|
|
115
140
|
};
|
|
116
141
|
bankIndex: BN;
|
|
117
142
|
amount: BN;
|
|
143
|
+
oraclePrice: BN;
|
|
118
144
|
from?: PublicKey;
|
|
119
145
|
to?: PublicKey;
|
|
120
146
|
};
|
|
@@ -182,7 +208,10 @@ export declare type OrderRecord = {
|
|
|
182
208
|
maker: PublicKey;
|
|
183
209
|
takerOrder: Order;
|
|
184
210
|
makerOrder: Order;
|
|
211
|
+
takerUnsettledPnl: BN;
|
|
212
|
+
makerUnsettledPnl: BN;
|
|
185
213
|
action: OrderAction;
|
|
214
|
+
actionExplanation: OrderActionExplanation;
|
|
186
215
|
filler: PublicKey;
|
|
187
216
|
fillRecordId: BN;
|
|
188
217
|
marketIndex: BN;
|
|
@@ -274,6 +303,8 @@ export declare type AMM = {
|
|
|
274
303
|
lastMarkPriceTwapTs: BN;
|
|
275
304
|
lastOraclePriceTwap: BN;
|
|
276
305
|
lastOraclePriceTwapTs: BN;
|
|
306
|
+
lastOracleMarkSpreadPct: BN;
|
|
307
|
+
lastOracleConfPct: BN;
|
|
277
308
|
oracle: PublicKey;
|
|
278
309
|
oracleSource: OracleSource;
|
|
279
310
|
fundingPeriod: BN;
|
|
@@ -288,6 +319,8 @@ export declare type AMM = {
|
|
|
288
319
|
totalFee: BN;
|
|
289
320
|
minimumQuoteAssetTradeSize: BN;
|
|
290
321
|
baseAssetAmountStepSize: BN;
|
|
322
|
+
maxBaseAssetAmountRatio: number;
|
|
323
|
+
maxSlippageRatio: number;
|
|
291
324
|
lastOraclePrice: BN;
|
|
292
325
|
baseSpread: number;
|
|
293
326
|
curveUpdateIntensity: number;
|
|
@@ -304,6 +337,7 @@ export declare type AMM = {
|
|
|
304
337
|
lastAskPriceTwap: BN;
|
|
305
338
|
longSpread: BN;
|
|
306
339
|
shortSpread: BN;
|
|
340
|
+
maxSpread: number;
|
|
307
341
|
};
|
|
308
342
|
export declare type UserPosition = {
|
|
309
343
|
baseAssetAmount: BN;
|
|
@@ -356,6 +390,7 @@ export declare type Order = {
|
|
|
356
390
|
reduceOnly: boolean;
|
|
357
391
|
triggerPrice: BN;
|
|
358
392
|
triggerCondition: OrderTriggerCondition;
|
|
393
|
+
triggered: boolean;
|
|
359
394
|
discountTier: OrderDiscountTier;
|
|
360
395
|
existingPositionDirection: PositionDirection;
|
|
361
396
|
referrer: PublicKey;
|
|
@@ -370,7 +405,6 @@ export declare type OrderParams = {
|
|
|
370
405
|
orderType: OrderType;
|
|
371
406
|
userOrderId: number;
|
|
372
407
|
direction: PositionDirection;
|
|
373
|
-
quoteAssetAmount: BN;
|
|
374
408
|
baseAssetAmount: BN;
|
|
375
409
|
price: BN;
|
|
376
410
|
marketIndex: BN;
|
|
@@ -388,10 +422,50 @@ export declare type OrderParams = {
|
|
|
388
422
|
referrer: boolean;
|
|
389
423
|
};
|
|
390
424
|
};
|
|
425
|
+
export declare type NecessaryOrderParams = {
|
|
426
|
+
orderType: OrderType;
|
|
427
|
+
marketIndex: BN;
|
|
428
|
+
baseAssetAmount: BN;
|
|
429
|
+
direction: PositionDirection;
|
|
430
|
+
};
|
|
431
|
+
export declare type OptionalOrderParams = {
|
|
432
|
+
[Property in keyof OrderParams]?: OrderParams[Property];
|
|
433
|
+
} & NecessaryOrderParams;
|
|
434
|
+
export declare const DefaultOrderParams: {
|
|
435
|
+
orderType: {
|
|
436
|
+
market: {};
|
|
437
|
+
};
|
|
438
|
+
userOrderId: number;
|
|
439
|
+
direction: {
|
|
440
|
+
long: {};
|
|
441
|
+
};
|
|
442
|
+
baseAssetAmount: BN;
|
|
443
|
+
price: BN;
|
|
444
|
+
marketIndex: BN;
|
|
445
|
+
reduceOnly: boolean;
|
|
446
|
+
postOnly: boolean;
|
|
447
|
+
immediateOrCancel: boolean;
|
|
448
|
+
triggerPrice: BN;
|
|
449
|
+
triggerCondition: {
|
|
450
|
+
above: {};
|
|
451
|
+
};
|
|
452
|
+
positionLimit: BN;
|
|
453
|
+
oraclePriceOffset: BN;
|
|
454
|
+
padding0: BN;
|
|
455
|
+
padding1: BN;
|
|
456
|
+
optionalAccounts: {
|
|
457
|
+
discountToken: boolean;
|
|
458
|
+
referrer: boolean;
|
|
459
|
+
};
|
|
460
|
+
};
|
|
391
461
|
export declare type MakerInfo = {
|
|
392
462
|
maker: PublicKey;
|
|
393
463
|
order: Order;
|
|
394
464
|
};
|
|
465
|
+
export declare type TakerInfo = {
|
|
466
|
+
taker: PublicKey;
|
|
467
|
+
order: Order;
|
|
468
|
+
};
|
|
395
469
|
export interface IWallet {
|
|
396
470
|
signTransaction(tx: Transaction): Promise<Transaction>;
|
|
397
471
|
signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
|
package/lib/types.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TradeSide = exports.isOneOfVariant = exports.isVariant = exports.OrderTriggerCondition = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.OrderType = exports.OracleSource = exports.PositionDirection = exports.BankBalanceType = exports.SwapDirection = void 0;
|
|
3
|
+
exports.DefaultOrderParams = exports.TradeSide = exports.isOneOfVariant = exports.isVariant = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.BankBalanceType = exports.SwapDirection = void 0;
|
|
4
|
+
const _1 = require(".");
|
|
4
5
|
// # Utility Types / Enums / Constants
|
|
5
6
|
class SwapDirection {
|
|
6
7
|
}
|
|
@@ -17,6 +18,11 @@ class PositionDirection {
|
|
|
17
18
|
exports.PositionDirection = PositionDirection;
|
|
18
19
|
PositionDirection.LONG = { long: {} };
|
|
19
20
|
PositionDirection.SHORT = { short: {} };
|
|
21
|
+
class DepositDirection {
|
|
22
|
+
}
|
|
23
|
+
exports.DepositDirection = DepositDirection;
|
|
24
|
+
DepositDirection.DEPOSIT = { deposit: {} };
|
|
25
|
+
DepositDirection.WITHDRAW = { withdraw: {} };
|
|
20
26
|
class OracleSource {
|
|
21
27
|
}
|
|
22
28
|
exports.OracleSource = OracleSource;
|
|
@@ -50,6 +56,20 @@ OrderAction.PLACE = { place: {} };
|
|
|
50
56
|
OrderAction.CANCEL = { cancel: {} };
|
|
51
57
|
OrderAction.EXPIRE = { expire: {} };
|
|
52
58
|
OrderAction.FILL = { fill: {} };
|
|
59
|
+
OrderAction.TRIGGER = { trigger: {} };
|
|
60
|
+
class OrderActionExplanation {
|
|
61
|
+
}
|
|
62
|
+
exports.OrderActionExplanation = OrderActionExplanation;
|
|
63
|
+
OrderActionExplanation.NONE = { none: {} };
|
|
64
|
+
OrderActionExplanation.BREACHED_MARGIN_REQUIREMENT = {
|
|
65
|
+
breachedMarginRequirement: {},
|
|
66
|
+
};
|
|
67
|
+
OrderActionExplanation.ORACLE_PRICE_BREACHED_LIMIT_PRICE = {
|
|
68
|
+
oraclePriceBreachedLimitPrice: {},
|
|
69
|
+
};
|
|
70
|
+
OrderActionExplanation.MARKET_ORDER_FILLED_TO_LIMIT_PRICE = {
|
|
71
|
+
marketOrderFilledToLimitPrice: {},
|
|
72
|
+
};
|
|
53
73
|
class OrderTriggerCondition {
|
|
54
74
|
}
|
|
55
75
|
exports.OrderTriggerCondition = OrderTriggerCondition;
|
|
@@ -71,3 +91,24 @@ var TradeSide;
|
|
|
71
91
|
TradeSide[TradeSide["Buy"] = 1] = "Buy";
|
|
72
92
|
TradeSide[TradeSide["Sell"] = 2] = "Sell";
|
|
73
93
|
})(TradeSide = exports.TradeSide || (exports.TradeSide = {}));
|
|
94
|
+
exports.DefaultOrderParams = {
|
|
95
|
+
orderType: OrderType.MARKET,
|
|
96
|
+
userOrderId: 0,
|
|
97
|
+
direction: PositionDirection.LONG,
|
|
98
|
+
baseAssetAmount: _1.ZERO,
|
|
99
|
+
price: _1.ZERO,
|
|
100
|
+
marketIndex: _1.ZERO,
|
|
101
|
+
reduceOnly: false,
|
|
102
|
+
postOnly: false,
|
|
103
|
+
immediateOrCancel: false,
|
|
104
|
+
triggerPrice: _1.ZERO,
|
|
105
|
+
triggerCondition: OrderTriggerCondition.ABOVE,
|
|
106
|
+
positionLimit: _1.ZERO,
|
|
107
|
+
oraclePriceOffset: _1.ZERO,
|
|
108
|
+
padding0: _1.ZERO,
|
|
109
|
+
padding1: _1.ZERO,
|
|
110
|
+
optionalAccounts: {
|
|
111
|
+
discountToken: false,
|
|
112
|
+
referrer: false,
|
|
113
|
+
},
|
|
114
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "0.2.0-master.
|
|
3
|
+
"version": "0.2.0-master.10",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@project-serum/anchor": "0.24.2",
|
|
33
|
-
"@pythnetwork/client": "2.5.
|
|
33
|
+
"@pythnetwork/client": "2.5.3",
|
|
34
34
|
"@solana/spl-token": "^0.1.6",
|
|
35
35
|
"@solana/web3.js": "1.41.0",
|
|
36
36
|
"@switchboard-xyz/switchboard-v2": "^0.0.67",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/chai": "^4.3.1",
|
|
42
|
+
"@types/jest": "^28.1.3",
|
|
42
43
|
"@types/mocha": "^9.1.1",
|
|
43
44
|
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
|
44
45
|
"@typescript-eslint/parser": "^4.28.0",
|
|
45
|
-
"@types/jest": "^28.1.3",
|
|
46
46
|
"chai": "^4.3.6",
|
|
47
47
|
"eslint": "^7.29.0",
|
|
48
48
|
"eslint-config-prettier": "^8.3.0",
|
|
@@ -0,0 +1,197 @@
|
|
|
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;
|
|
@@ -0,0 +1,33 @@
|
|
|
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;
|
|
@@ -0,0 +1,29 @@
|
|
|
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.fetchUserAccounts = void 0;
|
|
13
|
+
const pda_1 = require("../addresses/pda");
|
|
14
|
+
function fetchUserAccounts(connection, program, authority, limit = 8) {
|
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
const userAccountPublicKeys = new Array();
|
|
17
|
+
for (let i = 0; i < limit; i++) {
|
|
18
|
+
userAccountPublicKeys.push(yield pda_1.getUserAccountPublicKey(program.programId, authority, i));
|
|
19
|
+
}
|
|
20
|
+
const accountInfos = yield connection.getMultipleAccountsInfo(userAccountPublicKeys, 'confirmed');
|
|
21
|
+
return accountInfos.map((accountInfo) => {
|
|
22
|
+
if (!accountInfo) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
return program.account.user.coder.accounts.decode('User', accountInfo.data);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.fetchUserAccounts = fetchUserAccounts;
|