@depthhq/sdk 0.1.1 → 0.1.3
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/dist/account/funding.d.ts +2 -1
- package/dist/account/funding.js +4 -2
- package/dist/account/state.d.ts +9 -0
- package/dist/chain/environment.d.ts +1 -0
- package/dist/chain/manifest.d.ts +2 -2
- package/dist/chain/provider.d.ts +4 -1
- package/dist/client/client.d.ts +11 -1
- package/dist/client/types.d.ts +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +380 -108
- package/dist/view/cache.d.ts +31 -0
- package/dist/view/view.d.ts +5 -1
- package/dist/view/view.js +17 -2
- package/package.json +6 -3
|
@@ -7,11 +7,12 @@ export declare class FundingClient {
|
|
|
7
7
|
readonly connection: Connection;
|
|
8
8
|
readonly owner: PublicKey;
|
|
9
9
|
private readonly queue;
|
|
10
|
+
readonly settlement: "keeper" | "wallet";
|
|
10
11
|
readonly market: PublicKey;
|
|
11
12
|
readonly protocol: PublicKey;
|
|
12
13
|
readonly balance: PublicKey;
|
|
13
14
|
readonly marketAccount: PublicKey;
|
|
14
|
-
constructor(program: anchor.Program, connection: Connection, owner: PublicKey, queue: Queue);
|
|
15
|
+
constructor(program: anchor.Program, connection: Connection, owner: PublicKey, queue: Queue, settlement?: "keeper" | "wallet");
|
|
15
16
|
private assertOwner;
|
|
16
17
|
read<T>(name: string, address: PublicKey): Promise<T | undefined>;
|
|
17
18
|
private recoveryKey;
|
package/dist/account/funding.js
CHANGED
|
@@ -76,15 +76,17 @@ class FundingClient {
|
|
|
76
76
|
connection;
|
|
77
77
|
owner;
|
|
78
78
|
queue;
|
|
79
|
+
settlement;
|
|
79
80
|
market;
|
|
80
81
|
protocol;
|
|
81
82
|
balance;
|
|
82
83
|
marketAccount;
|
|
83
|
-
constructor(program, connection, owner, queue) {
|
|
84
|
+
constructor(program, connection, owner, queue, settlement = "wallet") {
|
|
84
85
|
this.program = program;
|
|
85
86
|
this.connection = connection;
|
|
86
87
|
this.owner = owner;
|
|
87
88
|
this.queue = queue;
|
|
89
|
+
this.settlement = settlement;
|
|
88
90
|
this.market = marketAddress(program.programId);
|
|
89
91
|
this.protocol = protocolAddress(program.programId);
|
|
90
92
|
this.balance = balanceAddress(owner, program.programId);
|
|
@@ -418,7 +420,7 @@ class TransferHandle {
|
|
|
418
420
|
return true;
|
|
419
421
|
if (transfer.state === "rejected" || transfer.state === "refunded" || transfer.state === "cancelled")
|
|
420
422
|
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") {
|
|
423
|
+
if (transfer.state === "escrow" && this.client.settlement === "wallet") {
|
|
422
424
|
try {
|
|
423
425
|
await this.settle();
|
|
424
426
|
} catch (error) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as anchor from "@anchor-lang/core";
|
|
2
|
+
import { Connection, PublicKey } from "@solana/web3.js";
|
|
3
|
+
export type AccountState = {
|
|
4
|
+
id: string;
|
|
5
|
+
status: "uninitialized" | "opening" | "ready" | "crediting" | "withdrawing" | "moving" | "claiming";
|
|
6
|
+
version: bigint;
|
|
7
|
+
slot: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function balanceState(program: anchor.Program, connection: Connection, owner: PublicKey, address: PublicKey): Promise<AccountState>;
|
|
@@ -18,3 +18,4 @@ export type ResolvedConnection = {
|
|
|
18
18
|
environment?: DepthEnvironment;
|
|
19
19
|
};
|
|
20
20
|
export declare function resolveConnection(options: ConnectionOptions): Promise<ResolvedConnection>;
|
|
21
|
+
export declare function prepare_depth(options: ConnectionOptions): Promise<ResolvedConnection>;
|
package/dist/chain/manifest.d.ts
CHANGED
|
@@ -32,5 +32,5 @@ export type DeploymentPolicy = {
|
|
|
32
32
|
};
|
|
33
33
|
export declare function manifestBytes(value: unknown): Buffer;
|
|
34
34
|
export declare function authenticateManifest(signed: SignedManifest, trusted: PublicKey): Promise<void>;
|
|
35
|
-
export declare function captureDeployment(provider: anchor.
|
|
36
|
-
export declare function verifyDeployment(provider: anchor.
|
|
35
|
+
export declare function captureDeployment(provider: Pick<anchor.Provider, "connection">, version: number, expiresAt: number): Promise<DeploymentManifest>;
|
|
36
|
+
export declare function verifyDeployment(provider: Pick<anchor.Provider, "connection">, policy: DeploymentPolicy): Promise<void>;
|
package/dist/chain/provider.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as anchor from "@anchor-lang/core";
|
|
2
|
-
import { Transaction } from "@solana/web3.js";
|
|
2
|
+
import { PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js";
|
|
3
3
|
export declare function applyDepthComputeBudget(transaction: Transaction): void;
|
|
4
4
|
export declare class DepthProvider extends anchor.AnchorProvider {
|
|
5
|
+
private readonly cleanup;
|
|
6
|
+
deferClose(id: PublicKey, instruction: TransactionInstruction): void;
|
|
7
|
+
appendCleanup(transaction: Transaction): Promise<string[]>;
|
|
5
8
|
sendAndConfirm(transaction: Parameters<anchor.AnchorProvider["sendAndConfirm"]>[0], signers?: Parameters<anchor.AnchorProvider["sendAndConfirm"]>[1], options?: Parameters<anchor.AnchorProvider["sendAndConfirm"]>[2]): Promise<string>;
|
|
6
9
|
}
|
package/dist/client/client.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as anchor from "@anchor-lang/core";
|
|
2
2
|
import { SOL_USD_MARKET_ID } from "@depthhq/bindings";
|
|
3
3
|
import { PublicKey } from "@solana/web3.js";
|
|
4
|
+
import { DepthProvider } from "../chain/provider.js";
|
|
4
5
|
import { AppAdmin } from "../app/app.js";
|
|
5
6
|
import { MarketCatalog } from "../catalog/catalog.js";
|
|
6
7
|
import { FundingDiscovery } from "../account/discovery.js";
|
|
@@ -16,7 +17,9 @@ import type { CloseInput, DepthOptions, ResolvedDepthOptions, MarketState, Reduc
|
|
|
16
17
|
export declare class DepthClient {
|
|
17
18
|
readonly options: ResolvedDepthOptions;
|
|
18
19
|
readonly program: anchor.Program;
|
|
19
|
-
readonly provider:
|
|
20
|
+
readonly provider: DepthProvider;
|
|
21
|
+
private readonly views;
|
|
22
|
+
private readonly viewReads;
|
|
20
23
|
readonly position: ReturnType<DepthClient["positionActions"]>;
|
|
21
24
|
readonly marketAddress: anchor.web3.PublicKey;
|
|
22
25
|
readonly protocolAddress: anchor.web3.PublicKey;
|
|
@@ -51,6 +54,7 @@ export declare class DepthClient {
|
|
|
51
54
|
private withdrawRequest;
|
|
52
55
|
private accountActions;
|
|
53
56
|
readonly account: (() => {
|
|
57
|
+
state: () => Promise<import("../account/state.js").AccountState>;
|
|
54
58
|
detail: (item: Parameters<FundingDiscovery["detail"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
|
|
55
59
|
transaction: (item: Parameters<FundingDiscovery["transaction"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
|
|
56
60
|
history: (options?: Parameters<FundingDiscovery["history"]>[0]) => Promise<import("../account/discovery.js").PendingPage>;
|
|
@@ -78,6 +82,7 @@ export declare class DepthClient {
|
|
|
78
82
|
pollMs?: number;
|
|
79
83
|
}) => Promise<BalanceSnapshot>;
|
|
80
84
|
}) & {
|
|
85
|
+
state: () => Promise<import("../account/state.js").AccountState>;
|
|
81
86
|
detail: (item: Parameters<FundingDiscovery["detail"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
|
|
82
87
|
transaction: (item: Parameters<FundingDiscovery["transaction"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
|
|
83
88
|
history: (options?: Parameters<FundingDiscovery["history"]>[0]) => Promise<import("../account/discovery.js").PendingPage>;
|
|
@@ -131,7 +136,12 @@ export declare class DepthClient {
|
|
|
131
136
|
}>;
|
|
132
137
|
};
|
|
133
138
|
private orderAddress;
|
|
139
|
+
private deferViewClose;
|
|
140
|
+
private viewState;
|
|
141
|
+
private summaryView;
|
|
142
|
+
private readSummaryView;
|
|
134
143
|
private submitTrade;
|
|
144
|
+
private waitForMarket;
|
|
135
145
|
private validateTrade;
|
|
136
146
|
}
|
|
137
147
|
export declare function createDepth(options: DepthOptions): Promise<DepthClient>;
|
package/dist/client/types.d.ts
CHANGED
|
@@ -11,10 +11,14 @@ export type DepthWallet = {
|
|
|
11
11
|
export type DepthOptions = ConnectionOptions & {
|
|
12
12
|
appId?: PublicKey | string;
|
|
13
13
|
wallet: DepthWallet;
|
|
14
|
+
privateViews?: "memory" | "device";
|
|
15
|
+
settlement?: "keeper" | "wallet";
|
|
14
16
|
};
|
|
15
17
|
export type ResolvedDepthOptions = ResolvedConnection & {
|
|
16
18
|
appId?: PublicKey;
|
|
17
19
|
wallet: DepthWallet;
|
|
20
|
+
privateViews?: "memory" | "device";
|
|
21
|
+
settlement?: "keeper" | "wallet";
|
|
18
22
|
};
|
|
19
23
|
export type TradeTerms = {
|
|
20
24
|
marketId: typeof SOL_USD_MARKET_ID;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,8 @@ export { resolveAmount } from "./trade/amount.js";
|
|
|
26
26
|
export type { AmountSelector } from "./trade/amount.js";
|
|
27
27
|
export type { BalanceSnapshot, FillSnapshot, PositionSnapshot, QuoteBalanceSnapshot, } from "./view/view.js";
|
|
28
28
|
export type { DepthOptions, DepthWallet, TradeInput, ReductionInput, CloseInput, ReverseInput, TradeIntent, } from "./client/types.js";
|
|
29
|
-
export { resolveConnection } from "./chain/environment.js";
|
|
29
|
+
export { resolveConnection, prepare_depth } from "./chain/environment.js";
|
|
30
|
+
export type { AccountState } from "./account/state.js";
|
|
30
31
|
export type { ConnectionOptions, ResolvedConnection, DepthEnvironment, } from "./chain/environment.js";
|
|
31
32
|
export { DepthError } from "./operation/error.js";
|
|
32
33
|
export { DepthProvider } from "./chain/provider.js";
|
package/dist/index.js
CHANGED
|
@@ -43628,7 +43628,7 @@ import {
|
|
|
43628
43628
|
recoveryConfigAddress as recoveryConfigAddress2,
|
|
43629
43629
|
SOL_USD_MARKET_ID as SOL_USD_MARKET_ID3
|
|
43630
43630
|
} from "@depthhq/bindings";
|
|
43631
|
-
import { PublicKey as
|
|
43631
|
+
import { PublicKey as PublicKey10 } from "@solana/web3.js";
|
|
43632
43632
|
|
|
43633
43633
|
// src/chain/random.ts
|
|
43634
43634
|
function randomBytes3(length) {
|
|
@@ -44491,7 +44491,7 @@ async function captureDeployment(provider, version, expiresAt) {
|
|
|
44491
44491
|
const protocol = coder.decode("protocol", protocolInfo.data);
|
|
44492
44492
|
if (!market.settlementMint.equals(protocol.settlementMint))
|
|
44493
44493
|
throw new Error("Deployment settlement mints disagree");
|
|
44494
|
-
const arcium2 =
|
|
44494
|
+
const arcium2 = new anchor2.Program(ARCIUM_IDL, provider);
|
|
44495
44495
|
const mxeAddress = getMXEAccAddress(DEPTH_PROGRAM_ID);
|
|
44496
44496
|
const mxe = await arcium2.account.mxeAccount.fetch(mxeAddress);
|
|
44497
44497
|
if (!mxe.mxeProgramId.equals(DEPTH_PROGRAM_ID))
|
|
@@ -44521,6 +44521,7 @@ async function captureDeployment(provider, version, expiresAt) {
|
|
|
44521
44521
|
})
|
|
44522
44522
|
};
|
|
44523
44523
|
}
|
|
44524
|
+
var verified = new WeakMap;
|
|
44524
44525
|
async function verifyDeployment(provider, policy) {
|
|
44525
44526
|
if ("localnet" in policy) {
|
|
44526
44527
|
const url = new URL(provider.connection.rpcEndpoint);
|
|
@@ -44530,9 +44531,28 @@ async function verifyDeployment(provider, policy) {
|
|
|
44530
44531
|
}
|
|
44531
44532
|
await authenticateManifest(policy.manifest, policy.trustedSigner);
|
|
44532
44533
|
const expected = policy.manifest.payload;
|
|
44533
|
-
const
|
|
44534
|
-
|
|
44535
|
-
|
|
44534
|
+
const key = manifestBytes(policy.manifest).toString("base64");
|
|
44535
|
+
const previous = verified.get(provider.connection);
|
|
44536
|
+
if (previous?.key === key && previous.expiresAt > Date.now())
|
|
44537
|
+
return previous.task;
|
|
44538
|
+
const task = (async () => {
|
|
44539
|
+
const actual = await captureDeployment(provider, expected.version, expected.expiresAt);
|
|
44540
|
+
if (!manifestBytes(actual).equals(manifestBytes(expected)))
|
|
44541
|
+
throw new Error("Signed deployment does not match the connected chain");
|
|
44542
|
+
})();
|
|
44543
|
+
const entry = {
|
|
44544
|
+
key,
|
|
44545
|
+
expiresAt: Math.min(Date.now() + 30000, expected.expiresAt * 1000),
|
|
44546
|
+
task
|
|
44547
|
+
};
|
|
44548
|
+
verified.set(provider.connection, entry);
|
|
44549
|
+
try {
|
|
44550
|
+
await task;
|
|
44551
|
+
} catch (error) {
|
|
44552
|
+
if (verified.get(provider.connection) === entry)
|
|
44553
|
+
verified.delete(provider.connection);
|
|
44554
|
+
throw error;
|
|
44555
|
+
}
|
|
44536
44556
|
}
|
|
44537
44557
|
|
|
44538
44558
|
// src/chain/network.ts
|
|
@@ -44687,6 +44707,11 @@ async function resolveConnection(options) {
|
|
|
44687
44707
|
throw unavailable("Depth deployment could not be verified", error);
|
|
44688
44708
|
}
|
|
44689
44709
|
}
|
|
44710
|
+
async function prepare_depth(options) {
|
|
44711
|
+
const resolved = await resolveConnection(options);
|
|
44712
|
+
await verifyDeployment({ connection: resolved.connection }, resolved.deployment);
|
|
44713
|
+
return resolved;
|
|
44714
|
+
}
|
|
44690
44715
|
|
|
44691
44716
|
// src/chain/arcium.ts
|
|
44692
44717
|
function arciumAccount(provider) {
|
|
@@ -44701,6 +44726,7 @@ import { DEPTH_IDL as DEPTH_IDL2, DEPTH_PROGRAM_ID as DEPTH_PROGRAM_ID3 } from "
|
|
|
44701
44726
|
import {
|
|
44702
44727
|
ComputeBudgetProgram,
|
|
44703
44728
|
SendTransactionError,
|
|
44729
|
+
PublicKey as PublicKey4,
|
|
44704
44730
|
Transaction
|
|
44705
44731
|
} from "@solana/web3.js";
|
|
44706
44732
|
var queuedInstructions = new Set([
|
|
@@ -44743,11 +44769,52 @@ function applyDepthComputeBudget(transaction) {
|
|
|
44743
44769
|
}
|
|
44744
44770
|
|
|
44745
44771
|
class DepthProvider extends anchor3.AnchorProvider {
|
|
44772
|
+
cleanup = new Map;
|
|
44773
|
+
deferClose(id, instruction) {
|
|
44774
|
+
this.cleanup.set(id.toBase58(), instruction);
|
|
44775
|
+
}
|
|
44776
|
+
async appendCleanup(transaction) {
|
|
44777
|
+
if (!this.cleanup.size || transaction.signatures.some((item) => item.signature))
|
|
44778
|
+
return [];
|
|
44779
|
+
const entries = [...this.cleanup.entries()].slice(0, 64);
|
|
44780
|
+
const queued = new Set(entries.map(([, instruction]) => instruction));
|
|
44781
|
+
transaction.instructions = transaction.instructions.filter((instruction) => !queued.has(instruction));
|
|
44782
|
+
const accounts2 = await this.connection.getMultipleAccountsInfo(entries.map(([id]) => new PublicKey4(id)), "confirmed");
|
|
44783
|
+
const added = [];
|
|
44784
|
+
for (let index = 0;index < entries.length; index++) {
|
|
44785
|
+
const [id, instruction] = entries[index];
|
|
44786
|
+
if (!accounts2[index]?.owner.equals(DEPTH_PROGRAM_ID3)) {
|
|
44787
|
+
this.cleanup.delete(id);
|
|
44788
|
+
continue;
|
|
44789
|
+
}
|
|
44790
|
+
const candidate = new Transaction({
|
|
44791
|
+
feePayer: transaction.feePayer ?? this.wallet.publicKey,
|
|
44792
|
+
recentBlockhash: transaction.recentBlockhash ?? PublicKey4.default.toBase58()
|
|
44793
|
+
}).add(...transaction.instructions, instruction);
|
|
44794
|
+
try {
|
|
44795
|
+
candidate.serialize({
|
|
44796
|
+
requireAllSignatures: false,
|
|
44797
|
+
verifySignatures: false
|
|
44798
|
+
});
|
|
44799
|
+
} catch {
|
|
44800
|
+
continue;
|
|
44801
|
+
}
|
|
44802
|
+
transaction.add(instruction);
|
|
44803
|
+
added.push(id);
|
|
44804
|
+
}
|
|
44805
|
+
return added;
|
|
44806
|
+
}
|
|
44746
44807
|
async sendAndConfirm(transaction, signers, options) {
|
|
44747
|
-
|
|
44808
|
+
let cleanup = [];
|
|
44809
|
+
if (transaction instanceof Transaction) {
|
|
44748
44810
|
applyDepthComputeBudget(transaction);
|
|
44811
|
+
cleanup = await this.appendCleanup(transaction);
|
|
44812
|
+
}
|
|
44749
44813
|
try {
|
|
44750
|
-
|
|
44814
|
+
const signature = await super.sendAndConfirm(transaction, signers, options);
|
|
44815
|
+
for (const id of cleanup)
|
|
44816
|
+
this.cleanup.delete(id);
|
|
44817
|
+
return signature;
|
|
44751
44818
|
} catch (error) {
|
|
44752
44819
|
if (!(error instanceof Error) || !error.message.includes("Unknown action 'undefined'"))
|
|
44753
44820
|
throw error;
|
|
@@ -44998,7 +45065,7 @@ import {
|
|
|
44998
45065
|
transferAddress,
|
|
44999
45066
|
withdrawalAddress
|
|
45000
45067
|
} from "@depthhq/bindings";
|
|
45001
|
-
import { PublicKey as
|
|
45068
|
+
import { PublicKey as PublicKey5 } from "@solana/web3.js";
|
|
45002
45069
|
|
|
45003
45070
|
// src/chain/transaction.ts
|
|
45004
45071
|
init_buffer();
|
|
@@ -45156,7 +45223,7 @@ class FundingDiscovery {
|
|
|
45156
45223
|
const limit = options.limit ?? 20;
|
|
45157
45224
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
45158
45225
|
throw new RangeError("limit must be an integer from 1 to 100");
|
|
45159
|
-
const cursor = options.cursor ? new
|
|
45226
|
+
const cursor = options.cursor ? new PublicKey5(options.cursor).toBase58() : undefined;
|
|
45160
45227
|
const accounts2 = await this.connection.getProgramAccounts(this.program.programId, {
|
|
45161
45228
|
commitment: "confirmed",
|
|
45162
45229
|
dataSlice: { offset: 0, length: 0 },
|
|
@@ -45188,7 +45255,7 @@ class FundingDiscovery {
|
|
|
45188
45255
|
const current = status(state);
|
|
45189
45256
|
if (!state.toMarket || current !== "settled")
|
|
45190
45257
|
return;
|
|
45191
|
-
const orderId =
|
|
45258
|
+
const orderId = PublicKey5.findProgramAddressSync([
|
|
45192
45259
|
Buffer2.from("order"),
|
|
45193
45260
|
state.market.toBuffer(),
|
|
45194
45261
|
this.owner.toBuffer(),
|
|
@@ -45235,7 +45302,7 @@ class FundingDiscovery {
|
|
|
45235
45302
|
const limit = options.limit ?? 20;
|
|
45236
45303
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
|
|
45237
45304
|
throw new RangeError("limit must be an integer from 1 to 100");
|
|
45238
|
-
const cursor = options.cursor ? new
|
|
45305
|
+
const cursor = options.cursor ? new PublicKey5(options.cursor).toBase58() : undefined;
|
|
45239
45306
|
const types3 = [
|
|
45240
45307
|
{
|
|
45241
45308
|
name: "depositReceipt",
|
|
@@ -45326,7 +45393,7 @@ class FundingDiscovery {
|
|
|
45326
45393
|
throw new Error("Order changed during discovery");
|
|
45327
45394
|
const bytes = Buffer2.alloc(8);
|
|
45328
45395
|
bytes.writeBigUInt64LE(nonce);
|
|
45329
|
-
canonical =
|
|
45396
|
+
canonical = PublicKey5.findProgramAddressSync([
|
|
45330
45397
|
Buffer2.from("order"),
|
|
45331
45398
|
state.market.toBuffer(),
|
|
45332
45399
|
this.owner.toBuffer(),
|
|
@@ -45412,15 +45479,17 @@ class FundingClient {
|
|
|
45412
45479
|
connection;
|
|
45413
45480
|
owner;
|
|
45414
45481
|
queue;
|
|
45482
|
+
settlement;
|
|
45415
45483
|
market;
|
|
45416
45484
|
protocol;
|
|
45417
45485
|
balance;
|
|
45418
45486
|
marketAccount;
|
|
45419
|
-
constructor(program, connection, owner, queue) {
|
|
45487
|
+
constructor(program, connection, owner, queue, settlement = "wallet") {
|
|
45420
45488
|
this.program = program;
|
|
45421
45489
|
this.connection = connection;
|
|
45422
45490
|
this.owner = owner;
|
|
45423
45491
|
this.queue = queue;
|
|
45492
|
+
this.settlement = settlement;
|
|
45424
45493
|
this.market = marketAddress3(program.programId);
|
|
45425
45494
|
this.protocol = protocolAddress2(program.programId);
|
|
45426
45495
|
this.balance = balanceAddress(owner, program.programId);
|
|
@@ -45754,7 +45823,7 @@ class TransferHandle {
|
|
|
45754
45823
|
return true;
|
|
45755
45824
|
if (transfer.state === "rejected" || transfer.state === "refunded" || transfer.state === "cancelled")
|
|
45756
45825
|
throw new DepthError("MARGIN_REJECTED", "confirmation", `Margin transfer ${transfer.state}`, false, "Read the receipt and private account before retrying", this.id.toBase58());
|
|
45757
|
-
if (transfer.state === "escrow") {
|
|
45826
|
+
if (transfer.state === "escrow" && this.client.settlement === "wallet") {
|
|
45758
45827
|
try {
|
|
45759
45828
|
await this.settle();
|
|
45760
45829
|
} catch (error) {
|
|
@@ -45827,18 +45896,46 @@ class WithdrawalHandle {
|
|
|
45827
45896
|
}
|
|
45828
45897
|
}
|
|
45829
45898
|
|
|
45899
|
+
// src/account/state.ts
|
|
45900
|
+
async function balanceState(program, connection, owner, address2) {
|
|
45901
|
+
const { context, value: value2 } = await connection.getAccountInfoAndContext(address2, "confirmed");
|
|
45902
|
+
const base = { id: address2.toBase58(), slot: context.slot };
|
|
45903
|
+
if (!value2)
|
|
45904
|
+
return { ...base, status: "uninitialized", version: 0n };
|
|
45905
|
+
if (!value2.owner.equals(program.programId))
|
|
45906
|
+
throw new Error("Balance account is not owned by Depth");
|
|
45907
|
+
const state = program.coder.accounts.decode("balanceAccount", value2.data);
|
|
45908
|
+
if (!state.owner.equals(owner))
|
|
45909
|
+
throw new Error("Balance account does not belong to this wallet");
|
|
45910
|
+
const status3 = Object.keys(state.status)[0];
|
|
45911
|
+
if (![
|
|
45912
|
+
"opening",
|
|
45913
|
+
"ready",
|
|
45914
|
+
"crediting",
|
|
45915
|
+
"withdrawing",
|
|
45916
|
+
"moving",
|
|
45917
|
+
"claiming"
|
|
45918
|
+
].includes(status3))
|
|
45919
|
+
throw new Error("Balance account has an invalid status");
|
|
45920
|
+
return {
|
|
45921
|
+
...base,
|
|
45922
|
+
status: status3,
|
|
45923
|
+
version: BigInt(state.version.toString())
|
|
45924
|
+
};
|
|
45925
|
+
}
|
|
45926
|
+
|
|
45830
45927
|
// src/account/token.ts
|
|
45831
45928
|
init_buffer();
|
|
45832
45929
|
import {
|
|
45833
|
-
PublicKey as
|
|
45930
|
+
PublicKey as PublicKey6,
|
|
45834
45931
|
SystemProgram,
|
|
45835
45932
|
Transaction as Transaction2,
|
|
45836
|
-
TransactionInstruction
|
|
45933
|
+
TransactionInstruction as TransactionInstruction2
|
|
45837
45934
|
} from "@solana/web3.js";
|
|
45838
|
-
var tokenProgram = new
|
|
45839
|
-
var associatedProgram = new
|
|
45935
|
+
var tokenProgram = new PublicKey6("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
|
45936
|
+
var associatedProgram = new PublicKey6("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
|
|
45840
45937
|
function associatedTokenAddress(owner, mint) {
|
|
45841
|
-
return
|
|
45938
|
+
return PublicKey6.findProgramAddressSync([owner.toBuffer(), tokenProgram.toBuffer(), mint.toBuffer()], associatedProgram)[0];
|
|
45842
45939
|
}
|
|
45843
45940
|
function tokenBalance(info, owner, mint) {
|
|
45844
45941
|
if (!info.owner.equals(tokenProgram) || info.data.length < 165 || !info.data.subarray(0, 32).equals(mint.toBuffer()) || !info.data.subarray(32, 64).equals(owner.toBuffer()) || info.data[108] !== 1)
|
|
@@ -45867,7 +45964,7 @@ async function destinationTokenAccount(provider, owner, mint) {
|
|
|
45867
45964
|
const address2 = associatedTokenAddress(owner, mint);
|
|
45868
45965
|
let info = await provider.connection.getAccountInfo(address2, "confirmed");
|
|
45869
45966
|
if (!info) {
|
|
45870
|
-
const instruction = new
|
|
45967
|
+
const instruction = new TransactionInstruction2({
|
|
45871
45968
|
programId: associatedProgram,
|
|
45872
45969
|
data: Buffer2.from([1]),
|
|
45873
45970
|
keys: [
|
|
@@ -45909,7 +46006,7 @@ import {
|
|
|
45909
46006
|
marketAddress as marketAddress4,
|
|
45910
46007
|
SOL_USD_MARKET_ID as SOL_USD_MARKET_ID2
|
|
45911
46008
|
} from "@depthhq/bindings";
|
|
45912
|
-
import { PublicKey as
|
|
46009
|
+
import { PublicKey as PublicKey7 } from "@solana/web3.js";
|
|
45913
46010
|
|
|
45914
46011
|
// src/position/pnl.ts
|
|
45915
46012
|
var scale = 100000000000n;
|
|
@@ -46139,11 +46236,11 @@ class DepthOperation {
|
|
|
46139
46236
|
throw new DepthError(result.status === "pending" ? "FILL_VIEW_PENDING" : "FILL_VIEW_STALE", "confirmation", result.status === "pending" ? "Private fill computation is still pending" : "Private fill view is stale", result.status === "pending", result.status === "pending" ? "Call privateResult again with the same operation" : "Restore this operation and request a fresh fill view", this.id.toBase58());
|
|
46140
46237
|
this.fill = {
|
|
46141
46238
|
...result,
|
|
46142
|
-
positionId: marketAccountAddress2(new
|
|
46239
|
+
positionId: marketAccountAddress2(new PublicKey7(snapshot.owner), this.program.programId)
|
|
46143
46240
|
};
|
|
46144
46241
|
}
|
|
46145
46242
|
try {
|
|
46146
|
-
await this.view.
|
|
46243
|
+
await this.view.deferClose();
|
|
46147
46244
|
} catch (error) {
|
|
46148
46245
|
let remaining;
|
|
46149
46246
|
try {
|
|
@@ -46159,7 +46256,7 @@ class DepthOperation {
|
|
|
46159
46256
|
return this.fill;
|
|
46160
46257
|
}
|
|
46161
46258
|
cleanupError(cause) {
|
|
46162
|
-
return new DepthError("FILL_VIEW_CLEANUP_PENDING", "confirmation", "Private fill was read but
|
|
46259
|
+
return new DepthError("FILL_VIEW_CLEANUP_PENDING", "confirmation", "Private fill was read but receipt cleanup could not be scheduled", true, "Call privateResult again with the same operation to schedule cleanup", this.id.toBase58(), { cause });
|
|
46163
46260
|
}
|
|
46164
46261
|
}
|
|
46165
46262
|
|
|
@@ -46170,22 +46267,22 @@ import {
|
|
|
46170
46267
|
marketAddress as marketAddress5,
|
|
46171
46268
|
protocolAddress as protocolAddress3
|
|
46172
46269
|
} from "@depthhq/bindings";
|
|
46173
|
-
import { PublicKey as
|
|
46270
|
+
import { PublicKey as PublicKey8 } from "@solana/web3.js";
|
|
46174
46271
|
|
|
46175
46272
|
class DepthRecovery {
|
|
46176
46273
|
program;
|
|
46177
46274
|
connection;
|
|
46178
46275
|
owner;
|
|
46179
46276
|
market = marketAddress5();
|
|
46180
|
-
winddown =
|
|
46277
|
+
winddown = PublicKey8.findProgramAddressSync([Buffer2.from("winddown"), this.market.toBuffer()], DEPTH_PROGRAM_ID5)[0];
|
|
46181
46278
|
marketAccount;
|
|
46182
46279
|
claim;
|
|
46183
46280
|
constructor(program, connection, owner) {
|
|
46184
46281
|
this.program = program;
|
|
46185
46282
|
this.connection = connection;
|
|
46186
46283
|
this.owner = owner;
|
|
46187
|
-
this.marketAccount =
|
|
46188
|
-
this.claim =
|
|
46284
|
+
this.marketAccount = PublicKey8.findProgramAddressSync([Buffer2.from("market-account"), this.market.toBuffer(), owner.toBuffer()], DEPTH_PROGRAM_ID5)[0];
|
|
46285
|
+
this.claim = PublicKey8.findProgramAddressSync([Buffer2.from("winddown-claim"), this.marketAccount.toBuffer()], DEPTH_PROGRAM_ID5)[0];
|
|
46189
46286
|
}
|
|
46190
46287
|
async read(address2, name2) {
|
|
46191
46288
|
const result = await this.connection.getAccountInfoAndContext(address2, "confirmed");
|
|
@@ -46275,7 +46372,7 @@ import {
|
|
|
46275
46372
|
marketAddress as marketAddress6,
|
|
46276
46373
|
transferAddress as transferAddress3
|
|
46277
46374
|
} from "@depthhq/bindings";
|
|
46278
|
-
import { PublicKey as
|
|
46375
|
+
import { PublicKey as PublicKey9 } from "@solana/web3.js";
|
|
46279
46376
|
|
|
46280
46377
|
// src/history/replay.ts
|
|
46281
46378
|
function replayFill(state, fill, fundingIndex, maker = false) {
|
|
@@ -46354,7 +46451,7 @@ class ExecutionHistory {
|
|
|
46354
46451
|
this.requestView = requestView;
|
|
46355
46452
|
}
|
|
46356
46453
|
orderAddress(trader, nonce) {
|
|
46357
|
-
return
|
|
46454
|
+
return PublicKey9.findProgramAddressSync([
|
|
46358
46455
|
Buffer2.from("order"),
|
|
46359
46456
|
marketAddress6(this.program.programId).toBuffer(),
|
|
46360
46457
|
trader.toBuffer(),
|
|
@@ -46376,7 +46473,7 @@ class ExecutionHistory {
|
|
|
46376
46473
|
}
|
|
46377
46474
|
const result = this.fills.get(key) ?? await view.wait({ timeoutMs: 180000 });
|
|
46378
46475
|
if (result.status === "stale") {
|
|
46379
|
-
await view.
|
|
46476
|
+
await view.deferClose();
|
|
46380
46477
|
this.views.delete(key);
|
|
46381
46478
|
throw new Error("Historical private execution changed; retry with the same wallet");
|
|
46382
46479
|
}
|
|
@@ -46384,7 +46481,7 @@ class ExecutionHistory {
|
|
|
46384
46481
|
throw new Error("Historical private execution is still pending; retry with the same wallet");
|
|
46385
46482
|
this.fills.set(key, result);
|
|
46386
46483
|
try {
|
|
46387
|
-
await view.
|
|
46484
|
+
await view.deferClose();
|
|
46388
46485
|
} catch (error) {
|
|
46389
46486
|
if (await this.connection.getAccountInfo(view.id, "confirmed"))
|
|
46390
46487
|
throw error;
|
|
@@ -46752,19 +46849,151 @@ class DepthView {
|
|
|
46752
46849
|
await new Promise((resolve) => setTimeout(resolve, Math.min(pollMs, deadline - Date.now())));
|
|
46753
46850
|
}
|
|
46754
46851
|
}
|
|
46852
|
+
async deferClose() {
|
|
46853
|
+
const provider = this.program.provider;
|
|
46854
|
+
if (typeof provider.deferClose !== "function") {
|
|
46855
|
+
await this.close();
|
|
46856
|
+
return;
|
|
46857
|
+
}
|
|
46858
|
+
const snapshot = await this.status();
|
|
46859
|
+
if (snapshot.status === "pending")
|
|
46860
|
+
throw new Error("Private view computation is still pending");
|
|
46861
|
+
const instruction = await this.closeBuilder().instruction();
|
|
46862
|
+
provider.deferClose(this.id, instruction);
|
|
46863
|
+
}
|
|
46864
|
+
closeBuilder() {
|
|
46865
|
+
const builder = this.kind === "balance" ? this.program.methods.closeBalanceView() : this.kind === "market" ? this.program.methods.closeMarketView() : this.kind === "fill" ? this.program.methods.closeFillView() : this.program.methods.closeQuoteView();
|
|
46866
|
+
return builder.accountsPartial({ owner: this.owner, view: this.id });
|
|
46867
|
+
}
|
|
46755
46868
|
async close() {
|
|
46756
46869
|
const snapshot = await this.status();
|
|
46757
46870
|
if (snapshot.status === "pending") {
|
|
46758
46871
|
throw new Error("Private view computation is still pending");
|
|
46759
46872
|
}
|
|
46760
|
-
|
|
46761
|
-
|
|
46873
|
+
return this.closeBuilder().rpc({ commitment: "confirmed" });
|
|
46874
|
+
}
|
|
46875
|
+
}
|
|
46876
|
+
|
|
46877
|
+
// src/view/cache.ts
|
|
46878
|
+
class DeviceViews {
|
|
46879
|
+
database;
|
|
46880
|
+
open() {
|
|
46881
|
+
return this.database ??= new Promise((resolve, reject) => {
|
|
46882
|
+
const request = indexedDB.open("depth-private-views", 1);
|
|
46883
|
+
request.onupgradeneeded = () => {
|
|
46884
|
+
request.result.createObjectStore("keys");
|
|
46885
|
+
request.result.createObjectStore("views");
|
|
46886
|
+
};
|
|
46887
|
+
request.onerror = () => reject(request.error);
|
|
46888
|
+
request.onblocked = () => reject(new Error("Private view storage is blocked"));
|
|
46889
|
+
request.onsuccess = () => resolve(request.result);
|
|
46890
|
+
});
|
|
46891
|
+
}
|
|
46892
|
+
async key(scope, proposed) {
|
|
46893
|
+
const database = await this.open();
|
|
46894
|
+
return new Promise((resolve, reject) => {
|
|
46895
|
+
const transaction = database.transaction("keys", "readwrite");
|
|
46896
|
+
const store = transaction.objectStore("keys");
|
|
46897
|
+
const request = store.get(scope);
|
|
46898
|
+
let value2;
|
|
46899
|
+
request.onsuccess = () => {
|
|
46900
|
+
value2 = request.result ?? proposed;
|
|
46901
|
+
if (!request.result)
|
|
46902
|
+
store.put(value2, scope);
|
|
46903
|
+
};
|
|
46904
|
+
transaction.oncomplete = () => resolve(value2);
|
|
46905
|
+
transaction.onabort = () => reject(transaction.error);
|
|
46906
|
+
transaction.onerror = () => reject(transaction.error);
|
|
46907
|
+
});
|
|
46908
|
+
}
|
|
46909
|
+
async read(id) {
|
|
46910
|
+
const database = await this.open();
|
|
46911
|
+
return new Promise((resolve, reject) => {
|
|
46912
|
+
const transaction = database.transaction("views", "readonly");
|
|
46913
|
+
const request = transaction.objectStore("views").get(id);
|
|
46914
|
+
transaction.oncomplete = () => resolve(request.result);
|
|
46915
|
+
transaction.onabort = () => reject(transaction.error);
|
|
46916
|
+
transaction.onerror = () => reject(transaction.error);
|
|
46917
|
+
});
|
|
46918
|
+
}
|
|
46919
|
+
async write(id, value2) {
|
|
46920
|
+
const database = await this.open();
|
|
46921
|
+
return new Promise((resolve, reject) => {
|
|
46922
|
+
const transaction = database.transaction("views", "readwrite");
|
|
46923
|
+
transaction.objectStore("views").put(value2, id);
|
|
46924
|
+
transaction.oncomplete = () => resolve();
|
|
46925
|
+
transaction.onabort = () => reject(transaction.error);
|
|
46926
|
+
transaction.onerror = () => reject(transaction.error);
|
|
46927
|
+
});
|
|
46928
|
+
}
|
|
46929
|
+
}
|
|
46930
|
+
|
|
46931
|
+
class ViewCache {
|
|
46932
|
+
scope;
|
|
46933
|
+
storage;
|
|
46934
|
+
memory = new Map;
|
|
46935
|
+
key;
|
|
46936
|
+
constructor(scope, storage) {
|
|
46937
|
+
this.scope = scope;
|
|
46938
|
+
this.storage = storage;
|
|
46939
|
+
}
|
|
46940
|
+
encryptionKey() {
|
|
46941
|
+
return this.key ??= crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, [
|
|
46942
|
+
"encrypt",
|
|
46943
|
+
"decrypt"
|
|
46944
|
+
]).then((key) => this.storage.key(this.scope, key));
|
|
46945
|
+
}
|
|
46946
|
+
id(kind, account) {
|
|
46947
|
+
return `${this.scope}:${kind}:${account}`;
|
|
46948
|
+
}
|
|
46949
|
+
async get(kind, account, version) {
|
|
46950
|
+
const id = this.id(kind, account);
|
|
46951
|
+
let snapshot = this.memory.get(id);
|
|
46952
|
+
if (!snapshot && this.storage) {
|
|
46953
|
+
try {
|
|
46954
|
+
const envelope = await this.storage.read(id);
|
|
46955
|
+
if (envelope) {
|
|
46956
|
+
const bytes = await crypto.subtle.decrypt({
|
|
46957
|
+
name: "AES-GCM",
|
|
46958
|
+
iv: envelope.iv,
|
|
46959
|
+
additionalData: new TextEncoder().encode(id)
|
|
46960
|
+
}, await this.encryptionKey(), envelope.data);
|
|
46961
|
+
snapshot = JSON.parse(new TextDecoder().decode(bytes), (_, value2) => value2 && typeof value2 === "object" && typeof value2.$bigint === "string" ? BigInt(value2.$bigint) : value2);
|
|
46962
|
+
}
|
|
46963
|
+
} catch {
|
|
46964
|
+
return;
|
|
46965
|
+
}
|
|
46966
|
+
}
|
|
46967
|
+
if (!snapshot || snapshot.status !== "ready" || snapshot.version !== version || typeof snapshot.id !== "string" || !Number.isSafeInteger(snapshot.slot) || (kind === "balance" ? typeof snapshot.amount !== "bigint" : [
|
|
46968
|
+
"collateral",
|
|
46969
|
+
"reserved",
|
|
46970
|
+
"position",
|
|
46971
|
+
"entryPriceE8",
|
|
46972
|
+
"fundingCheckpoint"
|
|
46973
|
+
].some((field) => typeof snapshot[field] !== "bigint")))
|
|
46974
|
+
return;
|
|
46975
|
+
this.memory.set(id, snapshot);
|
|
46976
|
+
return { ...snapshot };
|
|
46977
|
+
}
|
|
46978
|
+
async set(kind, account, snapshot) {
|
|
46979
|
+
if (snapshot.status !== "ready")
|
|
46980
|
+
return;
|
|
46981
|
+
const id = this.id(kind, account);
|
|
46982
|
+
this.memory.set(id, { ...snapshot });
|
|
46983
|
+
if (!this.storage)
|
|
46984
|
+
return;
|
|
46985
|
+
try {
|
|
46986
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
46987
|
+
const bytes = new TextEncoder().encode(JSON.stringify(snapshot, (_, value2) => typeof value2 === "bigint" ? { $bigint: value2.toString() } : value2));
|
|
46988
|
+
const data = await crypto.subtle.encrypt({ name: "AES-GCM", iv, additionalData: new TextEncoder().encode(id) }, await this.encryptionKey(), bytes);
|
|
46989
|
+
await this.storage.write(id, { iv, data });
|
|
46990
|
+
} catch {}
|
|
46762
46991
|
}
|
|
46763
46992
|
}
|
|
46764
46993
|
|
|
46765
46994
|
// src/client/client.ts
|
|
46766
46995
|
function pda(seeds, programId = DEPTH_PROGRAM_ID7) {
|
|
46767
|
-
return
|
|
46996
|
+
return PublicKey10.findProgramAddressSync(seeds, programId)[0];
|
|
46768
46997
|
}
|
|
46769
46998
|
function nonce() {
|
|
46770
46999
|
return new anchor8.BN(randomBytes3(8), "le");
|
|
@@ -46777,6 +47006,8 @@ class DepthClient {
|
|
|
46777
47006
|
options;
|
|
46778
47007
|
program;
|
|
46779
47008
|
provider;
|
|
47009
|
+
views;
|
|
47010
|
+
viewReads = new Map;
|
|
46780
47011
|
position;
|
|
46781
47012
|
marketAddress = marketAddress7();
|
|
46782
47013
|
protocolAddress = protocolAddress4();
|
|
@@ -46785,7 +47016,7 @@ class DepthClient {
|
|
|
46785
47016
|
return new MarketCatalog(this);
|
|
46786
47017
|
}
|
|
46787
47018
|
get funding() {
|
|
46788
|
-
return new FundingClient(this.program, this.options.connection, this.options.wallet.publicKey, (name2, offset2) => this.queue(name2, offset2));
|
|
47019
|
+
return new FundingClient(this.program, this.options.connection, this.options.wallet.publicKey, (name2, offset2) => this.queue(name2, offset2), this.options.settlement ?? (this.options.environment && this.options.environment !== "localnet" ? "keeper" : "wallet"));
|
|
46789
47020
|
}
|
|
46790
47021
|
get app() {
|
|
46791
47022
|
return new AppAdmin(this.program, this.options.connection, this.options.wallet.publicKey, this.funding);
|
|
@@ -46799,6 +47030,7 @@ class DepthClient {
|
|
|
46799
47030
|
}
|
|
46800
47031
|
constructor(options) {
|
|
46801
47032
|
this.options = options;
|
|
47033
|
+
this.views = new ViewCache(`${"manifest" in options.deployment ? options.deployment.manifest.payload.genesisHash : "localnet"}:${DEPTH_PROGRAM_ID7.toBase58()}:${options.wallet.publicKey.toBase58()}`, options.privateViews === "device" && "manifest" in options.deployment && typeof indexedDB !== "undefined" && globalThis.crypto?.subtle ? new DeviceViews : undefined);
|
|
46802
47034
|
this.provider = new DepthProvider(options.connection, options.wallet, {
|
|
46803
47035
|
commitment: "confirmed",
|
|
46804
47036
|
preflightCommitment: "confirmed"
|
|
@@ -46807,7 +47039,7 @@ class DepthClient {
|
|
|
46807
47039
|
this.position = this.positionActions();
|
|
46808
47040
|
}
|
|
46809
47041
|
static async create(options) {
|
|
46810
|
-
const appId = typeof options.appId === "string" ? new
|
|
47042
|
+
const appId = typeof options.appId === "string" ? new PublicKey10(options.appId) : options.appId;
|
|
46811
47043
|
const resolved = {
|
|
46812
47044
|
...options,
|
|
46813
47045
|
...await resolveConnection(options),
|
|
@@ -47025,7 +47257,7 @@ class DepthClient {
|
|
|
47025
47257
|
return this.funding.release(amount, clientNonce ?? BigInt(nonce().toString()));
|
|
47026
47258
|
}
|
|
47027
47259
|
async depositRequest(sourceOrAmount, amount, clientNonce) {
|
|
47028
|
-
if (sourceOrAmount instanceof
|
|
47260
|
+
if (sourceOrAmount instanceof PublicKey10) {
|
|
47029
47261
|
if (amount === undefined || clientNonce === undefined)
|
|
47030
47262
|
throw new RangeError("Source deposits require amount and client nonce");
|
|
47031
47263
|
return this.funding.deposit(sourceOrAmount, amount, clientNonce);
|
|
@@ -47036,7 +47268,7 @@ class DepthClient {
|
|
|
47036
47268
|
return this.funding.deposit(source, sourceOrAmount, amount ?? BigInt(nonce().toString()));
|
|
47037
47269
|
}
|
|
47038
47270
|
async withdrawRequest(destinationOrAmount, amount, clientNonce) {
|
|
47039
|
-
if (destinationOrAmount instanceof
|
|
47271
|
+
if (destinationOrAmount instanceof PublicKey10) {
|
|
47040
47272
|
if (amount === undefined || clientNonce === undefined)
|
|
47041
47273
|
throw new RangeError("Destination withdrawals require amount and client nonce");
|
|
47042
47274
|
return this.funding.withdraw(destinationOrAmount, amount, clientNonce);
|
|
@@ -47051,6 +47283,7 @@ class DepthClient {
|
|
|
47051
47283
|
}
|
|
47052
47284
|
accountActions() {
|
|
47053
47285
|
const actions = {
|
|
47286
|
+
state: () => balanceState(this.program, this.options.connection, this.options.wallet.publicKey, this.funding.balance),
|
|
47054
47287
|
detail: (item) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).detail(item),
|
|
47055
47288
|
transaction: (item) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).transaction(item),
|
|
47056
47289
|
history: (options) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).history(options),
|
|
@@ -47067,11 +47300,10 @@ class DepthClient {
|
|
|
47067
47300
|
summary: async (options = {
|
|
47068
47301
|
timeoutMs: 180000
|
|
47069
47302
|
}) => {
|
|
47070
|
-
const
|
|
47071
|
-
|
|
47072
|
-
|
|
47073
|
-
|
|
47074
|
-
return result;
|
|
47303
|
+
const state = await actions.state();
|
|
47304
|
+
if (state.status === "uninitialized")
|
|
47305
|
+
return { ...state, status: "uninitialized", amount: 0n };
|
|
47306
|
+
return this.summaryView("balance", state.id, options);
|
|
47075
47307
|
}
|
|
47076
47308
|
};
|
|
47077
47309
|
return Object.assign(() => actions, actions);
|
|
@@ -47107,29 +47339,7 @@ class DepthClient {
|
|
|
47107
47339
|
summary: async (options = {
|
|
47108
47340
|
timeoutMs: 180000
|
|
47109
47341
|
}) => {
|
|
47110
|
-
|
|
47111
|
-
let view;
|
|
47112
|
-
for (;; ) {
|
|
47113
|
-
try {
|
|
47114
|
-
view = await this.requestMarketView();
|
|
47115
|
-
break;
|
|
47116
|
-
} catch (error) {
|
|
47117
|
-
const code2 = error.error?.errorCode?.code;
|
|
47118
|
-
if (code2 !== "WrongMarketAccountStatus" && !String(error).includes("Market account is processing another operation")) {
|
|
47119
|
-
throw error;
|
|
47120
|
-
}
|
|
47121
|
-
if (Date.now() >= deadline)
|
|
47122
|
-
throw error;
|
|
47123
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
47124
|
-
}
|
|
47125
|
-
}
|
|
47126
|
-
const result = await view.wait({
|
|
47127
|
-
...options,
|
|
47128
|
-
timeoutMs: Math.max(0, deadline - Date.now())
|
|
47129
|
-
});
|
|
47130
|
-
if (result.status !== "pending")
|
|
47131
|
-
await view.close();
|
|
47132
|
-
return result;
|
|
47342
|
+
return this.summaryView("market", address2.toBase58(), options);
|
|
47133
47343
|
}
|
|
47134
47344
|
};
|
|
47135
47345
|
return Object.assign((positionId) => this.positionActions(positionId), actions);
|
|
@@ -47175,6 +47385,75 @@ class DepthClient {
|
|
|
47175
47385
|
u64(clientNonce, "clientNonce").toArrayLike(Buffer2, "le", 8)
|
|
47176
47386
|
]);
|
|
47177
47387
|
}
|
|
47388
|
+
async deferViewClose(kind, id) {
|
|
47389
|
+
const view = new PublicKey10(id);
|
|
47390
|
+
const method = kind === "balance" ? this.program.methods.closeBalanceView : this.program.methods.closeMarketView;
|
|
47391
|
+
this.provider.deferClose(view, await method().accountsPartial({
|
|
47392
|
+
owner: this.options.wallet.publicKey,
|
|
47393
|
+
view
|
|
47394
|
+
}).instruction());
|
|
47395
|
+
}
|
|
47396
|
+
async viewState(kind, id) {
|
|
47397
|
+
if (kind === "balance")
|
|
47398
|
+
return this.account().state();
|
|
47399
|
+
const state = await this.read("MarketAccount", new PublicKey10(id));
|
|
47400
|
+
if (!state.owner.equals(this.options.wallet.publicKey) || !state.market.equals(this.marketAddress))
|
|
47401
|
+
throw new Error("Position does not belong to this wallet and market");
|
|
47402
|
+
return {
|
|
47403
|
+
status: enumName2(state.status),
|
|
47404
|
+
version: BigInt(state.version.toString())
|
|
47405
|
+
};
|
|
47406
|
+
}
|
|
47407
|
+
summaryView(kind, id, options) {
|
|
47408
|
+
const key = `${kind}:${id}`;
|
|
47409
|
+
const pending = this.viewReads.get(key);
|
|
47410
|
+
if (pending)
|
|
47411
|
+
return pending;
|
|
47412
|
+
const request = this.readSummaryView(kind, id, options).finally(() => {
|
|
47413
|
+
if (this.viewReads.get(key) === request)
|
|
47414
|
+
this.viewReads.delete(key);
|
|
47415
|
+
});
|
|
47416
|
+
this.viewReads.set(key, request);
|
|
47417
|
+
return request;
|
|
47418
|
+
}
|
|
47419
|
+
async readSummaryView(kind, id, options) {
|
|
47420
|
+
if (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 0)
|
|
47421
|
+
throw new RangeError("timeoutMs must be a nonnegative integer");
|
|
47422
|
+
const deadline = Date.now() + options.timeoutMs;
|
|
47423
|
+
for (;; ) {
|
|
47424
|
+
const state = await this.viewState(kind, id);
|
|
47425
|
+
if (state.status === "ready") {
|
|
47426
|
+
const cached = await this.views.get(kind, id, state.version);
|
|
47427
|
+
if (cached) {
|
|
47428
|
+
await this.deferViewClose(kind, cached.id);
|
|
47429
|
+
return cached;
|
|
47430
|
+
}
|
|
47431
|
+
try {
|
|
47432
|
+
const view = kind === "balance" ? await this.requestBalanceView() : await this.requestMarketView();
|
|
47433
|
+
const result = await view.wait({
|
|
47434
|
+
...options,
|
|
47435
|
+
timeoutMs: Math.max(0, deadline - Date.now())
|
|
47436
|
+
});
|
|
47437
|
+
if (result.status === "pending")
|
|
47438
|
+
return result;
|
|
47439
|
+
await this.deferViewClose(kind, result.id);
|
|
47440
|
+
const latest = await this.viewState(kind, id);
|
|
47441
|
+
if (result.status === "ready" && latest.status === "ready" && latest.version === result.version) {
|
|
47442
|
+
const snapshot = { ...result, readAt: Date.now() };
|
|
47443
|
+
await this.views.set(kind, id, snapshot);
|
|
47444
|
+
return snapshot;
|
|
47445
|
+
}
|
|
47446
|
+
} catch (error) {
|
|
47447
|
+
const code2 = error.error?.errorCode?.code;
|
|
47448
|
+
if (code2 !== "WrongMarketAccountStatus" && !String(error).includes("processing another operation"))
|
|
47449
|
+
throw error;
|
|
47450
|
+
}
|
|
47451
|
+
}
|
|
47452
|
+
if (Date.now() >= deadline)
|
|
47453
|
+
throw new Error("Private account is still processing an operation");
|
|
47454
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(options.pollMs ?? 1000, deadline - Date.now())));
|
|
47455
|
+
}
|
|
47456
|
+
}
|
|
47178
47457
|
async submitTrade(input, intent) {
|
|
47179
47458
|
const appId = this.options.appId;
|
|
47180
47459
|
if (!appId)
|
|
@@ -47206,43 +47485,13 @@ class DepthClient {
|
|
|
47206
47485
|
throw new Error("Position does not belong to this wallet and market");
|
|
47207
47486
|
await this.ensureBalanceReady();
|
|
47208
47487
|
await this.ensureMarketReady();
|
|
47209
|
-
let [market, protocol, account, app] = await
|
|
47210
|
-
|
|
47211
|
-
this.read("Protocol", this.protocolAddress),
|
|
47212
|
-
this.read("MarketAccount", this.accountAddress()),
|
|
47213
|
-
this.read("AppConfig", appAddress2(appId))
|
|
47214
|
-
]);
|
|
47215
|
-
const deadline = tradeDeadline(input, Math.floor(Date.now() / 1000), market.state.config.maxOrderQueueSeconds);
|
|
47488
|
+
let [market, protocol, account, app] = await this.waitForMarket(input, appId, intent);
|
|
47489
|
+
let deadline;
|
|
47216
47490
|
tradeLimit(input, "long", BigInt(market.state.oraclePriceE8.toString()));
|
|
47217
|
-
this.validateTrade(market.state, protocol, account, app, appId, intent, deadline);
|
|
47218
47491
|
if (additionalMargin > 0n) {
|
|
47219
47492
|
const transfer = await this.funding.allocate(additionalMargin, clientNonce);
|
|
47220
|
-
|
|
47221
|
-
|
|
47222
|
-
const current = await transfer.status();
|
|
47223
|
-
if (current.state === "settled")
|
|
47224
|
-
break;
|
|
47225
|
-
if (current.state === "rejected" || current.state === "refunded")
|
|
47226
|
-
throw new Error(`Margin allocation ${transfer.id.toBase58()} ${current.state}`);
|
|
47227
|
-
if (current.state === "escrow") {
|
|
47228
|
-
try {
|
|
47229
|
-
await transfer.settle();
|
|
47230
|
-
} catch (error) {
|
|
47231
|
-
if ((await transfer.status()).state === "escrow")
|
|
47232
|
-
throw error;
|
|
47233
|
-
}
|
|
47234
|
-
}
|
|
47235
|
-
if (Date.now() >= allocationDeadline)
|
|
47236
|
-
throw new Error(`Margin allocation ${transfer.id.toBase58()} is pending`);
|
|
47237
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
47238
|
-
}
|
|
47239
|
-
[market, protocol, account, app] = await Promise.all([
|
|
47240
|
-
this.market(),
|
|
47241
|
-
this.read("Protocol", this.protocolAddress),
|
|
47242
|
-
this.read("MarketAccount", this.accountAddress()),
|
|
47243
|
-
this.read("AppConfig", appAddress2(appId))
|
|
47244
|
-
]);
|
|
47245
|
-
this.validateTrade(market.state, protocol, account, app, appId, intent, deadline);
|
|
47493
|
+
await transfer.confirm({ timeoutMs: 120000 });
|
|
47494
|
+
[market, protocol, account, app] = await this.waitForMarket(input, appId, intent);
|
|
47246
47495
|
}
|
|
47247
47496
|
const viewDeadline = Date.now() + 120000;
|
|
47248
47497
|
let position;
|
|
@@ -47260,15 +47509,13 @@ class DepthClient {
|
|
|
47260
47509
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
47261
47510
|
continue;
|
|
47262
47511
|
}
|
|
47263
|
-
[market, account] = await
|
|
47264
|
-
this.market(),
|
|
47265
|
-
this.read("MarketAccount", this.accountAddress())
|
|
47266
|
-
]);
|
|
47512
|
+
[market, protocol, account, app] = await this.waitForMarket(input, appId, intent);
|
|
47267
47513
|
if (position.status === "ready" && enumName2(account.status) === "ready" && account.version.toString() === position.version.toString()) {
|
|
47268
47514
|
break;
|
|
47269
47515
|
}
|
|
47270
47516
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
47271
47517
|
}
|
|
47518
|
+
deadline = tradeDeadline(input, Math.floor(Date.now() / 1000), market.state.config.maxOrderQueueSeconds);
|
|
47272
47519
|
this.validateTrade(market.state, protocol, account, app, appId, intent, deadline);
|
|
47273
47520
|
if (position.status !== "ready" || position.collateral === undefined || position.position === undefined)
|
|
47274
47521
|
throw new Error(`Private position view ${position.id} is ${position.status}`);
|
|
@@ -47338,6 +47585,29 @@ class DepthClient {
|
|
|
47338
47585
|
]).rpc({ commitment: "confirmed" }).catch((error) => submissionError(order.toBase58(), error));
|
|
47339
47586
|
return new DepthOperation(order, signature, this.program, this.options.connection, (id) => this.requestFillView(id), position);
|
|
47340
47587
|
}
|
|
47588
|
+
async waitForMarket(input, appId, intent) {
|
|
47589
|
+
const until = Date.now() + 60000;
|
|
47590
|
+
for (;; ) {
|
|
47591
|
+
const [market, protocol, account, app] = await Promise.all([
|
|
47592
|
+
this.market(),
|
|
47593
|
+
this.read("Protocol", this.protocolAddress),
|
|
47594
|
+
this.read("MarketAccount", this.accountAddress()),
|
|
47595
|
+
this.read("AppConfig", appAddress2(appId))
|
|
47596
|
+
]);
|
|
47597
|
+
const deadline = tradeDeadline(input, Math.floor(Date.now() / 1000), market.state.config.maxOrderQueueSeconds);
|
|
47598
|
+
try {
|
|
47599
|
+
this.validateTrade(market.state, protocol, account, app, appId, intent, deadline);
|
|
47600
|
+
return [market, protocol, account, app];
|
|
47601
|
+
} catch (error) {
|
|
47602
|
+
if (!(error instanceof Error) || ![
|
|
47603
|
+
"Waiting for maker liquidity",
|
|
47604
|
+
"Market is processing another order"
|
|
47605
|
+
].includes(error.message) || Date.now() >= until)
|
|
47606
|
+
throw error;
|
|
47607
|
+
}
|
|
47608
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
47609
|
+
}
|
|
47610
|
+
}
|
|
47341
47611
|
validateTrade(market, protocol, account, app, appId, intent = "increase", deadline) {
|
|
47342
47612
|
const now = Math.floor(Date.now() / 1000);
|
|
47343
47613
|
const marketStatus = enumName2(market.status);
|
|
@@ -47350,9 +47620,10 @@ class DepthClient {
|
|
|
47350
47620
|
if (enumName2(account.status) !== "ready" || !account.market.equals(this.marketAddress) || !account.owner.equals(this.options.wallet.publicKey)) {
|
|
47351
47621
|
throw new Error("Market account is unavailable");
|
|
47352
47622
|
}
|
|
47353
|
-
if (market.pendingOrders !== 0
|
|
47354
|
-
throw new Error("Market is processing another order
|
|
47355
|
-
|
|
47623
|
+
if (market.pendingOrders !== 0)
|
|
47624
|
+
throw new Error("Market is processing another order");
|
|
47625
|
+
if (market.activeQuoteCount === 0)
|
|
47626
|
+
throw new Error("Waiting for maker liquidity");
|
|
47356
47627
|
const age = now - market.oracleTimestamp.toNumber();
|
|
47357
47628
|
if (age < 0 || age > market.config.maxOracleAgeSeconds) {
|
|
47358
47629
|
throw new Error("Oracle update is stale");
|
|
@@ -47506,6 +47777,7 @@ export {
|
|
|
47506
47777
|
verifyDeployment,
|
|
47507
47778
|
resolveConnection,
|
|
47508
47779
|
resolveAmount,
|
|
47780
|
+
prepare_depth,
|
|
47509
47781
|
positionPnl,
|
|
47510
47782
|
manifestBytes,
|
|
47511
47783
|
create_depth_data,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { BalanceSnapshot, PositionSnapshot } from "./view.js";
|
|
2
|
+
type Snapshot = BalanceSnapshot | PositionSnapshot;
|
|
3
|
+
type Kind = "balance" | "market";
|
|
4
|
+
type Envelope = {
|
|
5
|
+
iv: Uint8Array;
|
|
6
|
+
data: ArrayBuffer;
|
|
7
|
+
};
|
|
8
|
+
export interface ViewStorage {
|
|
9
|
+
key(scope: string, proposed: CryptoKey): Promise<CryptoKey>;
|
|
10
|
+
read(id: string): Promise<Envelope | undefined>;
|
|
11
|
+
write(id: string, value: Envelope): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export declare class DeviceViews implements ViewStorage {
|
|
14
|
+
private database?;
|
|
15
|
+
private open;
|
|
16
|
+
key(scope: string, proposed: CryptoKey): Promise<CryptoKey>;
|
|
17
|
+
read(id: string): Promise<Envelope | undefined>;
|
|
18
|
+
write(id: string, value: Envelope): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare class ViewCache {
|
|
21
|
+
private readonly scope;
|
|
22
|
+
private readonly storage?;
|
|
23
|
+
private readonly memory;
|
|
24
|
+
private key?;
|
|
25
|
+
constructor(scope: string, storage?: ViewStorage | undefined);
|
|
26
|
+
private encryptionKey;
|
|
27
|
+
private id;
|
|
28
|
+
get<T extends Snapshot>(kind: Kind, account: string, version: bigint): Promise<T | undefined>;
|
|
29
|
+
set(kind: Kind, account: string, snapshot: Snapshot): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
package/dist/view/view.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as anchor from "@anchor-lang/core";
|
|
2
2
|
import { Connection, PublicKey } from "@solana/web3.js";
|
|
3
3
|
export type BalanceSnapshot = {
|
|
4
|
-
status: "pending" | "ready" | "stale";
|
|
4
|
+
status: "uninitialized" | "pending" | "ready" | "stale";
|
|
5
5
|
id: string;
|
|
6
6
|
version: bigint;
|
|
7
|
+
readAt?: number;
|
|
7
8
|
slot: number;
|
|
8
9
|
amount?: bigint;
|
|
9
10
|
};
|
|
@@ -11,6 +12,7 @@ export type PositionSnapshot = {
|
|
|
11
12
|
status: "pending" | "ready" | "stale";
|
|
12
13
|
id: string;
|
|
13
14
|
version: bigint;
|
|
15
|
+
readAt?: number;
|
|
14
16
|
slot: number;
|
|
15
17
|
collateral?: bigint;
|
|
16
18
|
reserved?: bigint;
|
|
@@ -55,5 +57,7 @@ export declare class DepthView {
|
|
|
55
57
|
timeoutMs: number;
|
|
56
58
|
pollMs?: number;
|
|
57
59
|
}): Promise<BalanceSnapshot | PositionSnapshot | FillSnapshot | QuoteBalanceSnapshot>;
|
|
60
|
+
deferClose(): Promise<void>;
|
|
61
|
+
private closeBuilder;
|
|
58
62
|
close(): Promise<string>;
|
|
59
63
|
}
|
package/dist/view/view.js
CHANGED
|
@@ -26667,13 +26667,28 @@ class DepthView {
|
|
|
26667
26667
|
await new Promise((resolve) => setTimeout(resolve, Math.min(pollMs, deadline - Date.now())));
|
|
26668
26668
|
}
|
|
26669
26669
|
}
|
|
26670
|
+
async deferClose() {
|
|
26671
|
+
const provider = this.program.provider;
|
|
26672
|
+
if (typeof provider.deferClose !== "function") {
|
|
26673
|
+
await this.close();
|
|
26674
|
+
return;
|
|
26675
|
+
}
|
|
26676
|
+
const snapshot = await this.status();
|
|
26677
|
+
if (snapshot.status === "pending")
|
|
26678
|
+
throw new Error("Private view computation is still pending");
|
|
26679
|
+
const instruction = await this.closeBuilder().instruction();
|
|
26680
|
+
provider.deferClose(this.id, instruction);
|
|
26681
|
+
}
|
|
26682
|
+
closeBuilder() {
|
|
26683
|
+
const builder = this.kind === "balance" ? this.program.methods.closeBalanceView() : this.kind === "market" ? this.program.methods.closeMarketView() : this.kind === "fill" ? this.program.methods.closeFillView() : this.program.methods.closeQuoteView();
|
|
26684
|
+
return builder.accountsPartial({ owner: this.owner, view: this.id });
|
|
26685
|
+
}
|
|
26670
26686
|
async close() {
|
|
26671
26687
|
const snapshot = await this.status();
|
|
26672
26688
|
if (snapshot.status === "pending") {
|
|
26673
26689
|
throw new Error("Private view computation is still pending");
|
|
26674
26690
|
}
|
|
26675
|
-
|
|
26676
|
-
return builder.accountsPartial({ owner: this.owner, view: this.id }).rpc({ commitment: "confirmed" });
|
|
26691
|
+
return this.closeBuilder().rpc({ commitment: "confirmed" });
|
|
26677
26692
|
}
|
|
26678
26693
|
}
|
|
26679
26694
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depthhq/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -44,8 +44,11 @@
|
|
|
44
44
|
"@noble/hashes": "1.8.0",
|
|
45
45
|
"@solana/web3.js": "1.99.0",
|
|
46
46
|
"buffer": "6.0.3",
|
|
47
|
-
"@depthhq/
|
|
48
|
-
"@depthhq/
|
|
47
|
+
"@depthhq/bindings": "0.1.1",
|
|
48
|
+
"@depthhq/schema": "0.1.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"fake-indexeddb": "6.2.4"
|
|
49
52
|
},
|
|
50
53
|
"scripts": {
|
|
51
54
|
"build": "node ../../scripts/build-package.mjs sdk",
|