@drift-labs/sdk 0.2.0-master.24 → 0.2.0-master.25
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/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +5 -1
- package/lib/admin.js +7 -12
- package/lib/clearingHouse.d.ts +2 -0
- package/lib/clearingHouse.js +12 -5
- package/lib/clearingHouseUser.d.ts +3 -1
- package/lib/clearingHouseUser.js +6 -4
- package/lib/config.js +1 -1
- package/lib/events/eventSubscriber.d.ts +4 -2
- package/lib/events/eventSubscriber.js +16 -9
- package/lib/events/fetchLogs.d.ts +10 -1
- package/lib/events/fetchLogs.js +27 -7
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +6 -2
- package/lib/events/types.d.ts +3 -2
- package/lib/events/types.js +1 -0
- package/lib/examples/makeTradeExample.js +13 -1
- package/lib/idl/clearing_house.json +97 -45
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/amm.d.ts +3 -1
- package/lib/math/amm.js +41 -3
- package/lib/types.d.ts +25 -6
- package/lib/types.js +7 -1
- package/package.json +1 -1
- package/src/addresses/pda.ts +9 -0
- package/src/admin.ts +11 -30
- package/src/clearingHouse.ts +17 -5
- package/src/clearingHouseUser.ts +6 -5
- package/src/config.ts +1 -1
- package/src/events/eventSubscriber.ts +20 -12
- package/src/events/fetchLogs.ts +35 -8
- package/src/events/pollingLogProvider.ts +10 -2
- package/src/events/types.ts +4 -1
- package/src/examples/makeTradeExample.ts +20 -1
- package/src/idl/clearing_house.json +97 -45
- package/src/index.ts +1 -0
- package/src/math/amm.ts +67 -2
- package/src/types.ts +21 -6
package/src/clearingHouseUser.ts
CHANGED
|
@@ -183,7 +183,9 @@ export class ClearingHouseUser {
|
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
185
|
* calculates the market position if the lp position was settled
|
|
186
|
-
* @returns : userPosition
|
|
186
|
+
* @returns : the settled userPosition
|
|
187
|
+
* @returns : the dust base asset amount (ie, < stepsize)
|
|
188
|
+
* @returns : pnl from settle
|
|
187
189
|
*/
|
|
188
190
|
public getSettledLPPosition(marketIndex: BN): [UserPosition, BN, BN] {
|
|
189
191
|
const _position = this.getUserPosition(marketIndex);
|
|
@@ -224,9 +226,6 @@ export class ClearingHouseUser {
|
|
|
224
226
|
|
|
225
227
|
const reaminderPerLP = remainderBaa.mul(AMM_RESERVE_PRECISION).div(nShares);
|
|
226
228
|
|
|
227
|
-
position.baseAssetAmount = position.baseAssetAmount.add(standardizedBaa);
|
|
228
|
-
position.quoteAssetAmount = position.quoteAssetAmount.add(deltaQaa);
|
|
229
|
-
|
|
230
229
|
position.lastNetBaseAssetAmountPerLp =
|
|
231
230
|
market.amm.marketPositionPerLp.baseAssetAmount.sub(reaminderPerLP);
|
|
232
231
|
|
|
@@ -254,7 +253,7 @@ export class ClearingHouseUser {
|
|
|
254
253
|
.mul(deltaBaa.abs())
|
|
255
254
|
.div(position.baseAssetAmount.abs())
|
|
256
255
|
);
|
|
257
|
-
pnl = position.quoteEntryAmount.sub(newQuoteEntry);
|
|
256
|
+
pnl = position.quoteEntryAmount.sub(newQuoteEntry).add(deltaQaa);
|
|
258
257
|
} else {
|
|
259
258
|
newQuoteEntry = deltaQaa.sub(
|
|
260
259
|
deltaQaa.mul(position.baseAssetAmount.abs()).div(deltaBaa.abs())
|
|
@@ -262,6 +261,8 @@ export class ClearingHouseUser {
|
|
|
262
261
|
pnl = position.quoteEntryAmount.add(deltaQaa.sub(newQuoteEntry));
|
|
263
262
|
}
|
|
264
263
|
position.quoteEntryAmount = newQuoteEntry;
|
|
264
|
+
position.baseAssetAmount = position.baseAssetAmount.add(standardizedBaa);
|
|
265
|
+
position.quoteAssetAmount = position.quoteAssetAmount.add(deltaQaa);
|
|
265
266
|
|
|
266
267
|
if (position.baseAssetAmount.gt(ZERO)) {
|
|
267
268
|
position.lastCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
|
package/src/config.ts
CHANGED
|
@@ -28,7 +28,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
28
28
|
devnet: {
|
|
29
29
|
ENV: 'devnet',
|
|
30
30
|
PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
|
|
31
|
-
CLEARING_HOUSE_PROGRAM_ID: '
|
|
31
|
+
CLEARING_HOUSE_PROGRAM_ID: '3v1iEjbSSLSSYyt1pmx4UB5rqJGurmz71RibXF7X6UF3',
|
|
32
32
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
33
33
|
MARKETS: DevnetMarkets,
|
|
34
34
|
BANKS: DevnetBanks,
|
|
@@ -25,6 +25,8 @@ export class EventSubscriber {
|
|
|
25
25
|
private awaitTxResolver = new Map<string, () => void>();
|
|
26
26
|
private logProvider: LogProvider;
|
|
27
27
|
public eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
|
|
28
|
+
private lastSeenSlot: number;
|
|
29
|
+
public lastSeenTxSig: string;
|
|
28
30
|
|
|
29
31
|
public constructor(
|
|
30
32
|
private connection: Connection,
|
|
@@ -62,19 +64,22 @@ export class EventSubscriber {
|
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
public subscribe(): boolean {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
public async subscribe(): Promise<boolean> {
|
|
68
|
+
try {
|
|
69
|
+
if (this.logProvider.isSubscribed()) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
69
72
|
|
|
70
|
-
|
|
73
|
+
this.logProvider.subscribe((txSig, slot, logs) => {
|
|
74
|
+
this.handleTxLogs(txSig, slot, logs);
|
|
75
|
+
}, true);
|
|
76
|
+
|
|
77
|
+
return true;
|
|
78
|
+
} catch (e) {
|
|
71
79
|
console.error('Error fetching previous txs in event subscriber');
|
|
72
80
|
console.error(e);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return this.logProvider.subscribe((txSig, slot, logs) => {
|
|
76
|
-
this.handleTxLogs(txSig, slot, logs);
|
|
77
|
-
});
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
private handleTxLogs(
|
|
@@ -98,11 +103,14 @@ export class EventSubscriber {
|
|
|
98
103
|
this.awaitTxResolver.delete(txSig);
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
if (slot > this.lastSeenSlot) {
|
|
107
|
+
this.lastSeenTxSig = txSig;
|
|
108
|
+
}
|
|
101
109
|
this.txEventCache.add(txSig, wrappedEvents);
|
|
102
110
|
}
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
if (!this.options.untilTx) {
|
|
112
|
+
public async fetchPreviousTx(fetchMax?: boolean): Promise<void> {
|
|
113
|
+
if (!this.options.untilTx && !fetchMax) {
|
|
106
114
|
return;
|
|
107
115
|
}
|
|
108
116
|
|
package/src/events/fetchLogs.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import { Program } from '@project-serum/anchor';
|
|
1
2
|
import {
|
|
2
3
|
Connection,
|
|
3
4
|
Finality,
|
|
4
5
|
PublicKey,
|
|
5
6
|
TransactionSignature,
|
|
6
7
|
} from '@solana/web3.js';
|
|
8
|
+
import { WrappedEvents } from './types';
|
|
7
9
|
|
|
8
10
|
type Log = { txSig: TransactionSignature; slot: number; logs: string[] };
|
|
9
11
|
type FetchLogsResponse = {
|
|
10
12
|
earliestTx: string;
|
|
11
13
|
mostRecentTx: string;
|
|
14
|
+
earliestSlot: number;
|
|
15
|
+
mostRecentSlot: number;
|
|
12
16
|
transactionLogs: Log[];
|
|
13
17
|
};
|
|
14
18
|
|
|
@@ -17,19 +21,21 @@ export async function fetchLogs(
|
|
|
17
21
|
programId: PublicKey,
|
|
18
22
|
finality: Finality,
|
|
19
23
|
beforeTx?: TransactionSignature,
|
|
20
|
-
untilTx?: TransactionSignature
|
|
21
|
-
|
|
24
|
+
untilTx?: TransactionSignature,
|
|
25
|
+
limit?: number
|
|
26
|
+
): Promise<FetchLogsResponse> {
|
|
22
27
|
const signatures = await connection.getSignaturesForAddress(
|
|
23
28
|
programId,
|
|
24
29
|
{
|
|
25
30
|
before: beforeTx,
|
|
26
31
|
until: untilTx,
|
|
32
|
+
limit,
|
|
27
33
|
},
|
|
28
34
|
finality
|
|
29
35
|
);
|
|
30
36
|
|
|
31
37
|
const sortedSignatures = signatures.sort((a, b) =>
|
|
32
|
-
a.slot < b.slot ? -1 : 1
|
|
38
|
+
a.slot === b.slot ? 0 : a.slot < b.slot ? -1 : 1
|
|
33
39
|
);
|
|
34
40
|
|
|
35
41
|
const filteredSignatures = sortedSignatures.filter(
|
|
@@ -61,14 +67,15 @@ export async function fetchLogs(
|
|
|
61
67
|
)
|
|
62
68
|
).flat();
|
|
63
69
|
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
filteredSignatures[filteredSignatures.length - 1].signature;
|
|
70
|
+
const earliest = filteredSignatures[0];
|
|
71
|
+
const mostRecent = filteredSignatures[filteredSignatures.length - 1];
|
|
67
72
|
|
|
68
73
|
return {
|
|
69
74
|
transactionLogs: transactionLogs,
|
|
70
|
-
earliestTx:
|
|
71
|
-
mostRecentTx:
|
|
75
|
+
earliestTx: earliest.signature,
|
|
76
|
+
mostRecentTx: mostRecent.signature,
|
|
77
|
+
earliestSlot: earliest.slot,
|
|
78
|
+
mostRecentSlot: mostRecent.slot,
|
|
72
79
|
};
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -78,3 +85,23 @@ function chunk<T>(array: readonly T[], size: number): T[][] {
|
|
|
78
85
|
.map((_, index) => index * size)
|
|
79
86
|
.map((begin) => array.slice(begin, begin + size));
|
|
80
87
|
}
|
|
88
|
+
|
|
89
|
+
export class LogParser {
|
|
90
|
+
private program: Program;
|
|
91
|
+
|
|
92
|
+
constructor(program: Program) {
|
|
93
|
+
this.program = program;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public parseEventsFromLogs(event: Log): WrappedEvents {
|
|
97
|
+
const records: WrappedEvents = [];
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
this.program._events._eventParser.parseLogs(event.logs, (eventLog) => {
|
|
100
|
+
eventLog.data.txSig = event.txSig;
|
|
101
|
+
eventLog.data.slot = event.slot;
|
|
102
|
+
eventLog.data.eventType = eventLog.name;
|
|
103
|
+
records.push(eventLog.data);
|
|
104
|
+
});
|
|
105
|
+
return records;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -13,6 +13,7 @@ export class PollingLogProvider implements LogProvider {
|
|
|
13
13
|
private intervalId: NodeJS.Timer;
|
|
14
14
|
private mostRecentSeenTx?: TransactionSignature;
|
|
15
15
|
private mutex: number;
|
|
16
|
+
private firstFetch = true;
|
|
16
17
|
|
|
17
18
|
public constructor(
|
|
18
19
|
private connection: Connection,
|
|
@@ -23,7 +24,10 @@ export class PollingLogProvider implements LogProvider {
|
|
|
23
24
|
this.finality = commitment === 'finalized' ? 'finalized' : 'confirmed';
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
public subscribe(
|
|
27
|
+
public subscribe(
|
|
28
|
+
callback: logProviderCallback,
|
|
29
|
+
skipHistory?: boolean
|
|
30
|
+
): boolean {
|
|
27
31
|
if (this.intervalId) {
|
|
28
32
|
return true;
|
|
29
33
|
}
|
|
@@ -40,9 +44,13 @@ export class PollingLogProvider implements LogProvider {
|
|
|
40
44
|
this.programId,
|
|
41
45
|
this.finality,
|
|
42
46
|
undefined,
|
|
43
|
-
this.mostRecentSeenTx
|
|
47
|
+
this.mostRecentSeenTx,
|
|
48
|
+
// If skipping history, only fetch one log back, not the maximum amount available
|
|
49
|
+
skipHistory && this.firstFetch ? 1 : undefined
|
|
44
50
|
);
|
|
45
51
|
|
|
52
|
+
this.firstFetch = false;
|
|
53
|
+
|
|
46
54
|
if (response === undefined) {
|
|
47
55
|
return;
|
|
48
56
|
}
|
package/src/events/types.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
OrderActionRecord,
|
|
9
9
|
OrderRecord,
|
|
10
10
|
SettlePnlRecord,
|
|
11
|
+
LPRecord,
|
|
11
12
|
} from '../index';
|
|
12
13
|
|
|
13
14
|
export type EventSubscriptionOptions = {
|
|
@@ -33,6 +34,7 @@ export const DefaultEventSubscriptionOptions: EventSubscriptionOptions = {
|
|
|
33
34
|
'FundingRateRecord',
|
|
34
35
|
'NewUserRecord',
|
|
35
36
|
'SettlePnlRecord',
|
|
37
|
+
'LPRecord',
|
|
36
38
|
],
|
|
37
39
|
maxEventsPerType: 4096,
|
|
38
40
|
orderBy: 'blockchain',
|
|
@@ -68,6 +70,7 @@ export type EventMap = {
|
|
|
68
70
|
OrderActionRecord: Event<OrderActionRecord>;
|
|
69
71
|
SettlePnlRecord: Event<SettlePnlRecord>;
|
|
70
72
|
NewUserRecord: Event<NewUserRecord>;
|
|
73
|
+
LPRecord: Event<LPRecord>;
|
|
71
74
|
};
|
|
72
75
|
|
|
73
76
|
export type EventType = keyof EventMap;
|
|
@@ -89,7 +92,7 @@ export type logProviderCallback = (
|
|
|
89
92
|
|
|
90
93
|
export interface LogProvider {
|
|
91
94
|
isSubscribed(): boolean;
|
|
92
|
-
subscribe(callback: logProviderCallback): boolean;
|
|
95
|
+
subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
|
|
93
96
|
unsubscribe(): Promise<boolean>;
|
|
94
97
|
}
|
|
95
98
|
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
PositionDirection,
|
|
11
11
|
convertToNumber,
|
|
12
12
|
calculateTradeSlippage,
|
|
13
|
+
BulkAccountLoader,
|
|
14
|
+
Markets,
|
|
13
15
|
MARK_PRICE_PRECISION,
|
|
14
16
|
QUOTE_PRECISION,
|
|
15
17
|
} from '..';
|
|
@@ -27,9 +29,11 @@ export const getTokenAddress = (
|
|
|
27
29
|
);
|
|
28
30
|
};
|
|
29
31
|
|
|
32
|
+
const cluster = 'devnet';
|
|
33
|
+
|
|
30
34
|
const main = async () => {
|
|
31
35
|
// Initialize Drift SDK
|
|
32
|
-
const sdkConfig = initialize({ env:
|
|
36
|
+
const sdkConfig = initialize({ env: cluster });
|
|
33
37
|
|
|
34
38
|
// Set up the Wallet and Provider
|
|
35
39
|
const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
|
|
@@ -63,10 +67,21 @@ const main = async () => {
|
|
|
63
67
|
const clearingHousePublicKey = new PublicKey(
|
|
64
68
|
sdkConfig.CLEARING_HOUSE_PROGRAM_ID
|
|
65
69
|
);
|
|
70
|
+
const bulkAccountLoader = new BulkAccountLoader(
|
|
71
|
+
connection,
|
|
72
|
+
'confirmed',
|
|
73
|
+
1000
|
|
74
|
+
);
|
|
66
75
|
const clearingHouse = new ClearingHouse({
|
|
67
76
|
connection,
|
|
68
77
|
wallet: provider.wallet,
|
|
69
78
|
programID: clearingHousePublicKey,
|
|
79
|
+
marketIndexes: Markets[cluster].map((market) => market.marketIndex),
|
|
80
|
+
bankIndexes: Banks[cluster].map((bank) => bank.bankIndex),
|
|
81
|
+
accountSubscription: {
|
|
82
|
+
type: 'polling',
|
|
83
|
+
accountLoader: bulkAccountLoader,
|
|
84
|
+
},
|
|
70
85
|
});
|
|
71
86
|
await clearingHouse.subscribe();
|
|
72
87
|
|
|
@@ -74,6 +89,10 @@ const main = async () => {
|
|
|
74
89
|
const user = new ClearingHouseUser({
|
|
75
90
|
clearingHouse,
|
|
76
91
|
userAccountPublicKey: await clearingHouse.getUserAccountPublicKey(),
|
|
92
|
+
accountSubscription: {
|
|
93
|
+
type: 'polling',
|
|
94
|
+
accountLoader: bulkAccountLoader,
|
|
95
|
+
},
|
|
77
96
|
});
|
|
78
97
|
|
|
79
98
|
//// Check if clearing house account exists for the current wallet
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"isSigner": false
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
"name": "
|
|
29
|
+
"name": "clearingHouseSigner",
|
|
30
30
|
"isMut": false,
|
|
31
31
|
"isSigner": false
|
|
32
32
|
},
|
|
@@ -71,18 +71,13 @@
|
|
|
71
71
|
"isMut": true,
|
|
72
72
|
"isSigner": false
|
|
73
73
|
},
|
|
74
|
-
{
|
|
75
|
-
"name": "bankVaultAuthority",
|
|
76
|
-
"isMut": false,
|
|
77
|
-
"isSigner": false
|
|
78
|
-
},
|
|
79
74
|
{
|
|
80
75
|
"name": "insuranceFundVault",
|
|
81
76
|
"isMut": true,
|
|
82
77
|
"isSigner": false
|
|
83
78
|
},
|
|
84
79
|
{
|
|
85
|
-
"name": "
|
|
80
|
+
"name": "clearingHouseSigner",
|
|
86
81
|
"isMut": false,
|
|
87
82
|
"isSigner": false
|
|
88
83
|
},
|
|
@@ -316,8 +311,8 @@
|
|
|
316
311
|
"isSigner": false
|
|
317
312
|
},
|
|
318
313
|
{
|
|
319
|
-
"name": "
|
|
320
|
-
"isMut":
|
|
314
|
+
"name": "clearingHouseSigner",
|
|
315
|
+
"isMut": false,
|
|
321
316
|
"isSigner": false
|
|
322
317
|
},
|
|
323
318
|
{
|
|
@@ -974,8 +969,8 @@
|
|
|
974
969
|
"isSigner": false
|
|
975
970
|
},
|
|
976
971
|
{
|
|
977
|
-
"name": "
|
|
978
|
-
"isMut":
|
|
972
|
+
"name": "clearingHouseSigner",
|
|
973
|
+
"isMut": false,
|
|
979
974
|
"isSigner": false
|
|
980
975
|
},
|
|
981
976
|
{
|
|
@@ -1029,8 +1024,8 @@
|
|
|
1029
1024
|
"isSigner": false
|
|
1030
1025
|
},
|
|
1031
1026
|
{
|
|
1032
|
-
"name": "
|
|
1033
|
-
"isMut":
|
|
1027
|
+
"name": "clearingHouseSigner",
|
|
1028
|
+
"isMut": false,
|
|
1034
1029
|
"isSigner": false
|
|
1035
1030
|
},
|
|
1036
1031
|
{
|
|
@@ -1100,8 +1095,8 @@
|
|
|
1100
1095
|
"isSigner": false
|
|
1101
1096
|
},
|
|
1102
1097
|
{
|
|
1103
|
-
"name": "
|
|
1104
|
-
"isMut":
|
|
1098
|
+
"name": "clearingHouseSigner",
|
|
1099
|
+
"isMut": false,
|
|
1105
1100
|
"isSigner": false
|
|
1106
1101
|
},
|
|
1107
1102
|
{
|
|
@@ -1146,7 +1141,7 @@
|
|
|
1146
1141
|
"isSigner": false
|
|
1147
1142
|
},
|
|
1148
1143
|
{
|
|
1149
|
-
"name": "
|
|
1144
|
+
"name": "clearingHouseSigner",
|
|
1150
1145
|
"isMut": false,
|
|
1151
1146
|
"isSigner": false
|
|
1152
1147
|
},
|
|
@@ -1192,7 +1187,7 @@
|
|
|
1192
1187
|
"isSigner": false
|
|
1193
1188
|
},
|
|
1194
1189
|
{
|
|
1195
|
-
"name": "
|
|
1190
|
+
"name": "clearingHouseSigner",
|
|
1196
1191
|
"isMut": false,
|
|
1197
1192
|
"isSigner": false
|
|
1198
1193
|
},
|
|
@@ -2414,8 +2409,8 @@
|
|
|
2414
2409
|
"isSigner": false
|
|
2415
2410
|
},
|
|
2416
2411
|
{
|
|
2417
|
-
"name": "
|
|
2418
|
-
"isMut":
|
|
2412
|
+
"name": "clearingHouseSigner",
|
|
2413
|
+
"isMut": false,
|
|
2419
2414
|
"isSigner": false
|
|
2420
2415
|
},
|
|
2421
2416
|
{
|
|
@@ -2565,6 +2560,11 @@
|
|
|
2565
2560
|
{
|
|
2566
2561
|
"name": "removeInsuranceFundStake",
|
|
2567
2562
|
"accounts": [
|
|
2563
|
+
{
|
|
2564
|
+
"name": "state",
|
|
2565
|
+
"isMut": false,
|
|
2566
|
+
"isSigner": false
|
|
2567
|
+
},
|
|
2568
2568
|
{
|
|
2569
2569
|
"name": "bank",
|
|
2570
2570
|
"isMut": false,
|
|
@@ -2591,8 +2591,8 @@
|
|
|
2591
2591
|
"isSigner": false
|
|
2592
2592
|
},
|
|
2593
2593
|
{
|
|
2594
|
-
"name": "
|
|
2595
|
-
"isMut":
|
|
2594
|
+
"name": "clearingHouseSigner",
|
|
2595
|
+
"isMut": false,
|
|
2596
2596
|
"isSigner": false
|
|
2597
2597
|
},
|
|
2598
2598
|
{
|
|
@@ -2646,26 +2646,10 @@
|
|
|
2646
2646
|
"name": "vault",
|
|
2647
2647
|
"type": "publicKey"
|
|
2648
2648
|
},
|
|
2649
|
-
{
|
|
2650
|
-
"name": "vaultAuthority",
|
|
2651
|
-
"type": "publicKey"
|
|
2652
|
-
},
|
|
2653
|
-
{
|
|
2654
|
-
"name": "vaultAuthorityNonce",
|
|
2655
|
-
"type": "u8"
|
|
2656
|
-
},
|
|
2657
2649
|
{
|
|
2658
2650
|
"name": "insuranceFundVault",
|
|
2659
2651
|
"type": "publicKey"
|
|
2660
2652
|
},
|
|
2661
|
-
{
|
|
2662
|
-
"name": "insuranceFundVaultAuthority",
|
|
2663
|
-
"type": "publicKey"
|
|
2664
|
-
},
|
|
2665
|
-
{
|
|
2666
|
-
"name": "insuranceFundVaultAuthorityNonce",
|
|
2667
|
-
"type": "u8"
|
|
2668
|
-
},
|
|
2669
2653
|
{
|
|
2670
2654
|
"name": "revenuePool",
|
|
2671
2655
|
"type": {
|
|
@@ -2976,14 +2960,6 @@
|
|
|
2976
2960
|
"name": "insuranceVault",
|
|
2977
2961
|
"type": "publicKey"
|
|
2978
2962
|
},
|
|
2979
|
-
{
|
|
2980
|
-
"name": "insuranceVaultAuthority",
|
|
2981
|
-
"type": "publicKey"
|
|
2982
|
-
},
|
|
2983
|
-
{
|
|
2984
|
-
"name": "insuranceVaultNonce",
|
|
2985
|
-
"type": "u8"
|
|
2986
|
-
},
|
|
2987
2963
|
{
|
|
2988
2964
|
"name": "marginRatioInitial",
|
|
2989
2965
|
"type": "u128"
|
|
@@ -3072,6 +3048,14 @@
|
|
|
3072
3048
|
"name": "liquidationMarginBufferRatio",
|
|
3073
3049
|
"type": "u8"
|
|
3074
3050
|
},
|
|
3051
|
+
{
|
|
3052
|
+
"name": "signer",
|
|
3053
|
+
"type": "publicKey"
|
|
3054
|
+
},
|
|
3055
|
+
{
|
|
3056
|
+
"name": "signerNonce",
|
|
3057
|
+
"type": "u8"
|
|
3058
|
+
},
|
|
3075
3059
|
{
|
|
3076
3060
|
"name": "padding0",
|
|
3077
3061
|
"type": "u128"
|
|
@@ -3352,6 +3336,10 @@
|
|
|
3352
3336
|
"name": "quoteAssetAmount",
|
|
3353
3337
|
"type": "i128"
|
|
3354
3338
|
},
|
|
3339
|
+
{
|
|
3340
|
+
"name": "lpShares",
|
|
3341
|
+
"type": "u128"
|
|
3342
|
+
},
|
|
3355
3343
|
{
|
|
3356
3344
|
"name": "userPnl",
|
|
3357
3345
|
"type": "i128"
|
|
@@ -4478,6 +4466,23 @@
|
|
|
4478
4466
|
]
|
|
4479
4467
|
}
|
|
4480
4468
|
},
|
|
4469
|
+
{
|
|
4470
|
+
"name": "LPAction",
|
|
4471
|
+
"type": {
|
|
4472
|
+
"kind": "enum",
|
|
4473
|
+
"variants": [
|
|
4474
|
+
{
|
|
4475
|
+
"name": "AddLiquidity"
|
|
4476
|
+
},
|
|
4477
|
+
{
|
|
4478
|
+
"name": "RemoveLiquidity"
|
|
4479
|
+
},
|
|
4480
|
+
{
|
|
4481
|
+
"name": "SettleLiquidity"
|
|
4482
|
+
}
|
|
4483
|
+
]
|
|
4484
|
+
}
|
|
4485
|
+
},
|
|
4481
4486
|
{
|
|
4482
4487
|
"name": "LiquidationType",
|
|
4483
4488
|
"type": {
|
|
@@ -5173,6 +5178,53 @@
|
|
|
5173
5178
|
}
|
|
5174
5179
|
]
|
|
5175
5180
|
},
|
|
5181
|
+
{
|
|
5182
|
+
"name": "LPRecord",
|
|
5183
|
+
"fields": [
|
|
5184
|
+
{
|
|
5185
|
+
"name": "ts",
|
|
5186
|
+
"type": "i64",
|
|
5187
|
+
"index": false
|
|
5188
|
+
},
|
|
5189
|
+
{
|
|
5190
|
+
"name": "user",
|
|
5191
|
+
"type": "publicKey",
|
|
5192
|
+
"index": false
|
|
5193
|
+
},
|
|
5194
|
+
{
|
|
5195
|
+
"name": "action",
|
|
5196
|
+
"type": {
|
|
5197
|
+
"defined": "LPAction"
|
|
5198
|
+
},
|
|
5199
|
+
"index": false
|
|
5200
|
+
},
|
|
5201
|
+
{
|
|
5202
|
+
"name": "nShares",
|
|
5203
|
+
"type": "u128",
|
|
5204
|
+
"index": false
|
|
5205
|
+
},
|
|
5206
|
+
{
|
|
5207
|
+
"name": "marketIndex",
|
|
5208
|
+
"type": "u64",
|
|
5209
|
+
"index": false
|
|
5210
|
+
},
|
|
5211
|
+
{
|
|
5212
|
+
"name": "deltaBaseAssetAmount",
|
|
5213
|
+
"type": "i128",
|
|
5214
|
+
"index": false
|
|
5215
|
+
},
|
|
5216
|
+
{
|
|
5217
|
+
"name": "deltaQuoteAssetAmount",
|
|
5218
|
+
"type": "i128",
|
|
5219
|
+
"index": false
|
|
5220
|
+
},
|
|
5221
|
+
{
|
|
5222
|
+
"name": "pnl",
|
|
5223
|
+
"type": "i128",
|
|
5224
|
+
"index": false
|
|
5225
|
+
}
|
|
5226
|
+
]
|
|
5227
|
+
},
|
|
5176
5228
|
{
|
|
5177
5229
|
"name": "LiquidationRecord",
|
|
5178
5230
|
"fields": [
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ export * from './factory/oracleClient';
|
|
|
30
30
|
export * from './factory/bigNum';
|
|
31
31
|
export * from './events/types';
|
|
32
32
|
export * from './events/eventSubscriber';
|
|
33
|
+
export * from './events/fetchLogs';
|
|
33
34
|
export * from './math/auction';
|
|
34
35
|
export * from './math/conversion';
|
|
35
36
|
export * from './math/funding';
|
package/src/math/amm.ts
CHANGED
|
@@ -308,6 +308,51 @@ export function calculateAmmReservesAfterSwap(
|
|
|
308
308
|
return [newQuoteAssetReserve, newBaseAssetReserve];
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
export function calculateMarketOpenBidAsk(
|
|
312
|
+
baseAssetReserve: BN,
|
|
313
|
+
minBaseAssetReserve: BN,
|
|
314
|
+
maxBaseAssetReserve: BN
|
|
315
|
+
): [BN, BN] {
|
|
316
|
+
// open orders
|
|
317
|
+
let openAsks;
|
|
318
|
+
if (maxBaseAssetReserve > baseAssetReserve) {
|
|
319
|
+
openAsks = maxBaseAssetReserve.sub(baseAssetReserve).mul(new BN(-1));
|
|
320
|
+
} else {
|
|
321
|
+
openAsks = ZERO;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
let openBids;
|
|
325
|
+
if (minBaseAssetReserve < baseAssetReserve) {
|
|
326
|
+
openBids = baseAssetReserve.sub(minBaseAssetReserve);
|
|
327
|
+
} else {
|
|
328
|
+
openBids = ZERO;
|
|
329
|
+
}
|
|
330
|
+
return [openBids, openAsks];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export function calculateInventoryScale(
|
|
334
|
+
netBaseAssetAmount: BN,
|
|
335
|
+
baseAssetReserve: BN,
|
|
336
|
+
minBaseAssetReserve: BN,
|
|
337
|
+
maxBaseAssetReserve: BN
|
|
338
|
+
): number {
|
|
339
|
+
// inventory skew
|
|
340
|
+
const [openBids, openAsks] = calculateMarketOpenBidAsk(
|
|
341
|
+
baseAssetReserve,
|
|
342
|
+
minBaseAssetReserve,
|
|
343
|
+
maxBaseAssetReserve
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
const totalLiquidity = BN.max(openBids.abs().add(openAsks.abs()), new BN(1));
|
|
347
|
+
const inventoryScale =
|
|
348
|
+
BN.min(netBaseAssetAmount.abs(), totalLiquidity)
|
|
349
|
+
.mul(BID_ASK_SPREAD_PRECISION.mul(new BN(5)))
|
|
350
|
+
.div(totalLiquidity)
|
|
351
|
+
.toNumber() / BID_ASK_SPREAD_PRECISION.toNumber();
|
|
352
|
+
|
|
353
|
+
return inventoryScale;
|
|
354
|
+
}
|
|
355
|
+
|
|
311
356
|
export function calculateEffectiveLeverage(
|
|
312
357
|
baseSpread: number,
|
|
313
358
|
quoteAssetReserve: BN,
|
|
@@ -353,7 +398,10 @@ export function calculateSpreadBN(
|
|
|
353
398
|
pegMultiplier: BN,
|
|
354
399
|
netBaseAssetAmount: BN,
|
|
355
400
|
markPrice: BN,
|
|
356
|
-
totalFeeMinusDistributions: BN
|
|
401
|
+
totalFeeMinusDistributions: BN,
|
|
402
|
+
baseAssetReserve: BN,
|
|
403
|
+
minBaseAssetReserve: BN,
|
|
404
|
+
maxBaseAssetReserve: BN
|
|
357
405
|
): [number, number] {
|
|
358
406
|
let longSpread = baseSpread / 2;
|
|
359
407
|
let shortSpread = baseSpread / 2;
|
|
@@ -374,6 +422,20 @@ export function calculateSpreadBN(
|
|
|
374
422
|
|
|
375
423
|
const MAX_INVENTORY_SKEW = 5;
|
|
376
424
|
|
|
425
|
+
const inventoryScale = calculateInventoryScale(
|
|
426
|
+
netBaseAssetAmount,
|
|
427
|
+
baseAssetReserve,
|
|
428
|
+
minBaseAssetReserve,
|
|
429
|
+
maxBaseAssetReserve
|
|
430
|
+
);
|
|
431
|
+
const inventorySpreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + inventoryScale);
|
|
432
|
+
|
|
433
|
+
if (netBaseAssetAmount.gt(ZERO)) {
|
|
434
|
+
longSpread *= inventorySpreadScale;
|
|
435
|
+
} else if (netBaseAssetAmount.lt(ZERO)) {
|
|
436
|
+
shortSpread *= inventorySpreadScale;
|
|
437
|
+
}
|
|
438
|
+
|
|
377
439
|
const effectiveLeverage = calculateEffectiveLeverage(
|
|
378
440
|
baseSpread,
|
|
379
441
|
quoteAssetReserve,
|
|
@@ -447,7 +509,10 @@ export function calculateSpread(
|
|
|
447
509
|
amm.pegMultiplier,
|
|
448
510
|
amm.netBaseAssetAmount,
|
|
449
511
|
markPrice,
|
|
450
|
-
amm.totalFeeMinusDistributions
|
|
512
|
+
amm.totalFeeMinusDistributions,
|
|
513
|
+
amm.baseAssetReserve,
|
|
514
|
+
amm.minBaseAssetReserve,
|
|
515
|
+
amm.maxBaseAssetReserve
|
|
451
516
|
);
|
|
452
517
|
|
|
453
518
|
let spread: number;
|