@drift-labs/sdk 0.1.23-master.0 → 0.1.23-master.4
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/bulkAccountLoader.js +4 -13
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +4 -4
- package/lib/accounts/webSocketAccountSubscriber.js +2 -2
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +2 -2
- package/lib/admin.js +7 -7
- package/lib/clearingHouse.js +21 -22
- package/lib/clearingHouseUser.js +21 -21
- package/lib/examples/makeTradeExample.js +6 -6
- package/lib/idl/clearing_house.json +68 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/math/amm.js +12 -12
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.js +1 -1
- package/lib/math/market.js +2 -2
- package/lib/math/orders.d.ts +1 -0
- package/lib/math/orders.js +26 -4
- package/lib/math/position.js +4 -3
- package/lib/math/trade.js +21 -17
- package/lib/orders.d.ts +3 -1
- package/lib/orders.js +47 -19
- package/lib/pythClient.js +1 -1
- package/lib/tx/retryTxSender.d.ts +19 -0
- package/lib/tx/retryTxSender.js +153 -0
- package/lib/tx/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/accounts/bulkAccountLoader.ts +5 -13
- package/src/clearingHouse.ts +3 -3
- package/src/idl/clearing_house.json +68 -0
- package/src/index.ts +2 -0
- package/src/math/orders.ts +33 -0
- package/src/math/position.ts +3 -2
- package/src/math/trade.ts +8 -3
- package/src/orders.ts +56 -3
- package/src/tx/retryTxSender.ts +196 -0
- package/src/tx/types.ts +3 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { TxSender } from './types';
|
|
2
|
+
import {
|
|
3
|
+
Commitment,
|
|
4
|
+
ConfirmOptions,
|
|
5
|
+
Context,
|
|
6
|
+
RpcResponseAndContext,
|
|
7
|
+
Signer,
|
|
8
|
+
SignatureResult,
|
|
9
|
+
Transaction,
|
|
10
|
+
TransactionSignature,
|
|
11
|
+
} from '@solana/web3.js';
|
|
12
|
+
import { Provider } from '@project-serum/anchor';
|
|
13
|
+
import assert from 'assert';
|
|
14
|
+
import bs58 from 'bs58';
|
|
15
|
+
|
|
16
|
+
const DEFAULT_TIMEOUT = 35000;
|
|
17
|
+
const DEFAULT_RETRY = 8000;
|
|
18
|
+
|
|
19
|
+
type ResolveReference = {
|
|
20
|
+
resolve?: () => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export class RetryTxSender implements TxSender {
|
|
24
|
+
provider: Provider;
|
|
25
|
+
timeout: number;
|
|
26
|
+
retrySleep: number;
|
|
27
|
+
|
|
28
|
+
public constructor(
|
|
29
|
+
provider: Provider,
|
|
30
|
+
timeout?: number,
|
|
31
|
+
retrySleep?: number
|
|
32
|
+
) {
|
|
33
|
+
this.provider = provider;
|
|
34
|
+
this.timeout = timeout ?? DEFAULT_TIMEOUT;
|
|
35
|
+
this.retrySleep = retrySleep ?? DEFAULT_RETRY;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async send(
|
|
39
|
+
tx: Transaction,
|
|
40
|
+
additionalSigners?: Array<Signer>,
|
|
41
|
+
opts?: ConfirmOptions
|
|
42
|
+
): Promise<TransactionSignature> {
|
|
43
|
+
if (additionalSigners === undefined) {
|
|
44
|
+
additionalSigners = [];
|
|
45
|
+
}
|
|
46
|
+
if (opts === undefined) {
|
|
47
|
+
opts = this.provider.opts;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
await this.prepareTx(tx, additionalSigners, opts);
|
|
51
|
+
|
|
52
|
+
const rawTransaction = tx.serialize();
|
|
53
|
+
const startTime = this.getTimestamp();
|
|
54
|
+
|
|
55
|
+
const txid: TransactionSignature =
|
|
56
|
+
await this.provider.connection.sendRawTransaction(rawTransaction, opts);
|
|
57
|
+
|
|
58
|
+
let done = false;
|
|
59
|
+
const resolveReference: ResolveReference = {
|
|
60
|
+
resolve: undefined,
|
|
61
|
+
};
|
|
62
|
+
const stopWaiting = () => {
|
|
63
|
+
done = true;
|
|
64
|
+
if (resolveReference.resolve) {
|
|
65
|
+
resolveReference.resolve();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
(async () => {
|
|
70
|
+
while (!done && this.getTimestamp() - startTime < this.timeout) {
|
|
71
|
+
await this.sleep(resolveReference);
|
|
72
|
+
if (!done) {
|
|
73
|
+
this.provider.connection
|
|
74
|
+
.sendRawTransaction(rawTransaction, opts)
|
|
75
|
+
.catch((e) => {
|
|
76
|
+
console.error(e);
|
|
77
|
+
stopWaiting();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await this.confirmTransaction(txid, opts.commitment);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.error(e);
|
|
87
|
+
throw e;
|
|
88
|
+
} finally {
|
|
89
|
+
stopWaiting();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return txid;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async prepareTx(
|
|
96
|
+
tx: Transaction,
|
|
97
|
+
additionalSigners: Array<Signer>,
|
|
98
|
+
opts: ConfirmOptions
|
|
99
|
+
): Promise<Transaction> {
|
|
100
|
+
tx.feePayer = this.provider.wallet.publicKey;
|
|
101
|
+
tx.recentBlockhash = (
|
|
102
|
+
await this.provider.connection.getRecentBlockhash(
|
|
103
|
+
opts.preflightCommitment
|
|
104
|
+
)
|
|
105
|
+
).blockhash;
|
|
106
|
+
|
|
107
|
+
await this.provider.wallet.signTransaction(tx);
|
|
108
|
+
additionalSigners
|
|
109
|
+
.filter((s): s is Signer => s !== undefined)
|
|
110
|
+
.forEach((kp) => {
|
|
111
|
+
tx.partialSign(kp);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return tx;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async confirmTransaction(
|
|
118
|
+
signature: TransactionSignature,
|
|
119
|
+
commitment?: Commitment
|
|
120
|
+
): Promise<RpcResponseAndContext<SignatureResult>> {
|
|
121
|
+
let decodedSignature;
|
|
122
|
+
try {
|
|
123
|
+
decodedSignature = bs58.decode(signature);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
throw new Error('signature must be base58 encoded: ' + signature);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
assert(decodedSignature.length === 64, 'signature has invalid length');
|
|
129
|
+
|
|
130
|
+
const start = Date.now();
|
|
131
|
+
const subscriptionCommitment = commitment || this.provider.opts.commitment;
|
|
132
|
+
|
|
133
|
+
let subscriptionId;
|
|
134
|
+
let response: RpcResponseAndContext<SignatureResult> | null = null;
|
|
135
|
+
const confirmPromise = new Promise((resolve, reject) => {
|
|
136
|
+
try {
|
|
137
|
+
subscriptionId = this.provider.connection.onSignature(
|
|
138
|
+
signature,
|
|
139
|
+
(result: SignatureResult, context: Context) => {
|
|
140
|
+
subscriptionId = undefined;
|
|
141
|
+
response = {
|
|
142
|
+
context,
|
|
143
|
+
value: result,
|
|
144
|
+
};
|
|
145
|
+
resolve(null);
|
|
146
|
+
},
|
|
147
|
+
subscriptionCommitment
|
|
148
|
+
);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
reject(err);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
await this.promiseTimeout(confirmPromise, this.timeout);
|
|
156
|
+
} finally {
|
|
157
|
+
if (subscriptionId) {
|
|
158
|
+
this.provider.connection.removeSignatureListener(subscriptionId);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (response === null) {
|
|
163
|
+
const duration = (Date.now() - start) / 1000;
|
|
164
|
+
throw new Error(
|
|
165
|
+
`Transaction was not confirmed in ${duration.toFixed(
|
|
166
|
+
2
|
|
167
|
+
)} seconds. It is unknown if it succeeded or failed. Check signature ${signature} using the Solana Explorer or CLI tools.`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return response;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
getTimestamp(): number {
|
|
175
|
+
return new Date().getTime();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async sleep(reference: ResolveReference): Promise<void> {
|
|
179
|
+
return new Promise((resolve) => {
|
|
180
|
+
reference.resolve = resolve;
|
|
181
|
+
setTimeout(resolve, this.retrySleep);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
promiseTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T | null> {
|
|
186
|
+
let timeoutId: ReturnType<typeof setTimeout>;
|
|
187
|
+
const timeoutPromise: Promise<null> = new Promise((resolve) => {
|
|
188
|
+
timeoutId = setTimeout(() => resolve(null), timeoutMs);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return Promise.race([promise, timeoutPromise]).then((result: T | null) => {
|
|
192
|
+
clearTimeout(timeoutId);
|
|
193
|
+
return result;
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
package/src/tx/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Provider } from '@project-serum/anchor';
|
|
1
2
|
import {
|
|
2
3
|
ConfirmOptions,
|
|
3
4
|
Signer,
|
|
@@ -6,6 +7,8 @@ import {
|
|
|
6
7
|
} from '@solana/web3.js';
|
|
7
8
|
|
|
8
9
|
export interface TxSender {
|
|
10
|
+
provider: Provider;
|
|
11
|
+
|
|
9
12
|
send(
|
|
10
13
|
tx: Transaction,
|
|
11
14
|
additionalSigners?: Array<Signer>,
|