@depthhq/sdk 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/account/confirm.d.ts +5 -0
  2. package/dist/account/discovery.d.ts +49 -0
  3. package/dist/account/funding.d.ts +86 -0
  4. package/dist/account/funding.js +498 -0
  5. package/dist/account/release.d.ts +8 -0
  6. package/dist/account/token.d.ts +5 -0
  7. package/dist/app/app.d.ts +50 -0
  8. package/dist/catalog/catalog.d.ts +50 -0
  9. package/dist/catalog/data.d.ts +30 -0
  10. package/dist/catalog/data.js +169 -0
  11. package/dist/chain/arcium.d.ts +10 -0
  12. package/dist/chain/connection.d.ts +4 -0
  13. package/dist/chain/environment.d.ts +20 -0
  14. package/dist/chain/manifest.d.ts +36 -0
  15. package/dist/chain/network.d.ts +18 -0
  16. package/dist/chain/provider.d.ts +6 -0
  17. package/dist/chain/random.d.ts +1 -0
  18. package/dist/chain/settlement.d.ts +15 -0
  19. package/dist/chain/transaction.d.ts +12 -0
  20. package/dist/client/client.d.ts +137 -0
  21. package/dist/client/types.d.ts +105 -0
  22. package/dist/history/history.d.ts +26 -0
  23. package/dist/history/replay.d.ts +13 -0
  24. package/dist/index.d.ts +34 -0
  25. package/dist/index.js +47534 -0
  26. package/dist/operation/error.d.ts +10 -0
  27. package/dist/operation/operation.d.ts +49 -0
  28. package/dist/operator.d.ts +6 -0
  29. package/dist/operator.js +25383 -0
  30. package/dist/position/pnl.d.ts +14 -0
  31. package/dist/recovery/coordinator.d.ts +17 -0
  32. package/dist/recovery/recovery.d.ts +26 -0
  33. package/dist/recovery/recovery.js +1420 -0
  34. package/dist/recovery/shares.d.ts +26 -0
  35. package/dist/recovery/winddown.d.ts +38 -0
  36. package/dist/recovery/witness.d.ts +16 -0
  37. package/dist/trade/amount.d.ts +2 -0
  38. package/dist/trade/flow.d.ts +21 -0
  39. package/dist/trade/input.d.ts +3 -0
  40. package/dist/trade/terms.d.ts +3 -0
  41. package/dist/view/view.d.ts +59 -0
  42. package/dist/view/view.js +26681 -0
  43. package/package.json +52 -3
  44. package/README.md +0 -3
