@drift-labs/sdk 0.2.0-master.2 → 0.2.0-master.20
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/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +14 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +8 -1
- package/lib/admin.d.ts +9 -5
- package/lib/admin.js +52 -11
- package/lib/clearingHouse.d.ts +52 -23
- package/lib/clearingHouse.js +727 -197
- package/lib/clearingHouseConfig.d.ts +1 -0
- package/lib/clearingHouseUser.d.ts +17 -17
- package/lib/clearingHouseUser.js +186 -101
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +12 -4
- package/lib/constants/numericConstants.d.ts +5 -0
- package/lib/constants/numericConstants.js +8 -3
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +3 -1
- package/lib/events/types.js +2 -0
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +34 -10
- package/lib/idl/clearing_house.json +1609 -388
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +9 -3
- package/lib/index.js +13 -3
- package/lib/math/amm.d.ts +1 -0
- package/lib/math/amm.js +22 -38
- package/lib/math/auction.js +4 -1
- package/lib/math/bankBalance.d.ts +7 -1
- package/lib/math/bankBalance.js +77 -2
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/oracles.d.ts +3 -0
- package/lib/math/oracles.js +25 -5
- package/lib/math/orders.d.ts +5 -2
- package/lib/math/orders.js +53 -12
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +45 -12
- 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/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.js +9 -2
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +233 -26
- package/lib/types.js +64 -1
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +3 -3
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +18 -0
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.js +26 -0
- package/src/addresses/pda.ts +13 -0
- package/src/admin.ts +82 -15
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +1224 -319
- package/src/clearingHouseConfig.ts +1 -0
- package/src/clearingHouseUser.ts +311 -148
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +14 -4
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +14 -2
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -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.ts +6 -0
- package/src/events/webSocketLogProvider.js +41 -0
- package/src/examples/makeTradeExample.js +80 -0
- package/src/factory/bigNum.js +390 -0
- package/src/factory/bigNum.ts +42 -13
- package/src/factory/oracleClient.js +20 -0
- package/src/idl/clearing_house.json +1609 -388
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +9 -3
- package/src/math/amm.ts +54 -55
- package/src/math/auction.js +42 -0
- package/src/math/auction.ts +5 -1
- package/src/math/bankBalance.ts +148 -2
- package/src/math/conversion.js +11 -0
- package/src/math/funding.js +248 -0
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/oracles.js +26 -0
- package/src/math/oracles.ts +42 -5
- package/src/math/orders.ts +112 -13
- package/src/math/position.ts +64 -9
- package/src/math/repeg.js +128 -0
- 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/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/slot/SlotSubscriber.js +39 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/tokenFaucet.js +189 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +11 -3
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +236 -27
- package/src/userName.js +20 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.js +35 -0
- package/tests/bn/test.ts +10 -0
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -142
- package/src/orders.ts +0 -251
- package/src/util/computeUnits.js.map +0 -1
package/lib/util/computeUnits.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.findComputeUnitConsumption = void 0;
|
|
|
4
4
|
async function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
|
|
5
5
|
const tx = await connection.getTransaction(txSignature, { commitment });
|
|
6
6
|
const computeUnits = [];
|
|
7
|
-
const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of
|
|
7
|
+
const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
|
|
8
8
|
tx.meta.logMessages.forEach((logMessage) => {
|
|
9
9
|
const match = logMessage.match(regex);
|
|
10
10
|
if (match && match[1]) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTokenAddress = void 0;
|
|
4
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
7
|
+
return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
|
|
8
|
+
};
|
|
9
|
+
exports.getTokenAddress = getTokenAddress;
|
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.20",
|
|
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,33 @@
|
|
|
1
|
+
import { ClearingHouseUserStats } from '../clearingHouseUserStats';
|
|
2
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
3
|
+
import { PollingUserStatsAccountSubscriber } from './pollingUserStatsAccountSubscriber';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param userStats
|
|
7
|
+
* @param accountLoader
|
|
8
|
+
*/
|
|
9
|
+
export async function bulkPollingUserStatsSubscribe(
|
|
10
|
+
userStats: ClearingHouseUserStats[],
|
|
11
|
+
accountLoader: BulkAccountLoader
|
|
12
|
+
): Promise<void> {
|
|
13
|
+
if (userStats.length === 0) {
|
|
14
|
+
await accountLoader.load();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
await Promise.all(
|
|
19
|
+
userStats.map((userStat) => {
|
|
20
|
+
return (
|
|
21
|
+
userStat.accountSubscriber as PollingUserStatsAccountSubscriber
|
|
22
|
+
).addToAccountLoader();
|
|
23
|
+
})
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
await accountLoader.load();
|
|
27
|
+
|
|
28
|
+
await Promise.all(
|
|
29
|
+
userStats.map(async (userStat) => {
|
|
30
|
+
return userStat.subscribe();
|
|
31
|
+
})
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -17,7 +17,6 @@ export async function bulkPollingUserSubscribe(
|
|
|
17
17
|
|
|
18
18
|
await Promise.all(
|
|
19
19
|
users.map((user) => {
|
|
20
|
-
// Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
|
|
21
20
|
return (
|
|
22
21
|
user.accountSubscriber as PollingUserAccountSubscriber
|
|
23
22
|
).addToAccountLoader();
|
package/src/accounts/fetch.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
2
|
-
import { UserAccount } from '../types';
|
|
3
|
-
import {
|
|
2
|
+
import { UserAccount, UserStatsAccount } from '../types';
|
|
3
|
+
import {
|
|
4
|
+
getUserAccountPublicKey,
|
|
5
|
+
getUserStatsAccountPublicKey,
|
|
6
|
+
} from '../addresses/pda';
|
|
4
7
|
import { Program } from '@project-serum/anchor';
|
|
5
8
|
|
|
6
9
|
export async function fetchUserAccounts(
|
|
@@ -31,3 +34,25 @@ export async function fetchUserAccounts(
|
|
|
31
34
|
) as UserAccount;
|
|
32
35
|
});
|
|
33
36
|
}
|
|
37
|
+
|
|
38
|
+
export async function fetchUserStatsAccount(
|
|
39
|
+
connection: Connection,
|
|
40
|
+
program: Program,
|
|
41
|
+
authority: PublicKey
|
|
42
|
+
): Promise<UserStatsAccount | undefined> {
|
|
43
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
44
|
+
program.programId,
|
|
45
|
+
authority
|
|
46
|
+
);
|
|
47
|
+
const accountInfo = await connection.getAccountInfo(
|
|
48
|
+
userStatsPublicKey,
|
|
49
|
+
'confirmed'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return accountInfo
|
|
53
|
+
? (program.account.user.coder.accounts.decode(
|
|
54
|
+
'UserStats',
|
|
55
|
+
accountInfo.data
|
|
56
|
+
) as UserStatsAccount)
|
|
57
|
+
: undefined;
|
|
58
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataAndSlot,
|
|
3
|
+
AccountToPoll,
|
|
4
|
+
NotSubscribedError,
|
|
5
|
+
UserStatsAccountSubscriber,
|
|
6
|
+
UserStatsAccountEvents,
|
|
7
|
+
} from './types';
|
|
8
|
+
import { Program } from '@project-serum/anchor';
|
|
9
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
import { PublicKey } from '@solana/web3.js';
|
|
12
|
+
import { UserStatsAccount } from '../types';
|
|
13
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
14
|
+
import { capitalize } from './utils';
|
|
15
|
+
|
|
16
|
+
export class PollingUserStatsAccountSubscriber
|
|
17
|
+
implements UserStatsAccountSubscriber
|
|
18
|
+
{
|
|
19
|
+
isSubscribed: boolean;
|
|
20
|
+
program: Program;
|
|
21
|
+
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
22
|
+
userStatsAccountPublicKey: PublicKey;
|
|
23
|
+
|
|
24
|
+
accountLoader: BulkAccountLoader;
|
|
25
|
+
accountsToPoll = new Map<string, AccountToPoll>();
|
|
26
|
+
errorCallbackId?: string;
|
|
27
|
+
|
|
28
|
+
userStats?: DataAndSlot<UserStatsAccount>;
|
|
29
|
+
|
|
30
|
+
public constructor(
|
|
31
|
+
program: Program,
|
|
32
|
+
userStatsAccountPublicKey: PublicKey,
|
|
33
|
+
accountLoader: BulkAccountLoader
|
|
34
|
+
) {
|
|
35
|
+
this.isSubscribed = false;
|
|
36
|
+
this.program = program;
|
|
37
|
+
this.accountLoader = accountLoader;
|
|
38
|
+
this.eventEmitter = new EventEmitter();
|
|
39
|
+
this.userStatsAccountPublicKey = userStatsAccountPublicKey;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async subscribe(): Promise<boolean> {
|
|
43
|
+
if (this.isSubscribed) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await this.addToAccountLoader();
|
|
48
|
+
|
|
49
|
+
let subscriptionSucceeded = false;
|
|
50
|
+
let retries = 0;
|
|
51
|
+
while (!subscriptionSucceeded && retries < 5) {
|
|
52
|
+
await this.fetchIfUnloaded();
|
|
53
|
+
subscriptionSucceeded = this.didSubscriptionSucceed();
|
|
54
|
+
retries++;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (subscriptionSucceeded) {
|
|
58
|
+
this.eventEmitter.emit('update');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.isSubscribed = subscriptionSucceeded;
|
|
62
|
+
return subscriptionSucceeded;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async addToAccountLoader(): Promise<void> {
|
|
66
|
+
if (this.accountsToPoll.size > 0) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this.accountsToPoll.set(this.userStatsAccountPublicKey.toString(), {
|
|
71
|
+
key: 'userStats',
|
|
72
|
+
publicKey: this.userStatsAccountPublicKey,
|
|
73
|
+
eventType: 'userStatsAccountUpdate',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
77
|
+
accountToPoll.callbackId = this.accountLoader.addAccount(
|
|
78
|
+
accountToPoll.publicKey,
|
|
79
|
+
(buffer, slot) => {
|
|
80
|
+
if (!buffer) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const account = this.program.account[
|
|
85
|
+
accountToPoll.key
|
|
86
|
+
].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
|
|
87
|
+
this[accountToPoll.key] = { data: account, slot };
|
|
88
|
+
// @ts-ignore
|
|
89
|
+
this.eventEmitter.emit(accountToPoll.eventType, account);
|
|
90
|
+
this.eventEmitter.emit('update');
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
|
|
96
|
+
this.eventEmitter.emit('error', error);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async fetchIfUnloaded(): Promise<void> {
|
|
101
|
+
let shouldFetch = false;
|
|
102
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
103
|
+
if (this[accountToPoll.key] === undefined) {
|
|
104
|
+
shouldFetch = true;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (shouldFetch) {
|
|
110
|
+
await this.fetch();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async fetch(): Promise<void> {
|
|
115
|
+
await this.accountLoader.load();
|
|
116
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
117
|
+
const { buffer, slot } = this.accountLoader.getBufferAndSlot(
|
|
118
|
+
accountToPoll.publicKey
|
|
119
|
+
);
|
|
120
|
+
if (buffer) {
|
|
121
|
+
const account = this.program.account[
|
|
122
|
+
accountToPoll.key
|
|
123
|
+
].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
|
|
124
|
+
this[accountToPoll.key] = { data: account, slot };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
didSubscriptionSucceed(): boolean {
|
|
130
|
+
let success = true;
|
|
131
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
132
|
+
if (!this[accountToPoll.key]) {
|
|
133
|
+
success = false;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return success;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async unsubscribe(): Promise<void> {
|
|
141
|
+
if (!this.isSubscribed) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
146
|
+
this.accountLoader.removeAccount(
|
|
147
|
+
accountToPoll.publicKey,
|
|
148
|
+
accountToPoll.callbackId
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
|
|
153
|
+
this.errorCallbackId = undefined;
|
|
154
|
+
|
|
155
|
+
this.accountsToPoll.clear();
|
|
156
|
+
|
|
157
|
+
this.isSubscribed = false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
assertIsSubscribed(): void {
|
|
161
|
+
if (!this.isSubscribed) {
|
|
162
|
+
throw new NotSubscribedError(
|
|
163
|
+
'You must call `subscribe` before using this function'
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount> {
|
|
169
|
+
this.assertIsSubscribed();
|
|
170
|
+
return this.userStats;
|
|
171
|
+
}
|
|
172
|
+
}
|
package/src/accounts/types.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
OracleSource,
|
|
5
5
|
StateAccount,
|
|
6
6
|
UserAccount,
|
|
7
|
+
UserStatsAccount,
|
|
7
8
|
} from '../types';
|
|
8
9
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
9
10
|
import { EventEmitter } from 'events';
|
|
@@ -130,3 +131,20 @@ export type DataAndSlot<T> = {
|
|
|
130
131
|
data: T;
|
|
131
132
|
slot: number;
|
|
132
133
|
};
|
|
134
|
+
|
|
135
|
+
export interface UserStatsAccountEvents {
|
|
136
|
+
userStatsAccountUpdate: (payload: UserStatsAccount) => void;
|
|
137
|
+
update: void;
|
|
138
|
+
error: (e: Error) => void;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface UserStatsAccountSubscriber {
|
|
142
|
+
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
143
|
+
isSubscribed: boolean;
|
|
144
|
+
|
|
145
|
+
subscribe(): Promise<boolean>;
|
|
146
|
+
fetch(): Promise<void>;
|
|
147
|
+
unsubscribe(): Promise<void>;
|
|
148
|
+
|
|
149
|
+
getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount>;
|
|
150
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataAndSlot,
|
|
3
|
+
AccountSubscriber,
|
|
4
|
+
NotSubscribedError,
|
|
5
|
+
UserStatsAccountSubscriber,
|
|
6
|
+
UserStatsAccountEvents,
|
|
7
|
+
} from './types';
|
|
8
|
+
import { Program } from '@project-serum/anchor';
|
|
9
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
import { PublicKey } from '@solana/web3.js';
|
|
12
|
+
import { WebSocketAccountSubscriber } from './webSocketAccountSubscriber';
|
|
13
|
+
import { UserStatsAccount } from '../types';
|
|
14
|
+
|
|
15
|
+
export class WebSocketUserStatsAccountSubscriber
|
|
16
|
+
implements UserStatsAccountSubscriber
|
|
17
|
+
{
|
|
18
|
+
isSubscribed: boolean;
|
|
19
|
+
program: Program;
|
|
20
|
+
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
21
|
+
userStatsAccountPublicKey: PublicKey;
|
|
22
|
+
|
|
23
|
+
userStatsAccountSubscriber: AccountSubscriber<UserStatsAccount>;
|
|
24
|
+
|
|
25
|
+
public constructor(program: Program, userStatsAccountPublicKey: PublicKey) {
|
|
26
|
+
this.isSubscribed = false;
|
|
27
|
+
this.program = program;
|
|
28
|
+
this.userStatsAccountPublicKey = userStatsAccountPublicKey;
|
|
29
|
+
this.eventEmitter = new EventEmitter();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async subscribe(): Promise<boolean> {
|
|
33
|
+
if (this.isSubscribed) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.userStatsAccountSubscriber = new WebSocketAccountSubscriber(
|
|
38
|
+
'userStats',
|
|
39
|
+
this.program,
|
|
40
|
+
this.userStatsAccountPublicKey
|
|
41
|
+
);
|
|
42
|
+
await this.userStatsAccountSubscriber.subscribe(
|
|
43
|
+
(data: UserStatsAccount) => {
|
|
44
|
+
this.eventEmitter.emit('userStatsAccountUpdate', data);
|
|
45
|
+
this.eventEmitter.emit('update');
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
this.eventEmitter.emit('update');
|
|
50
|
+
this.isSubscribed = true;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async fetch(): Promise<void> {
|
|
55
|
+
await Promise.all([this.userStatsAccountSubscriber.fetch()]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async unsubscribe(): Promise<void> {
|
|
59
|
+
if (!this.isSubscribed) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await Promise.all([this.userStatsAccountSubscriber.unsubscribe()]);
|
|
64
|
+
|
|
65
|
+
this.isSubscribed = false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
assertIsSubscribed(): void {
|
|
69
|
+
if (!this.isSubscribed) {
|
|
70
|
+
throw new NotSubscribedError(
|
|
71
|
+
'You must call `subscribe` before using this function'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount> {
|
|
77
|
+
this.assertIsSubscribed();
|
|
78
|
+
return this.userStatsAccountSubscriber.dataAndSlot;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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.getMarketAddress = void 0;
|
|
13
|
+
const pda_1 = require("./pda");
|
|
14
|
+
const CACHE = new Map();
|
|
15
|
+
function getMarketAddress(programId, marketIndex) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const cacheKey = `${programId.toString()}-${marketIndex.toString()}`;
|
|
18
|
+
if (CACHE.has(cacheKey)) {
|
|
19
|
+
return CACHE.get(cacheKey);
|
|
20
|
+
}
|
|
21
|
+
const publicKey = yield pda_1.getMarketPublicKey(programId, marketIndex);
|
|
22
|
+
CACHE.set(cacheKey, publicKey);
|
|
23
|
+
return publicKey;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
exports.getMarketAddress = getMarketAddress;
|
package/src/addresses/pda.ts
CHANGED
|
@@ -57,6 +57,19 @@ export function getUserAccountPublicKeySync(
|
|
|
57
57
|
)[0];
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export function getUserStatsAccountPublicKey(
|
|
61
|
+
programId: PublicKey,
|
|
62
|
+
authority: PublicKey
|
|
63
|
+
): PublicKey {
|
|
64
|
+
return anchor.web3.PublicKey.findProgramAddressSync(
|
|
65
|
+
[
|
|
66
|
+
Buffer.from(anchor.utils.bytes.utf8.encode('user_stats')),
|
|
67
|
+
authority.toBuffer(),
|
|
68
|
+
],
|
|
69
|
+
programId
|
|
70
|
+
)[0];
|
|
71
|
+
}
|
|
72
|
+
|
|
60
73
|
export async function getMarketPublicKey(
|
|
61
74
|
programId: PublicKey,
|
|
62
75
|
marketIndex: BN
|
package/src/admin.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from './addresses/pda';
|
|
21
21
|
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
22
22
|
import { ClearingHouse } from './clearingHouse';
|
|
23
|
-
import { PEG_PRECISION } from './constants/numericConstants';
|
|
23
|
+
import { PEG_PRECISION, ZERO } from './constants/numericConstants';
|
|
24
24
|
import { calculateTargetPriceTrade } from './math/trade';
|
|
25
25
|
import { calculateAmmReservesAfterSwap, getSwapDirection } from './math/amm';
|
|
26
26
|
|
|
@@ -85,7 +85,9 @@ export class Admin extends ClearingHouse {
|
|
|
85
85
|
initialAssetWeight: BN,
|
|
86
86
|
maintenanceAssetWeight: BN,
|
|
87
87
|
initialLiabilityWeight: BN,
|
|
88
|
-
maintenanceLiabilityWeight: BN
|
|
88
|
+
maintenanceLiabilityWeight: BN,
|
|
89
|
+
imfFactor = new BN(0),
|
|
90
|
+
liquidationFee = ZERO
|
|
89
91
|
): Promise<TransactionSignature> {
|
|
90
92
|
const bankIndex = this.getStateAccount().numberOfBanks;
|
|
91
93
|
const bank = await getBankPublicKey(this.program.programId, bankIndex);
|
|
@@ -109,6 +111,8 @@ export class Admin extends ClearingHouse {
|
|
|
109
111
|
maintenanceAssetWeight,
|
|
110
112
|
initialLiabilityWeight,
|
|
111
113
|
maintenanceLiabilityWeight,
|
|
114
|
+
imfFactor,
|
|
115
|
+
liquidationFee,
|
|
112
116
|
{
|
|
113
117
|
accounts: {
|
|
114
118
|
admin: this.wallet.publicKey,
|
|
@@ -144,8 +148,8 @@ export class Admin extends ClearingHouse {
|
|
|
144
148
|
pegMultiplier: BN = PEG_PRECISION,
|
|
145
149
|
oracleSource: OracleSource = OracleSource.PYTH,
|
|
146
150
|
marginRatioInitial = 2000,
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
marginRatioMaintenance = 500,
|
|
152
|
+
liquidationFee = ZERO
|
|
149
153
|
): Promise<TransactionSignature> {
|
|
150
154
|
const marketPublicKey = await getMarketPublicKey(
|
|
151
155
|
this.program.programId,
|
|
@@ -159,8 +163,8 @@ export class Admin extends ClearingHouse {
|
|
|
159
163
|
pegMultiplier,
|
|
160
164
|
oracleSource,
|
|
161
165
|
marginRatioInitial,
|
|
162
|
-
marginRatioPartial,
|
|
163
166
|
marginRatioMaintenance,
|
|
167
|
+
liquidationFee,
|
|
164
168
|
{
|
|
165
169
|
accounts: {
|
|
166
170
|
state: await this.getStatePublicKey(),
|
|
@@ -329,10 +333,12 @@ export class Admin extends ClearingHouse {
|
|
|
329
333
|
recipient: PublicKey
|
|
330
334
|
): Promise<TransactionSignature> {
|
|
331
335
|
const state = await this.getStateAccount();
|
|
336
|
+
const bank = this.getQuoteAssetBankAccount();
|
|
332
337
|
return await this.program.rpc.withdrawFromInsuranceVault(amount, {
|
|
333
338
|
accounts: {
|
|
334
339
|
admin: this.wallet.publicKey,
|
|
335
340
|
state: await this.getStatePublicKey(),
|
|
341
|
+
bank: bank.pubkey,
|
|
336
342
|
insuranceVault: state.insuranceVault,
|
|
337
343
|
insuranceVaultAuthority: state.insuranceVaultAuthority,
|
|
338
344
|
recipient: recipient,
|
|
@@ -341,7 +347,7 @@ export class Admin extends ClearingHouse {
|
|
|
341
347
|
});
|
|
342
348
|
}
|
|
343
349
|
|
|
344
|
-
public async
|
|
350
|
+
public async withdrawFromMarketToInsuranceVault(
|
|
345
351
|
marketIndex: BN,
|
|
346
352
|
amount: BN,
|
|
347
353
|
recipient: PublicKey
|
|
@@ -351,7 +357,7 @@ export class Admin extends ClearingHouse {
|
|
|
351
357
|
marketIndex
|
|
352
358
|
);
|
|
353
359
|
const bank = this.getQuoteAssetBankAccount();
|
|
354
|
-
return await this.program.rpc.
|
|
360
|
+
return await this.program.rpc.withdrawFromMarketToInsuranceVault(amount, {
|
|
355
361
|
accounts: {
|
|
356
362
|
admin: this.wallet.publicKey,
|
|
357
363
|
state: await this.getStatePublicKey(),
|
|
@@ -370,6 +376,8 @@ export class Admin extends ClearingHouse {
|
|
|
370
376
|
amount: BN
|
|
371
377
|
): Promise<TransactionSignature> {
|
|
372
378
|
const state = await this.getStateAccount();
|
|
379
|
+
const bank = this.getQuoteAssetBankAccount();
|
|
380
|
+
|
|
373
381
|
return await this.program.rpc.withdrawFromInsuranceVaultToMarket(amount, {
|
|
374
382
|
accounts: {
|
|
375
383
|
admin: this.wallet.publicKey,
|
|
@@ -377,7 +385,9 @@ export class Admin extends ClearingHouse {
|
|
|
377
385
|
market: await getMarketPublicKey(this.program.programId, marketIndex),
|
|
378
386
|
insuranceVault: state.insuranceVault,
|
|
379
387
|
insuranceVaultAuthority: state.insuranceVaultAuthority,
|
|
380
|
-
|
|
388
|
+
bank: bank.pubkey,
|
|
389
|
+
bankVault: bank.vault,
|
|
390
|
+
bankVaultAuthority: bank.vaultAuthority,
|
|
381
391
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
382
392
|
},
|
|
383
393
|
});
|
|
@@ -414,12 +424,10 @@ export class Admin extends ClearingHouse {
|
|
|
414
424
|
public async updateMarginRatio(
|
|
415
425
|
marketIndex: BN,
|
|
416
426
|
marginRatioInitial: number,
|
|
417
|
-
marginRatioPartial: number,
|
|
418
427
|
marginRatioMaintenance: number
|
|
419
428
|
): Promise<TransactionSignature> {
|
|
420
429
|
return await this.program.rpc.updateMarginRatio(
|
|
421
430
|
marginRatioInitial,
|
|
422
|
-
marginRatioPartial,
|
|
423
431
|
marginRatioMaintenance,
|
|
424
432
|
{
|
|
425
433
|
accounts: {
|
|
@@ -567,6 +575,35 @@ export class Admin extends ClearingHouse {
|
|
|
567
575
|
});
|
|
568
576
|
}
|
|
569
577
|
|
|
578
|
+
public async updateBankWithdrawGuardThreshold(
|
|
579
|
+
bankIndex: BN,
|
|
580
|
+
withdrawGuardThreshold: BN
|
|
581
|
+
): Promise<TransactionSignature> {
|
|
582
|
+
return await this.program.rpc.updateBankWithdrawGuardThreshold(
|
|
583
|
+
withdrawGuardThreshold,
|
|
584
|
+
{
|
|
585
|
+
accounts: {
|
|
586
|
+
admin: this.wallet.publicKey,
|
|
587
|
+
state: await this.getStatePublicKey(),
|
|
588
|
+
bank: await getBankPublicKey(this.program.programId, bankIndex),
|
|
589
|
+
},
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
public async updateLpCooldownTime(
|
|
595
|
+
marketIndex: BN,
|
|
596
|
+
cooldownTime: BN
|
|
597
|
+
): Promise<TransactionSignature> {
|
|
598
|
+
return await this.program.rpc.updateLpCooldownTime(cooldownTime, {
|
|
599
|
+
accounts: {
|
|
600
|
+
admin: this.wallet.publicKey,
|
|
601
|
+
state: await this.getStatePublicKey(),
|
|
602
|
+
market: await getMarketPublicKey(this.program.programId, marketIndex),
|
|
603
|
+
},
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
|
|
570
607
|
public async updateMarketOracle(
|
|
571
608
|
marketIndex: BN,
|
|
572
609
|
oracle: PublicKey,
|
|
@@ -654,7 +691,6 @@ export class Admin extends ClearingHouse {
|
|
|
654
691
|
},
|
|
655
692
|
});
|
|
656
693
|
}
|
|
657
|
-
|
|
658
694
|
public async updateExchangePaused(
|
|
659
695
|
exchangePaused: boolean
|
|
660
696
|
): Promise<TransactionSignature> {
|
|
@@ -675,17 +711,48 @@ export class Admin extends ClearingHouse {
|
|
|
675
711
|
});
|
|
676
712
|
}
|
|
677
713
|
|
|
678
|
-
public async
|
|
679
|
-
|
|
714
|
+
public async updateAuctionDuration(
|
|
715
|
+
minDuration: BN | number,
|
|
716
|
+
maxDuration: BN | number
|
|
717
|
+
): Promise<TransactionSignature> {
|
|
718
|
+
return await this.program.rpc.updateAuctionDuration(
|
|
719
|
+
typeof minDuration === 'number' ? minDuration : minDuration.toNumber(),
|
|
720
|
+
typeof maxDuration === 'number' ? maxDuration : maxDuration.toNumber(),
|
|
721
|
+
{
|
|
722
|
+
accounts: {
|
|
723
|
+
admin: this.wallet.publicKey,
|
|
724
|
+
state: await this.getStatePublicKey(),
|
|
725
|
+
},
|
|
726
|
+
}
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
public async updateMaxBaseAssetAmountRatio(
|
|
731
|
+
marketIndex: BN,
|
|
732
|
+
maxBaseAssetAmountRatio: number
|
|
680
733
|
): Promise<TransactionSignature> {
|
|
681
|
-
return await this.program.rpc.
|
|
682
|
-
|
|
734
|
+
return await this.program.rpc.updateMaxBaseAssetAmountRatio(
|
|
735
|
+
maxBaseAssetAmountRatio,
|
|
683
736
|
{
|
|
684
737
|
accounts: {
|
|
685
738
|
admin: this.wallet.publicKey,
|
|
686
739
|
state: await this.getStatePublicKey(),
|
|
740
|
+
market: this.getMarketAccount(marketIndex).pubkey,
|
|
687
741
|
},
|
|
688
742
|
}
|
|
689
743
|
);
|
|
690
744
|
}
|
|
745
|
+
|
|
746
|
+
public async updateMaxSlippageRatio(
|
|
747
|
+
marketIndex: BN,
|
|
748
|
+
maxSlippageRatio: number
|
|
749
|
+
): Promise<TransactionSignature> {
|
|
750
|
+
return await this.program.rpc.updateMaxSlippageRatio(maxSlippageRatio, {
|
|
751
|
+
accounts: {
|
|
752
|
+
admin: this.wallet.publicKey,
|
|
753
|
+
state: await this.getStatePublicKey(),
|
|
754
|
+
market: this.getMarketAccount(marketIndex).pubkey,
|
|
755
|
+
},
|
|
756
|
+
});
|
|
757
|
+
}
|
|
691
758
|
}
|