@@ -0,0 +1,5 @@
1
+ export type ConfirmOptions = {
2
+ timeoutMs?: number;
3
+ pollMs?: number;
4
+ };
5
+ export declare function confirmReceipt<T>(id: string, status: () => Promise<T>, advance: (current: T) => Promise<boolean>, options?: ConfirmOptions): Promise<T>;
@@ -0,0 +1,49 @@
1
+ import * as anchor from "@anchor-lang/core";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ import { type ReceiptTransaction } from "../chain/transaction.js";
4
+ export type PendingKind = "deposit" | "allocation" | "release" | "withdrawal" | "trade" | "risk";
5
+ export type PendingItem = {
6
+ id: PublicKey;
7
+ kind: PendingKind;
8
+ status: string;
9
+ nonce: bigint;
10
+ };
11
+ export type PendingPage = {
12
+ items: PendingItem[];
13
+ nextCursor?: string;
14
+ };
15
+ export type ReceiptDetail = ReceiptTransaction & {
16
+ amount?: bigint;
17
+ };
18
+ export type UnpairedAllocation = {
19
+ id: PublicKey;
20
+ nonce: bigint;
21
+ amount: bigint;
22
+ status: string;
23
+ orderId: PublicKey;
24
+ };
25
+ export declare class FundingDiscovery {
26
+ private readonly program;
27
+ private readonly connection;
28
+ private readonly owner;
29
+ constructor(program: anchor.Program, connection: Connection, owner: PublicKey);
30
+ transaction(item: PendingItem): Promise<ReceiptDetail>;
31
+ detail(item: PendingItem): Promise<ReceiptDetail>;
32
+ unpairedAllocations(options?: {
33
+ cursor?: string;
34
+ limit?: number;
35
+ }): Promise<{
36
+ items: UnpairedAllocation[];
37
+ nextCursor: string | null;
38
+ }>;
39
+ pending(options?: {
40
+ cursor?: string;
41
+ limit?: number;
42
+ }): Promise<PendingPage>;
43
+ history(options?: {
44
+ cursor?: string;
45
+ limit?: number;
46
+ }): Promise<PendingPage>;
47
+ private list;
48
+ private project;
49
+ }
@@ -0,0 +1,86 @@
1
+ import * as anchor from "@anchor-lang/core";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ import type { ConfirmOptions } from "./confirm.js";
4
+ type Queue = (name: string, offset: anchor.BN) => Promise<Record<string, PublicKey>>;
5
+ export declare class FundingClient {
6
+ readonly program: anchor.Program;
7
+ readonly connection: Connection;
8
+ readonly owner: PublicKey;
9
+ private readonly queue;
10
+ readonly market: PublicKey;
11
+ readonly protocol: PublicKey;
12
+ readonly balance: PublicKey;
13
+ readonly marketAccount: PublicKey;
14
+ constructor(program: anchor.Program, connection: Connection, owner: PublicKey, queue: Queue);
15
+ private assertOwner;
16
+ read<T>(name: string, address: PublicKey): Promise<T | undefined>;
17
+ private recoveryKey;
18
+ cancelOpenBalance(): Promise<string>;
19
+ cancelOpenMarket(): Promise<string>;
20
+ cancelDeposit(id: PublicKey): Promise<string>;
21
+ cancelTransfer(id: PublicKey, toMarket: boolean, phase: "debiting" | "crediting"): Promise<string>;
22
+ openBalance(): Promise<{
23
+ address: PublicKey;
24
+ signature: string;
25
+ }>;
26
+ openMarket(): Promise<{
27
+ address: PublicKey;
28
+ signature: string;
29
+ }>;
30
+ deposit(source: PublicKey, amount: bigint, clientNonce: bigint): Promise<DepositHandle>;
31
+ depositHandle(depositNonce: bigint): DepositHandle;
32
+ withdraw(destination: PublicKey, amount: bigint, clientNonce: bigint): Promise<WithdrawalHandle>;
33
+ withdrawalHandle(clientNonce: bigint): WithdrawalHandle;
34
+ cancelWithdrawal(receipt: PublicKey): Promise<string>;
35
+ allocate(amount: bigint, clientNonce: bigint): Promise<TransferHandle>;
36
+ release(amount: bigint, clientNonce: bigint): Promise<TransferHandle>;
37
+ transferHandle(transferNonce: bigint): TransferHandle;
38
+ private beginTransfer;
39
+ settleTransfer(id: PublicKey, toMarket: boolean): Promise<string>;
40
+ refundTransfer(id: PublicKey, destination: PublicKey): Promise<string>;
41
+ creditDeposit(id: PublicKey): Promise<string>;
42
+ refundDeposit(id: PublicKey, destination: PublicKey): Promise<string>;
43
+ }
44
+ export declare class DepositHandle {
45
+ readonly client: FundingClient;
46
+ readonly nonce: bigint;
47
+ readonly signature?: string | undefined;
48
+ readonly id: PublicKey;
49
+ constructor(client: FundingClient, nonce: bigint, signature?: string | undefined);
50
+ status(): Promise<"pending" | "crediting" | "credited" | "refunded">;
51
+ confirm(options?: ConfirmOptions): Promise<"credited">;
52
+ credit(): Promise<string>;
53
+ cancel(): Promise<string>;
54
+ refund(destination: PublicKey): Promise<string>;
55
+ }
56
+ export declare class TransferHandle {
57
+ readonly client: FundingClient;
58
+ readonly nonce: bigint;
59
+ readonly signature?: string | undefined;
60
+ readonly id: PublicKey;
61
+ constructor(client: FundingClient, nonce: bigint, signature?: string | undefined);
62
+ status(): Promise<{
63
+ state: string;
64
+ toMarket: boolean;
65
+ amount: bigint;
66
+ }>;
67
+ confirm(options?: ConfirmOptions): Promise<{
68
+ state: "settled";
69
+ toMarket: boolean;
70
+ amount: bigint;
71
+ }>;
72
+ settle(): Promise<string>;
73
+ cancel(): Promise<string>;
74
+ refund(destination: PublicKey): Promise<string>;
75
+ }
76
+ export declare class WithdrawalHandle {
77
+ readonly client: FundingClient;
78
+ readonly nonce: bigint;
79
+ readonly signature?: string | undefined;
80
+ readonly id: PublicKey;
81
+ constructor(client: FundingClient, nonce: bigint, signature?: string | undefined);
82
+ status(): Promise<"queued" | "paid" | "rejected" | "cancelled">;
83
+ confirm(options?: ConfirmOptions): Promise<"paid">;
84
+ cancel(): Promise<string>;
85
+ }
86
+ export {};
@@ -0,0 +1,498 @@
1
+ // src/account/funding.ts
2
+ import * as anchor2 from "@anchor-lang/core";
3
+ import {
4
+ balanceAddress,
5
+ depositAddress,
6
+ marketAccountAddress,
7
+ marketAddress,
8
+ protocolAddress,
9
+ recoveryConfigAddress,
10
+ transferAddress,
11
+ withdrawalAddress
12
+ } from "@depthhq/bindings";
13
+
14
+ // src/chain/random.ts
15
+ function randomBytes(length) {
16
+ return crypto.getRandomValues(new Uint8Array(length));
17
+ }
18
+
19
+ // src/operation/error.ts
20
+ class DepthError extends Error {
21
+ code;
22
+ stage;
23
+ retryable;
24
+ nextAction;
25
+ operationId;
26
+ constructor(code, stage, message, retryable, nextAction, operationId, options) {
27
+ super(message, options);
28
+ this.code = code;
29
+ this.stage = stage;
30
+ this.retryable = retryable;
31
+ this.nextAction = nextAction;
32
+ this.operationId = operationId;
33
+ this.name = "DepthError";
34
+ }
35
+ }
36
+ function submissionError(operationId, cause) {
37
+ throw new DepthError("SUBMISSION_UNCONFIRMED", "submission", "Submission was not confirmed; reconcile the saved operation before retrying", true, "Read the operation using the saved client nonce; do not create a new nonce", operationId, { cause });
38
+ }
39
+
40
+ // src/account/confirm.ts
41
+ async function confirmReceipt(id, status, advance, options = {}) {
42
+ const timeoutMs = options.timeoutMs ?? 60000;
43
+ const pollMs = options.pollMs ?? 1000;
44
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 0 || !Number.isSafeInteger(pollMs) || pollMs < 100)
45
+ throw new RangeError("Invalid confirmation timing");
46
+ const deadline = Date.now() + timeoutMs;
47
+ for (;; ) {
48
+ const current = await status();
49
+ if (await advance(current))
50
+ return current;
51
+ if (Date.now() >= deadline)
52
+ throw new DepthError("RECEIPT_PENDING", "confirmation", "The operation is still pending", true, "Restore this receipt with its nonce and continue confirmation", id);
53
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollMs, deadline - Date.now())));
54
+ }
55
+ }
56
+
57
+ // src/trade/input.ts
58
+ import * as anchor from "@anchor-lang/core";
59
+ function u64(value, name) {
60
+ if (typeof value !== "bigint" || value < 0n || value > (1n << 64n) - 1n) {
61
+ throw new RangeError(`${name} must be an unsigned 64-bit bigint`);
62
+ }
63
+ return new anchor.BN(value.toString());
64
+ }
65
+
66
+ // src/account/funding.ts
67
+ function offset() {
68
+ return new anchor2.BN(randomBytes(8), "le");
69
+ }
70
+ function status(value) {
71
+ return Object.keys(value)[0] ?? "unknown";
72
+ }
73
+
74
+ class FundingClient {
75
+ program;
76
+ connection;
77
+ owner;
78
+ queue;
79
+ market;
80
+ protocol;
81
+ balance;
82
+ marketAccount;
83
+ constructor(program, connection, owner, queue) {
84
+ this.program = program;
85
+ this.connection = connection;
86
+ this.owner = owner;
87
+ this.queue = queue;
88
+ this.market = marketAddress(program.programId);
89
+ this.protocol = protocolAddress(program.programId);
90
+ this.balance = balanceAddress(owner, program.programId);
91
+ this.marketAccount = marketAccountAddress(owner, program.programId);
92
+ }
93
+ assertOwner() {
94
+ const wallet = this.program.provider.wallet;
95
+ if (!wallet.publicKey.equals(this.owner)) {
96
+ throw new Error("Only the account owner can move collateral");
97
+ }
98
+ }
99
+ async read(name, address) {
100
+ const info = await this.connection.getAccountInfo(address, "confirmed");
101
+ if (!info)
102
+ return;
103
+ if (!info.owner.equals(this.program.programId)) {
104
+ throw new Error(`${name} is not owned by Depth`);
105
+ }
106
+ return this.program.coder.accounts.decode(name[0].toLowerCase() + name.slice(1), info.data);
107
+ }
108
+ async recoveryKey() {
109
+ const config = await this.read("RecoveryConfig", recoveryConfigAddress(this.program.programId));
110
+ if (!config || !config.market.equals(this.market) || config.recoveryKey.length !== 32) {
111
+ throw new Error("Market recovery configuration is unavailable");
112
+ }
113
+ return config.recoveryKey;
114
+ }
115
+ async cancelOpenBalance() {
116
+ this.assertOwner();
117
+ return this.program.methods.cancelOpenBalance().accountsPartial({ owner: this.owner, balance: this.balance }).rpc({ commitment: "confirmed" });
118
+ }
119
+ async cancelOpenMarket() {
120
+ this.assertOwner();
121
+ return this.program.methods.cancelOpenMarket().accountsPartial({ owner: this.owner, marketAccount: this.marketAccount }).rpc({ commitment: "confirmed" });
122
+ }
123
+ async cancelDeposit(id) {
124
+ this.assertOwner();
125
+ return this.program.methods.cancelCredit().accountsPartial({
126
+ owner: this.owner,
127
+ balance: this.balance,
128
+ receipt: id
129
+ }).rpc({ commitment: "confirmed" });
130
+ }
131
+ async cancelTransfer(id, toMarket, phase) {
132
+ this.assertOwner();
133
+ const free = phase === "debiting" ? toMarket : !toMarket;
134
+ const method = phase === "debiting" ? free ? this.program.methods.cancelFreeDebit : this.program.methods.cancelMarketDebit : free ? this.program.methods.cancelFreeCredit : this.program.methods.cancelMarketCredit;
135
+ return method().accountsPartial({
136
+ owner: this.owner,
137
+ transfer: id,
138
+ ...free ? { balance: this.balance } : { marketAccount: this.marketAccount }
139
+ }).rpc({ commitment: "confirmed" });
140
+ }
141
+ async openBalance() {
142
+ this.assertOwner();
143
+ if (await this.read("BalanceAccount", this.balance)) {
144
+ throw new Error("Balance account already exists");
145
+ }
146
+ const computationOffset = offset();
147
+ const signature = await this.program.methods.openBalance(computationOffset, await this.recoveryKey()).accountsPartial({
148
+ ...await this.queue("open_balance", computationOffset),
149
+ payer: this.owner,
150
+ protocol: this.protocol,
151
+ balance: this.balance
152
+ }).rpc({ commitment: "confirmed" });
153
+ return { address: this.balance, signature };
154
+ }
155
+ async openMarket() {
156
+ this.assertOwner();
157
+ if (await this.read("MarketAccount", this.marketAccount)) {
158
+ throw new Error("Market account already exists");
159
+ }
160
+ const computationOffset = offset();
161
+ const signature = await this.program.methods.openMarketAccount(computationOffset, await this.recoveryKey()).accountsPartial({
162
+ ...await this.queue("open_market", computationOffset),
163
+ payer: this.owner,
164
+ protocol: this.protocol,
165
+ market: this.market,
166
+ recoveryConfig: recoveryConfigAddress(this.program.programId),
167
+ marketAccount: this.marketAccount
168
+ }).rpc({ commitment: "confirmed" });
169
+ return { address: this.marketAccount, signature };
170
+ }
171
+ async deposit(source, amount, clientNonce) {
172
+ this.assertOwner();
173
+ u64(amount, "amount");
174
+ if (amount === 0n)
175
+ throw new RangeError("Deposit amount must be positive");
176
+ const depositNonce = clientNonce;
177
+ u64(clientNonce, "clientNonce");
178
+ const receipt = depositAddress(this.owner, depositNonce, this.program.programId);
179
+ const existing = await this.read("DepositReceipt", receipt);
180
+ if (existing) {
181
+ if (!existing.owner.equals(this.owner) || BigInt(existing.amount.toString()) !== amount) {
182
+ throw new Error("Deposit nonce is already bound to another request");
183
+ }
184
+ return this.depositHandle(clientNonce);
185
+ }
186
+ const protocol = await this.read("Protocol", this.protocol);
187
+ if (!protocol)
188
+ throw new Error("Protocol is unavailable");
189
+ const signature = await this.program.methods.deposit(u64(depositNonce, "nonce"), u64(amount, "amount")).accountsPartial({
190
+ owner: this.owner,
191
+ protocol: this.protocol,
192
+ settlementMint: protocol.settlementMint,
193
+ source,
194
+ vault: protocol.vault,
195
+ receipt
196
+ }).rpc({ commitment: "confirmed" }).catch((error) => submissionError(receipt.toBase58(), error));
197
+ return new DepositHandle(this, depositNonce, signature);
198
+ }
199
+ depositHandle(depositNonce) {
200
+ u64(depositNonce, "nonce");
201
+ return new DepositHandle(this, depositNonce);
202
+ }
203
+ async withdraw(destination, amount, clientNonce) {
204
+ this.assertOwner();
205
+ u64(amount, "amount");
206
+ u64(clientNonce, "clientNonce");
207
+ if (amount === 0n)
208
+ throw new RangeError("Withdrawal amount must be positive");
209
+ const handle = this.withdrawalHandle(clientNonce);
210
+ const existing = await this.read("WithdrawalReceipt", handle.id);
211
+ if (existing) {
212
+ if (!existing.owner.equals(this.owner) || !existing.destination.equals(destination) || BigInt(existing.amount.toString()) !== amount) {
213
+ throw new Error("Withdrawal nonce is already bound to another request");
214
+ }
215
+ return handle;
216
+ }
217
+ const computationOffset = offset();
218
+ const signature = await this.program.methods.requestWithdrawal(computationOffset, u64(clientNonce, "clientNonce"), u64(amount, "amount")).accountsPartial({
219
+ ...await this.queue("debit_balance", computationOffset),
220
+ payer: this.owner,
221
+ protocol: this.protocol,
222
+ destination,
223
+ balance: this.balance,
224
+ receipt: handle.id
225
+ }).rpc({ commitment: "confirmed" }).catch((error) => submissionError(handle.id.toBase58(), error));
226
+ return new WithdrawalHandle(this, clientNonce, signature);
227
+ }
228
+ withdrawalHandle(clientNonce) {
229
+ u64(clientNonce, "clientNonce");
230
+ return new WithdrawalHandle(this, clientNonce);
231
+ }
232
+ async cancelWithdrawal(receipt) {
233
+ this.assertOwner();
234
+ return this.program.methods.cancelWithdrawal().accountsPartial({ owner: this.owner, balance: this.balance, receipt }).rpc({ commitment: "confirmed" });
235
+ }
236
+ async allocate(amount, clientNonce) {
237
+ return this.beginTransfer("allocation", amount, clientNonce);
238
+ }
239
+ async release(amount, clientNonce) {
240
+ return this.beginTransfer("release", amount, clientNonce);
241
+ }
242
+ transferHandle(transferNonce) {
243
+ u64(transferNonce, "nonce");
244
+ return new TransferHandle(this, transferNonce);
245
+ }
246
+ async beginTransfer(kind, amount, clientNonce) {
247
+ this.assertOwner();
248
+ u64(amount, "amount");
249
+ if (amount === 0n)
250
+ throw new RangeError("Margin amount must be positive");
251
+ const transferNonce = clientNonce;
252
+ u64(clientNonce, "clientNonce");
253
+ const transfer = transferAddress(this.owner, transferNonce, this.program.programId);
254
+ const existing = await this.read("MarginTransfer", transfer);
255
+ if (existing) {
256
+ if (!existing.owner.equals(this.owner) || !existing.market.equals(this.market) || existing.toMarket !== (kind === "allocation") || BigInt(existing.amount.toString()) !== amount) {
257
+ throw new Error("Transfer nonce is already bound to another request");
258
+ }
259
+ return this.transferHandle(clientNonce);
260
+ }
261
+ const computationOffset = offset();
262
+ const queue = await this.queue(kind === "allocation" ? "debit_free" : "debit_market", computationOffset);
263
+ const accounts = {
264
+ ...queue,
265
+ payer: this.owner,
266
+ protocol: this.protocol,
267
+ market: this.market,
268
+ ...kind === "allocation" ? { balance: this.balance } : { marketAccount: this.marketAccount },
269
+ transfer
270
+ };
271
+ const method = kind === "allocation" ? this.program.methods.beginAllocation : this.program.methods.beginRelease;
272
+ const signature = await method(computationOffset, u64(transferNonce, "nonce"), u64(amount, "amount")).accountsPartial(accounts).rpc({ commitment: "confirmed" }).catch((error) => submissionError(transfer.toBase58(), error));
273
+ return new TransferHandle(this, transferNonce, signature);
274
+ }
275
+ async settleTransfer(id, toMarket) {
276
+ this.assertOwner();
277
+ const computationOffset = offset();
278
+ const name = toMarket ? "credit_market" : "credit_free";
279
+ const method = toMarket ? this.program.methods.settleAllocation : this.program.methods.settleRelease;
280
+ return method(computationOffset).accountsPartial({
281
+ ...await this.queue(name, computationOffset),
282
+ payer: this.owner,
283
+ protocol: this.protocol,
284
+ market: this.market,
285
+ transfer: id,
286
+ ...toMarket ? { marketAccount: this.marketAccount } : { balance: this.balance }
287
+ }).rpc({ commitment: "confirmed" });
288
+ }
289
+ async refundTransfer(id, destination) {
290
+ this.assertOwner();
291
+ const protocol = await this.read("Protocol", this.protocol);
292
+ if (!protocol)
293
+ throw new Error("Protocol is unavailable");
294
+ return this.program.methods.refundEscrow().accountsPartial({
295
+ owner: this.owner,
296
+ protocol: this.protocol,
297
+ settlementMint: protocol.settlementMint,
298
+ vault: protocol.vault,
299
+ destination,
300
+ transfer: id
301
+ }).rpc({ commitment: "confirmed" });
302
+ }
303
+ async creditDeposit(id) {
304
+ this.assertOwner();
305
+ const balance = await this.read("BalanceAccount", this.balance);
306
+ if (!balance || !balance.owner.equals(this.owner) || status(balance.status) !== "ready") {
307
+ throw new Error("Balance is unavailable or busy");
308
+ }
309
+ const computationOffset = offset();
310
+ return this.program.methods.creditDeposit(computationOffset).accountsPartial({
311
+ ...await this.queue("credit_balance", computationOffset),
312
+ payer: this.owner,
313
+ protocol: this.protocol,
314
+ balance: this.balance,
315
+ receipt: id
316
+ }).rpc({ commitment: "confirmed" });
317
+ }
318
+ async refundDeposit(id, destination) {
319
+ this.assertOwner();
320
+ const protocol = await this.read("Protocol", this.protocol);
321
+ if (!protocol)
322
+ throw new Error("Protocol is unavailable");
323
+ return this.program.methods.refundDeposit().accountsPartial({
324
+ owner: this.owner,
325
+ protocol: this.protocol,
326
+ settlementMint: protocol.settlementMint,
327
+ vault: protocol.vault,
328
+ destination,
329
+ receipt: id
330
+ }).rpc({ commitment: "confirmed" });
331
+ }
332
+ }
333
+
334
+ class DepositHandle {
335
+ client;
336
+ nonce;
337
+ signature;
338
+ id;
339
+ constructor(client, nonce, signature) {
340
+ this.client = client;
341
+ this.nonce = nonce;
342
+ this.signature = signature;
343
+ this.id = depositAddress(client.owner, nonce, client.program.programId);
344
+ }
345
+ async status() {
346
+ const receipt = await this.client.read("DepositReceipt", this.id);
347
+ if (!receipt || !receipt.owner.equals(this.client.owner)) {
348
+ throw new Error("Deposit receipt is unavailable");
349
+ }
350
+ const current = status(receipt.status);
351
+ if (!["pending", "crediting", "credited", "refunded"].includes(current)) {
352
+ throw new Error("Unknown deposit status");
353
+ }
354
+ return current;
355
+ }
356
+ async confirm(options) {
357
+ await confirmReceipt(this.id.toBase58(), () => this.status(), async (state) => {
358
+ if (state === "credited")
359
+ return true;
360
+ if (state === "refunded")
361
+ throw new DepthError("DEPOSIT_REFUNDED", "confirmation", "Deposit was refunded", false, "Read the receipt before funding again", this.id.toBase58());
362
+ if (state === "pending") {
363
+ try {
364
+ await this.credit();
365
+ } catch (error) {
366
+ if (await this.status() === "pending")
367
+ throw error;
368
+ }
369
+ }
370
+ return false;
371
+ }, options);
372
+ return "credited";
373
+ }
374
+ async credit() {
375
+ if (await this.status() !== "pending") {
376
+ throw new Error("Deposit is not pending credit");
377
+ }
378
+ return this.client.creditDeposit(this.id);
379
+ }
380
+ async cancel() {
381
+ if (await this.status() !== "crediting")
382
+ throw new Error("Deposit credit is not pending");
383
+ return this.client.cancelDeposit(this.id);
384
+ }
385
+ async refund(destination) {
386
+ if (await this.status() !== "pending") {
387
+ throw new Error("Deposit is not refundable");
388
+ }
389
+ return this.client.refundDeposit(this.id, destination);
390
+ }
391
+ }
392
+
393
+ class TransferHandle {
394
+ client;
395
+ nonce;
396
+ signature;
397
+ id;
398
+ constructor(client, nonce, signature) {
399
+ this.client = client;
400
+ this.nonce = nonce;
401
+ this.signature = signature;
402
+ this.id = transferAddress(client.owner, nonce, client.program.programId);
403
+ }
404
+ async status() {
405
+ const transfer = await this.client.read("MarginTransfer", this.id);
406
+ if (!transfer || !transfer.owner.equals(this.client.owner) || !transfer.market.equals(this.client.market)) {
407
+ throw new Error("Margin transfer is unavailable");
408
+ }
409
+ return {
410
+ state: status(transfer.status),
411
+ toMarket: transfer.toMarket,
412
+ amount: BigInt(transfer.amount.toString())
413
+ };
414
+ }
415
+ async confirm(options) {
416
+ const settled = await confirmReceipt(this.id.toBase58(), () => this.status(), async (transfer) => {
417
+ if (transfer.state === "settled")
418
+ return true;
419
+ if (transfer.state === "rejected" || transfer.state === "refunded" || transfer.state === "cancelled")
420
+ throw new DepthError("MARGIN_REJECTED", "confirmation", `Margin transfer ${transfer.state}`, false, "Read the receipt and private account before retrying", this.id.toBase58());
421
+ if (transfer.state === "escrow") {
422
+ try {
423
+ await this.settle();
424
+ } catch (error) {
425
+ if ((await this.status()).state === "escrow")
426
+ throw error;
427
+ }
428
+ }
429
+ return false;
430
+ }, options);
431
+ return { ...settled, state: "settled" };
432
+ }
433
+ async settle() {
434
+ const transfer = await this.status();
435
+ if (transfer.state !== "escrow") {
436
+ throw new Error("Margin transfer is not ready to settle");
437
+ }
438
+ return this.client.settleTransfer(this.id, transfer.toMarket);
439
+ }
440
+ async cancel() {
441
+ const transfer = await this.status();
442
+ if (transfer.state !== "debiting" && transfer.state !== "crediting")
443
+ throw new Error("Transfer computation is not pending");
444
+ return this.client.cancelTransfer(this.id, transfer.toMarket, transfer.state);
445
+ }
446
+ async refund(destination) {
447
+ const transfer = await this.status();
448
+ if (transfer.state !== "escrow") {
449
+ throw new Error("Margin transfer is not refundable");
450
+ }
451
+ return this.client.refundTransfer(this.id, destination);
452
+ }
453
+ }
454
+
455
+ class WithdrawalHandle {
456
+ client;
457
+ nonce;
458
+ signature;
459
+ id;
460
+ constructor(client, nonce, signature) {
461
+ this.client = client;
462
+ this.nonce = nonce;
463
+ this.signature = signature;
464
+ this.id = withdrawalAddress(client.owner, nonce, client.program.programId);
465
+ }
466
+ async status() {
467
+ const receipt = await this.client.read("WithdrawalReceipt", this.id);
468
+ if (!receipt || !receipt.owner.equals(this.client.owner) || !receipt.balance.equals(this.client.balance)) {
469
+ throw new Error("Withdrawal receipt is unavailable");
470
+ }
471
+ const state = status(receipt.status);
472
+ if (!["queued", "paid", "rejected", "cancelled"].includes(state)) {
473
+ throw new Error("Unknown withdrawal status");
474
+ }
475
+ return state;
476
+ }
477
+ async confirm(options) {
478
+ await confirmReceipt(this.id.toBase58(), () => this.status(), async (state) => {
479
+ if (state === "paid")
480
+ return true;
481
+ if (state === "rejected" || state === "cancelled")
482
+ throw new DepthError("WITHDRAWAL_REJECTED", "confirmation", `Withdrawal ${state}`, false, "Read the receipt and private balance before retrying", this.id.toBase58());
483
+ return false;
484
+ }, options);
485
+ return "paid";
486
+ }
487
+ async cancel() {
488
+ if (await this.status() !== "queued")
489
+ throw new Error("Withdrawal is not queued");
490
+ return this.client.cancelWithdrawal(this.id);
491
+ }
492
+ }
493
+ export {
494
+ WithdrawalHandle,
495
+ TransferHandle,
496
+ FundingClient,
497
+ DepositHandle
498
+ };
@@ -0,0 +1,8 @@
1
+ export type ReleasePosition = {
2
+ collateral: bigint;
3
+ reserved: bigint;
4
+ position: bigint;
5
+ entryPriceE8: bigint;
6
+ fundingCheckpoint: bigint;
7
+ };
8
+ export declare function releasableMargin(state: ReleasePosition, oraclePriceE8: bigint, fundingIndex: bigint, initialMarginBps: number): bigint;
@@ -0,0 +1,5 @@
1
+ import * as anchor from "@anchor-lang/core";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ export declare function associatedTokenAddress(owner: PublicKey, mint: PublicKey): PublicKey;
4
+ export declare function sourceTokenAccount(connection: Connection, owner: PublicKey, mint: PublicKey, amount: bigint): Promise<PublicKey>;
5
+ export declare function destinationTokenAccount(provider: anchor.AnchorProvider, owner: PublicKey, mint: PublicKey): Promise<PublicKey>;