@depthhq/sdk 0.1.0 → 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.
@@ -1,5 +1,6 @@
1
1
  import * as anchor from "@anchor-lang/core";
2
2
  import { Connection, PublicKey } from "@solana/web3.js";
3
+ import { type ReceiptTransaction } from "../chain/transaction.js";
3
4
  export type PendingKind = "deposit" | "allocation" | "release" | "withdrawal" | "trade" | "risk";
4
5
  export type PendingItem = {
5
6
  id: PublicKey;
@@ -11,6 +12,9 @@ export type PendingPage = {
11
12
  items: PendingItem[];
12
13
  nextCursor?: string;
13
14
  };
15
+ export type ReceiptDetail = ReceiptTransaction & {
16
+ amount?: bigint;
17
+ };
14
18
  export type UnpairedAllocation = {
15
19
  id: PublicKey;
16
20
  nonce: bigint;
@@ -23,6 +27,8 @@ export declare class FundingDiscovery {
23
27
  private readonly connection;
24
28
  private readonly owner;
25
29
  constructor(program: anchor.Program, connection: Connection, owner: PublicKey);
30
+ transaction(item: PendingItem): Promise<ReceiptDetail>;
31
+ detail(item: PendingItem): Promise<ReceiptDetail>;
26
32
  unpairedAllocations(options?: {
27
33
  cursor?: string;
28
34
  limit?: number;
@@ -0,0 +1,15 @@
1
+ import * as anchor from "@anchor-lang/core";
2
+ import type { Connection, PublicKey, VersionedTransactionResponse } from "@solana/web3.js";
3
+ export type SettlementTransaction = {
4
+ signature: string;
5
+ slot: number;
6
+ orderId: PublicKey;
7
+ timestamp?: number;
8
+ };
9
+ export declare function settlementOrder(transaction: VersionedTransactionResponse, program: anchor.Program): PublicKey | undefined;
10
+ export declare function settlementTransaction(connection: Connection, program: anchor.Program, address: PublicKey, match: {
11
+ orderId: PublicKey;
12
+ } | {
13
+ trader: PublicKey;
14
+ market: PublicKey;
15
+ }): Promise<SettlementTransaction>;
@@ -0,0 +1,12 @@
1
+ import * as anchor from "@anchor-lang/core";
2
+ import type { Connection, PublicKey, VersionedTransactionResponse } from "@solana/web3.js";
3
+ export type ReceiptTransaction = {
4
+ signature: string;
5
+ slot: number;
6
+ timestamp?: number;
7
+ };
8
+ export declare function depthInstructions(transaction: VersionedTransactionResponse, program: anchor.Program): {
9
+ definition: anchor.IdlInstruction;
10
+ accounts: (anchor.web3.PublicKey | undefined)[];
11
+ }[];
12
+ export declare function receiptTransaction(connection: Connection, program: anchor.Program, address: PublicKey, names?: readonly string[]): Promise<ReceiptTransaction>;
@@ -7,6 +7,7 @@ import { FundingDiscovery } from "../account/discovery.js";
7
7
  import { FundingClient } from "../account/funding.js";
8
8
  import { DepthOperation } from "../operation/operation.js";
9
9
  import { DepthRecovery } from "../recovery/recovery.js";
10
+ import { ExecutionHistory } from "../history/history.js";
10
11
  import type { AmountSelector } from "../trade/amount.js";
11
12
  import { TradeFlow } from "../trade/flow.js";
12
13
  import { DepthView } from "../view/view.js";
@@ -24,6 +25,8 @@ export declare class DepthClient {
24
25
  get funding(): FundingClient;
25
26
  get app(): AppAdmin;
26
27
  get recovery(): DepthRecovery;
28
+ private historyClient?;
29
+ get history(): ExecutionHistory;
27
30
  private constructor();
28
31
  static create(options: DepthOptions): Promise<DepthClient>;
29
32
  private verifyDeployment;
@@ -48,6 +51,8 @@ export declare class DepthClient {
48
51
  private withdrawRequest;
49
52
  private accountActions;
50
53
  readonly account: (() => {
54
+ detail: (item: Parameters<FundingDiscovery["detail"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
55
+ transaction: (item: Parameters<FundingDiscovery["transaction"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
51
56
  history: (options?: Parameters<FundingDiscovery["history"]>[0]) => Promise<import("../account/discovery.js").PendingPage>;
52
57
  pending: (options?: Parameters<FundingDiscovery["pending"]>[0]) => Promise<import("../account/discovery.js").PendingPage>;
53
58
  cancelOpen: () => Promise<string>;
@@ -73,6 +78,8 @@ export declare class DepthClient {
73
78
  pollMs?: number;
74
79
  }) => Promise<BalanceSnapshot>;
75
80
  }) & {
81
+ detail: (item: Parameters<FundingDiscovery["detail"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
82
+ transaction: (item: Parameters<FundingDiscovery["transaction"]>[0]) => Promise<import("../account/discovery.js").ReceiptDetail>;
76
83
  history: (options?: Parameters<FundingDiscovery["history"]>[0]) => Promise<import("../account/discovery.js").PendingPage>;
77
84
  pending: (options?: Parameters<FundingDiscovery["pending"]>[0]) => Promise<import("../account/discovery.js").PendingPage>;
78
85
  cancelOpen: () => Promise<string>;
@@ -98,5 +98,8 @@ export type OrderState = {
98
98
  status: Record<string, unknown>;
99
99
  kind: Record<string, unknown>;
100
100
  trader: PublicKey;
101
+ maker?: PublicKey;
101
102
  market: PublicKey;
103
+ traderVersion: anchor.BN;
104
+ fundingIndex: anchor.BN;
102
105
  };
@@ -0,0 +1,26 @@
1
+ import * as anchor from "@anchor-lang/core";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ import type { DepthView, FillSnapshot } from "../view/view.js";
4
+ import { type SettlementTransaction } from "../chain/settlement.js";
5
+ import type { PositionPnl } from "../position/pnl.js";
6
+ export type ExecutionDetail = {
7
+ id: PublicKey;
8
+ fill: FillSnapshot;
9
+ pnl?: PositionPnl;
10
+ transaction: SettlementTransaction;
11
+ };
12
+ export declare class ExecutionHistory {
13
+ private readonly program;
14
+ private readonly connection;
15
+ private readonly owner;
16
+ private readonly requestView;
17
+ private readonly views;
18
+ private readonly fills;
19
+ private readonly transactions;
20
+ constructor(program: anchor.Program, connection: Connection, owner: PublicKey, requestView: (id: PublicKey) => Promise<DepthView>);
21
+ private orderAddress;
22
+ fill(id: PublicKey): Promise<FillSnapshot>;
23
+ execution(nonce: bigint): Promise<ExecutionDetail>;
24
+ private settlement;
25
+ private scan;
26
+ }
@@ -0,0 +1,13 @@
1
+ import type { FillSnapshot } from "../view/view.js";
2
+ import { type PositionPnl } from "../position/pnl.js";
3
+ export type ReplayState = {
4
+ position: bigint;
5
+ entryPriceE8: bigint;
6
+ fundingCheckpoint: bigint;
7
+ collateral?: bigint;
8
+ };
9
+ export declare function replayFill(state: ReplayState, fill: FillSnapshot, fundingIndex: bigint, maker?: boolean): {
10
+ state: ReplayState;
11
+ pnl?: PositionPnl;
12
+ };
13
+ export declare function replayMargin(state: ReplayState, amount: bigint, toMarket: boolean): ReplayState;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  export { DepthClient, createDepth, createDepth as create_depth, } from "./client/client.js";
2
2
  export { DepthOperation } from "./operation/operation.js";
3
+ export { ExecutionHistory } from "./history/history.js";
4
+ export type { ExecutionDetail } from "./history/history.js";
5
+ export type { PositionPnl } from "./position/pnl.js";
6
+ export { positionPnl } from "./position/pnl.js";
7
+ export type { SettlementTransaction } from "./chain/settlement.js";
8
+ export type { ReceiptTransaction } from "./chain/transaction.js";
3
9
  export { TradeFlow } from "./trade/flow.js";
4
10
  export type { TradeFlowSnapshot } from "./trade/flow.js";
5
11
  export { MarketCatalog } from "./catalog/catalog.js";
@@ -9,6 +15,7 @@ export type { DataOptions, CandleQuery } from "./catalog/data.js";
9
15
  export type { Candle, CandleInterval, CandlePage, PublicMarket, PublicApp, } from "@depthhq/schema";
10
16
  export { AppAdmin, AppRegistration, AppUpdate } from "./app/app.js";
11
17
  export { FundingDiscovery } from "./account/discovery.js";
18
+ export type { ReceiptDetail } from "./account/discovery.js";
12
19
  export type { PendingItem, PendingKind, PendingPage, UnpairedAllocation, } from "./account/discovery.js";
13
20
  export type { AppSummary } from "./app/app.js";
14
21
  export { DepthRecovery } from "./recovery/recovery.js";
package/dist/index.js CHANGED
@@ -18122,7 +18122,7 @@ https://github.com/browserify/crypto-browserify`);
18122
18122
 
18123
18123
  // src/client/client.ts
18124
18124
  init_buffer();
18125
- import * as anchor6 from "@anchor-lang/core";
18125
+ import * as anchor8 from "@anchor-lang/core";
18126
18126
 
18127
18127
  // ../../node_modules/@noble/hashes/esm/crypto.js
18128
18128
  var crypto2 = typeof globalThis === "object" && "crypto" in globalThis ? globalThis.crypto : undefined;
@@ -43623,12 +43623,12 @@ import {
43623
43623
  computationName,
43624
43624
  DEPTH_IDL as DEPTH_IDL3,
43625
43625
  DEPTH_PROGRAM_ID as DEPTH_PROGRAM_ID7,
43626
- marketAddress as marketAddress6,
43626
+ marketAddress as marketAddress7,
43627
43627
  protocolAddress as protocolAddress4,
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 PublicKey8 } from "@solana/web3.js";
43631
+ import { PublicKey as PublicKey9 } from "@solana/web3.js";
43632
43632
 
43633
43633
  // src/chain/random.ts
43634
43634
  function randomBytes3(length) {
@@ -44625,7 +44625,7 @@ async function upgradeAuthority(connection) {
44625
44625
  if (!program?.executable || !program.owner.equals(loader) || program.data.length !== 36 || program.data.readUInt32LE(0) !== 2) {
44626
44626
  throw unavailable("Depth program is not deployed as an upgradeable program");
44627
44627
  }
44628
- const data = await connection.getAccountInfo(new PublicKey3(program.data.subarray(4)), "confirmed");
44628
+ const data = await connection.getAccountInfo(new PublicKey3(program.data.subarray(4)), { commitment: "confirmed", dataSlice: { offset: 0, length: 45 } });
44629
44629
  if (!data?.owner.equals(loader) || data.data.length < 45 || data.data.readUInt32LE(0) !== 3 || data.data[12] !== 1) {
44630
44630
  throw unavailable("Depth deployment has no verifiable upgrade authority");
44631
44631
  }
@@ -44999,6 +44999,124 @@ import {
44999
44999
  withdrawalAddress
45000
45000
  } from "@depthhq/bindings";
45001
45001
  import { PublicKey as PublicKey4 } from "@solana/web3.js";
45002
+
45003
+ // src/chain/transaction.ts
45004
+ init_buffer();
45005
+ import * as anchor4 from "@anchor-lang/core";
45006
+ function depthInstructions(transaction, program) {
45007
+ if (!transaction.meta || transaction.meta.err)
45008
+ return [];
45009
+ const keys = transaction.transaction.message.getAccountKeys({
45010
+ accountKeysFromLookups: transaction.meta.loadedAddresses
45011
+ });
45012
+ const instructions2 = [
45013
+ ...transaction.transaction.message.compiledInstructions.map((ix) => ({
45014
+ programIdIndex: ix.programIdIndex,
45015
+ accounts: ix.accountKeyIndexes,
45016
+ data: Buffer2.from(ix.data)
45017
+ })),
45018
+ ...(transaction.meta.innerInstructions ?? []).flatMap((group) => group.instructions.map((ix) => ({
45019
+ programIdIndex: ix.programIdIndex,
45020
+ accounts: ix.accounts,
45021
+ data: Buffer2.from(anchor4.utils.bytes.bs58.decode(ix.data))
45022
+ })))
45023
+ ];
45024
+ return instructions2.flatMap((ix) => {
45025
+ if (!keys.get(ix.programIdIndex)?.equals(program.programId))
45026
+ return [];
45027
+ let definition = program.idl.instructions.find((item) => ix.data.subarray(0, 8).equals(Buffer2.from(item.discriminator)));
45028
+ if (!definition && ix.data.subarray(0, 8).equals(Buffer2.from("057da1a57b4b7ec6", "hex"))) {
45029
+ const current = program.idl.instructions.find((item) => item.name === "debitMarketV2Callback");
45030
+ if (current)
45031
+ definition = { ...current, name: "debitMarketCallback" };
45032
+ }
45033
+ return definition ? [{ definition, accounts: ix.accounts.map((index) => keys.get(index)) }] : [];
45034
+ });
45035
+ }
45036
+ async function receiptTransaction(connection, program, address2, names) {
45037
+ let before;
45038
+ for (let page = 0;page < 10; page++) {
45039
+ const signatures = await connection.getSignaturesForAddress(address2, { before, limit: 50 }, "confirmed");
45040
+ for (const signature of signatures) {
45041
+ if (signature.err)
45042
+ continue;
45043
+ const transaction = await connection.getTransaction(signature.signature, {
45044
+ commitment: "confirmed",
45045
+ maxSupportedTransactionVersion: 0
45046
+ });
45047
+ if (!transaction)
45048
+ throw new Error("Transaction history is unavailable; retry with an archival RPC");
45049
+ const changed = depthInstructions(transaction, program).some((ix) => (!names || names.includes(ix.definition.name)) && ix.definition.accounts.some((account, index) => ("writable" in account) && account.writable && ix.accounts[index]?.equals(address2)));
45050
+ if (changed)
45051
+ return {
45052
+ signature: signature.signature,
45053
+ slot: signature.slot,
45054
+ ...transaction.blockTime == null ? {} : { timestamp: transaction.blockTime }
45055
+ };
45056
+ }
45057
+ if (signatures.length < 50)
45058
+ break;
45059
+ before = signatures.at(-1).signature;
45060
+ }
45061
+ throw new Error(`Receipt transaction for ${address2.toBase58()} was not found in recent history`);
45062
+ }
45063
+
45064
+ // src/chain/settlement.ts
45065
+ function settlementOrder(transaction, program) {
45066
+ const instruction = depthInstructions(transaction, program).find((ix) => ix.definition.name === "sealClearingCallback");
45067
+ if (!instruction)
45068
+ return;
45069
+ const orderIndex = instruction.definition.accounts.findIndex((account) => account.name === "order");
45070
+ if (orderIndex < 0)
45071
+ throw new Error("Settlement callback has no order account");
45072
+ return instruction.accounts[orderIndex];
45073
+ }
45074
+ async function settlementTransaction(connection, program, address2, match) {
45075
+ let before;
45076
+ for (let page = 0;page < 10; page++) {
45077
+ const signatures = await connection.getSignaturesForAddress(address2, { before, limit: 50 }, "confirmed");
45078
+ for (const signature of signatures) {
45079
+ if (signature.err)
45080
+ continue;
45081
+ const transaction = await connection.getTransaction(signature.signature, {
45082
+ commitment: "confirmed",
45083
+ maxSupportedTransactionVersion: 0
45084
+ });
45085
+ if (!transaction)
45086
+ throw new Error("Transaction history is unavailable; retry with an archival RPC");
45087
+ const orderId = settlementOrder(transaction, program);
45088
+ if (!orderId)
45089
+ continue;
45090
+ if ("orderId" in match) {
45091
+ if (orderId.equals(match.orderId))
45092
+ return {
45093
+ signature: signature.signature,
45094
+ slot: signature.slot,
45095
+ orderId,
45096
+ ...transaction.blockTime == null ? {} : { timestamp: transaction.blockTime }
45097
+ };
45098
+ } else {
45099
+ const info = await connection.getAccountInfo(orderId, "confirmed");
45100
+ if (!info?.owner.equals(program.programId))
45101
+ throw new Error("Settlement receipt is unavailable");
45102
+ const order = program.coder.accounts.decode("orderRecord", info.data);
45103
+ if (order.trader.equals(match.trader) && order.market.equals(match.market) && "trade" in order.kind && "filled" in order.status)
45104
+ return {
45105
+ signature: signature.signature,
45106
+ slot: signature.slot,
45107
+ orderId,
45108
+ ...transaction.blockTime == null ? {} : { timestamp: transaction.blockTime }
45109
+ };
45110
+ }
45111
+ }
45112
+ if (signatures.length < 50)
45113
+ break;
45114
+ before = signatures.at(-1).signature;
45115
+ }
45116
+ throw new Error("Settlement transaction was not found in recent history");
45117
+ }
45118
+
45119
+ // src/account/discovery.ts
45002
45120
  function status(state) {
45003
45121
  return Object.keys(state.status)[0] ?? "unknown";
45004
45122
  }
@@ -45012,6 +45130,28 @@ class FundingDiscovery {
45012
45130
  this.connection = connection;
45013
45131
  this.owner = owner;
45014
45132
  }
45133
+ async transaction(item) {
45134
+ return this.detail(item);
45135
+ }
45136
+ async detail(item) {
45137
+ const name2 = item.kind === "deposit" ? "depositReceipt" : item.kind === "withdrawal" ? "withdrawalReceipt" : item.kind === "allocation" || item.kind === "release" ? "marginTransfer" : "orderRecord";
45138
+ const info = await this.connection.getAccountInfo(item.id, "confirmed");
45139
+ if (!info?.owner.equals(this.program.programId))
45140
+ throw new Error("Receipt is unavailable");
45141
+ const state = this.program.coder.accounts.decode(name2, info.data);
45142
+ const canonical = this.project(name2, item.id, state, true);
45143
+ if (!canonical || canonical.kind !== item.kind || canonical.nonce !== item.nonce)
45144
+ throw new Error("Receipt does not match this wallet and operation");
45145
+ if ((canonical.kind === "trade" || canonical.kind === "risk") && canonical.status === "filled")
45146
+ return settlementTransaction(this.connection, this.program, item.id, {
45147
+ orderId: item.id
45148
+ });
45149
+ const transaction = await receiptTransaction(this.connection, this.program, item.id);
45150
+ return {
45151
+ ...transaction,
45152
+ ...state.amount === undefined ? {} : { amount: BigInt(state.amount.toString()) }
45153
+ };
45154
+ }
45015
45155
  async unpairedAllocations(options = {}) {
45016
45156
  const limit = options.limit ?? 20;
45017
45157
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
@@ -45216,7 +45356,7 @@ class FundingDiscovery {
45216
45356
  }
45217
45357
 
45218
45358
  // src/account/funding.ts
45219
- import * as anchor5 from "@anchor-lang/core";
45359
+ import * as anchor6 from "@anchor-lang/core";
45220
45360
  import {
45221
45361
  balanceAddress,
45222
45362
  depositAddress as depositAddress2,
@@ -45246,7 +45386,7 @@ async function confirmReceipt(id, status2, advance, options = {}) {
45246
45386
  }
45247
45387
 
45248
45388
  // src/trade/input.ts
45249
- import * as anchor4 from "@anchor-lang/core";
45389
+ import * as anchor5 from "@anchor-lang/core";
45250
45390
  function encodeSide(direction) {
45251
45391
  if (direction !== "long" && direction !== "short")
45252
45392
  throw new RangeError("Direction must be long or short");
@@ -45256,12 +45396,12 @@ function u64(value2, name2) {
45256
45396
  if (typeof value2 !== "bigint" || value2 < 0n || value2 > (1n << 64n) - 1n) {
45257
45397
  throw new RangeError(`${name2} must be an unsigned 64-bit bigint`);
45258
45398
  }
45259
- return new anchor4.BN(value2.toString());
45399
+ return new anchor5.BN(value2.toString());
45260
45400
  }
45261
45401
 
45262
45402
  // src/account/funding.ts
45263
45403
  function offset() {
45264
- return new anchor5.BN(randomBytes3(8), "le");
45404
+ return new anchor6.BN(randomBytes3(8), "le");
45265
45405
  }
45266
45406
  function status2(value2) {
45267
45407
  return Object.keys(value2)[0] ?? "unknown";
@@ -45770,6 +45910,42 @@ import {
45770
45910
  SOL_USD_MARKET_ID as SOL_USD_MARKET_ID2
45771
45911
  } from "@depthhq/bindings";
45772
45912
  import { PublicKey as PublicKey6 } from "@solana/web3.js";
45913
+
45914
+ // src/position/pnl.ts
45915
+ var scale = 100000000000n;
45916
+ function positionPnl(position, priceE8, fundingIndex, fill) {
45917
+ if (position.status !== "ready" || position.position === undefined || position.position === 0n || position.entryPriceE8 === undefined || position.fundingCheckpoint === undefined || position.collateral !== undefined && position.collateral < 0n || priceE8 <= 0n)
45918
+ throw new Error("A ready open position and a positive price are required");
45919
+ const size = position.position < 0n ? -position.position : position.position;
45920
+ const sign = position.position > 0n ? 1n : -1n;
45921
+ let closing = size;
45922
+ let fee = 0n;
45923
+ let state = "open";
45924
+ if (fill) {
45925
+ if (fill.status !== "ready" || fill.side !== -sign || fill.size === undefined || fill.size <= 0n || fill.executionPriceE8 !== priceE8 || fill.fee === undefined || fill.fee < 0n)
45926
+ throw new Error("A ready opposite-side execution is required");
45927
+ closing = fill.size < size ? fill.size : size;
45928
+ fee = fill.fee;
45929
+ state = fill.size === size ? "closed" : fill.size < size ? "reduced" : "reversed";
45930
+ }
45931
+ const gross = sign * closing * (priceE8 - position.entryPriceE8) / scale;
45932
+ const funding = position.position * (fundingIndex - position.fundingCheckpoint) / scale;
45933
+ const net = gross - funding - fee;
45934
+ return {
45935
+ side: sign > 0n ? "long" : "short",
45936
+ state,
45937
+ entryPriceE8: position.entryPriceE8,
45938
+ priceE8,
45939
+ collateral: position.collateral ?? null,
45940
+ gross,
45941
+ funding,
45942
+ fee,
45943
+ net,
45944
+ returnBps: position.collateral !== undefined && position.collateral > 0n ? net * 10000n / position.collateral : null
45945
+ };
45946
+ }
45947
+
45948
+ // src/operation/operation.ts
45773
45949
  function enumName(value2) {
45774
45950
  return Object.keys(value2)[0] ?? "unknown";
45775
45951
  }
@@ -45780,15 +45956,40 @@ class DepthOperation {
45780
45956
  program;
45781
45957
  connection;
45782
45958
  requestFillView;
45959
+ priorPosition;
45960
+ historicalPnl;
45783
45961
  viewPromise;
45784
45962
  view;
45785
45963
  fill;
45786
- constructor(id, signature, program, connection, requestFillView) {
45964
+ settlement;
45965
+ constructor(id, signature, program, connection, requestFillView, priorPosition, historicalPnl) {
45787
45966
  this.id = id;
45788
45967
  this.signature = signature;
45789
45968
  this.program = program;
45790
45969
  this.connection = connection;
45791
45970
  this.requestFillView = requestFillView;
45971
+ this.priorPosition = priorPosition;
45972
+ this.historicalPnl = historicalPnl;
45973
+ }
45974
+ async transaction() {
45975
+ if (this.settlement)
45976
+ return this.settlement;
45977
+ const snapshot = await this.status();
45978
+ if (snapshot.status !== "finalized" || snapshot.outcome !== "filled")
45979
+ throw new Error("Confirm the trade before reading its settlement transaction");
45980
+ this.settlement = await settlementTransaction(this.connection, this.program, this.id, { orderId: this.id });
45981
+ return this.settlement;
45982
+ }
45983
+ async pnl() {
45984
+ if (!this.priorPosition && this.historicalPnl)
45985
+ return this.historicalPnl();
45986
+ const { order } = await this.readOrder();
45987
+ if (!this.priorPosition || this.priorPosition.version !== BigInt(order.traderVersion.toString()))
45988
+ throw new Error("The private position before this execution is unavailable");
45989
+ const fill = await this.privateResult();
45990
+ if (fill.executionPriceE8 === undefined)
45991
+ throw new Error("Execution price is unavailable");
45992
+ return positionPnl(this.priorPosition, fill.executionPriceE8, BigInt(order.fundingIndex.toString()), fill);
45792
45993
  }
45793
45994
  async readOrder() {
45794
45995
  const response = await this.connection.getAccountInfoAndContext(this.id, "confirmed");
@@ -46066,6 +46267,240 @@ class DepthRecovery {
46066
46267
  }
46067
46268
  }
46068
46269
 
46270
+ // src/history/history.ts
46271
+ init_buffer();
46272
+ import * as anchor7 from "@anchor-lang/core";
46273
+ import {
46274
+ accountOffsets as accountOffsets2,
46275
+ marketAddress as marketAddress6,
46276
+ transferAddress as transferAddress3
46277
+ } from "@depthhq/bindings";
46278
+ import { PublicKey as PublicKey8 } from "@solana/web3.js";
46279
+
46280
+ // src/history/replay.ts
46281
+ function replayFill(state, fill, fundingIndex, maker = false) {
46282
+ if (fill.status !== "ready" || fill.side !== 1n && fill.side !== -1n || fill.size === undefined || fill.size <= 0n || fill.executionPriceE8 === undefined || fill.executionPriceE8 <= 0n || fill.fee === undefined || fill.fee < 0n || maker && (fill.makerRebate === undefined || fill.makerRebate < 0n))
46283
+ throw new Error("A complete private execution is required for history");
46284
+ const side = maker ? -fill.side : fill.side;
46285
+ const delta = side * fill.size;
46286
+ const old = state.position;
46287
+ const next = old + delta;
46288
+ const absolute = (value2) => value2 < 0n ? -value2 : value2;
46289
+ const closing = old !== 0n && old > 0n !== delta > 0n;
46290
+ const size = closing ? fill.size < absolute(old) ? fill.size : absolute(old) : 0n;
46291
+ const gross = (old > 0n ? 1n : -1n) * size * (fill.executionPriceE8 - state.entryPriceE8) / 100000000000n;
46292
+ const funding = old * (fundingIndex - state.fundingCheckpoint) / 100000000000n;
46293
+ const fee = maker ? -fill.makerRebate : fill.fee;
46294
+ const cash = gross - funding - fee;
46295
+ const collateral = state.collateral === undefined ? undefined : state.collateral + cash;
46296
+ if (collateral !== undefined && collateral < 0n)
46297
+ throw new Error("Execution history does not conserve collateral");
46298
+ const entryPriceE8 = next === 0n ? 0n : old === 0n || old > 0n !== next > 0n ? fill.executionPriceE8 : closing ? state.entryPriceE8 : (absolute(old) * state.entryPriceE8 + fill.size * fill.executionPriceE8) / absolute(next);
46299
+ let pnl;
46300
+ if (closing) {
46301
+ const position = {
46302
+ id: "history",
46303
+ status: "ready",
46304
+ slot: fill.slot,
46305
+ version: 0n,
46306
+ ...state
46307
+ };
46308
+ pnl = positionPnl(position, fill.executionPriceE8, fundingIndex, {
46309
+ ...fill,
46310
+ side,
46311
+ fee: maker ? 0n : fee
46312
+ });
46313
+ if (maker) {
46314
+ pnl = {
46315
+ ...pnl,
46316
+ fee,
46317
+ net: cash,
46318
+ returnBps: state.collateral !== undefined && state.collateral > 0n ? cash * 10000n / state.collateral : null
46319
+ };
46320
+ }
46321
+ }
46322
+ return {
46323
+ state: {
46324
+ position: next,
46325
+ entryPriceE8,
46326
+ fundingCheckpoint: fundingIndex,
46327
+ collateral
46328
+ },
46329
+ pnl
46330
+ };
46331
+ }
46332
+ function replayMargin(state, amount, toMarket) {
46333
+ if (amount < 0n)
46334
+ throw new Error("Margin history contains a negative amount");
46335
+ const collateral = state.collateral === undefined ? undefined : state.collateral + (toMarket ? amount : -amount);
46336
+ if (collateral !== undefined && collateral < 0n)
46337
+ throw new Error("Margin history does not conserve collateral");
46338
+ return { ...state, collateral };
46339
+ }
46340
+
46341
+ // src/history/history.ts
46342
+ class ExecutionHistory {
46343
+ program;
46344
+ connection;
46345
+ owner;
46346
+ requestView;
46347
+ views = new Map;
46348
+ fills = new Map;
46349
+ transactions = new Map;
46350
+ constructor(program, connection, owner, requestView) {
46351
+ this.program = program;
46352
+ this.connection = connection;
46353
+ this.owner = owner;
46354
+ this.requestView = requestView;
46355
+ }
46356
+ orderAddress(trader, nonce) {
46357
+ return PublicKey8.findProgramAddressSync([
46358
+ Buffer2.from("order"),
46359
+ marketAddress6(this.program.programId).toBuffer(),
46360
+ trader.toBuffer(),
46361
+ nonce.toArrayLike(Buffer2, "le", 8)
46362
+ ], this.program.programId)[0];
46363
+ }
46364
+ async fill(id) {
46365
+ const key = id.toBase58();
46366
+ if (this.fills.has(key) && !this.views.has(key))
46367
+ return this.fills.get(key);
46368
+ if (!this.views.has(key))
46369
+ this.views.set(key, this.requestView(id));
46370
+ let view;
46371
+ try {
46372
+ view = await this.views.get(key);
46373
+ } catch (error) {
46374
+ this.views.delete(key);
46375
+ throw error;
46376
+ }
46377
+ const result = this.fills.get(key) ?? await view.wait({ timeoutMs: 180000 });
46378
+ if (result.status === "stale") {
46379
+ await view.close();
46380
+ this.views.delete(key);
46381
+ throw new Error("Historical private execution changed; retry with the same wallet");
46382
+ }
46383
+ if (result.status !== "ready")
46384
+ throw new Error("Historical private execution is still pending; retry with the same wallet");
46385
+ this.fills.set(key, result);
46386
+ try {
46387
+ await view.close();
46388
+ } catch (error) {
46389
+ if (await this.connection.getAccountInfo(view.id, "confirmed"))
46390
+ throw error;
46391
+ }
46392
+ this.views.delete(key);
46393
+ return result;
46394
+ }
46395
+ async execution(nonce) {
46396
+ if (nonce < 0n || nonce > (1n << 64n) - 1n)
46397
+ throw new RangeError("Trade nonce is invalid");
46398
+ const target = this.orderAddress(this.owner, new anchor7.BN(nonce.toString()));
46399
+ const market = marketAddress6(this.program.programId);
46400
+ const scans = await Promise.all([
46401
+ this.scan("orderRecord", accountOffsets2.OrderRecord.trader),
46402
+ this.scan("orderRecord", accountOffsets2.OrderRecord.maker),
46403
+ this.scan("marginTransfer", accountOffsets2.MarginTransfer.owner)
46404
+ ]);
46405
+ const orders = new Map;
46406
+ for (const account of [...scans[0], ...scans[1]]) {
46407
+ const state2 = this.program.coder.accounts.decode("orderRecord", account.account.data);
46408
+ if (!state2.market.equals(market) || !state2.trader.equals(this.owner) && !state2.maker.equals(this.owner) || !account.pubkey.equals(this.orderAddress(state2.trader, state2.nonce)))
46409
+ throw new Error("Historical order identity is invalid");
46410
+ if ("filled" in state2.status)
46411
+ orders.set(account.pubkey.toBase58(), { id: account.pubkey, state: state2 });
46412
+ }
46413
+ const selected = orders.get(target.toBase58());
46414
+ if (!selected || !("trade" in selected.state.kind) || !selected.state.trader.equals(this.owner))
46415
+ throw new Error("Historical trade is not a filled execution by this wallet");
46416
+ const targetTx = await this.settlement(target);
46417
+ const events2 = [];
46418
+ for (const order of orders.values()) {
46419
+ const version = order.state.trader.equals(this.owner) ? order.state.traderVersion : order.state.makerVersion;
46420
+ if (version && selected.state.traderVersion && version.gt(selected.state.traderVersion))
46421
+ continue;
46422
+ const transaction = order.id.equals(target) ? targetTx : await this.settlement(order.id);
46423
+ if (transaction.slot <= targetTx.slot)
46424
+ events2.push({ id: order.id, order: order.state, transaction });
46425
+ }
46426
+ for (const account of scans[2]) {
46427
+ const state2 = this.program.coder.accounts.decode("marginTransfer", account.account.data);
46428
+ if (!state2.owner.equals(this.owner) || !state2.market.equals(market) || !account.pubkey.equals(transferAddress3(this.owner, BigInt(state2.nonce.toString()), this.program.programId)))
46429
+ throw new Error("Historical margin identity is invalid");
46430
+ if (!("settled" in state2.status) && (state2.toMarket || !("escrow" in state2.status) && !("crediting" in state2.status)) || state2.amount.isZero())
46431
+ continue;
46432
+ const key = account.pubkey.toBase58();
46433
+ const transaction = this.transactions.get(key) ?? await receiptTransaction(this.connection, this.program, account.pubkey, state2.toMarket ? ["creditMarketCallback"] : ["debitMarketV2Callback", "debitMarketCallback"]);
46434
+ this.transactions.set(key, transaction);
46435
+ if (transaction.slot <= targetTx.slot)
46436
+ events2.push({ id: account.pubkey, transfer: state2, transaction });
46437
+ }
46438
+ const indexes = new Map;
46439
+ const counts = new Map;
46440
+ for (const event of events2)
46441
+ counts.set(event.transaction.slot, (counts.get(event.transaction.slot) ?? 0) + 1);
46442
+ for (const [slot, count] of counts)
46443
+ if (count > 1) {
46444
+ const block = await this.connection.getBlockSignatures(slot, "confirmed");
46445
+ if (!block)
46446
+ throw new Error("Block ordering is unavailable; use an archival RPC for execution history");
46447
+ indexes.set(slot, new Map(block.signatures.map((signature, index) => [signature, index])));
46448
+ if (events2.some((event) => event.transaction.slot === slot && !indexes.get(slot).has(event.transaction.signature)))
46449
+ throw new Error("Historical transaction is missing from its canonical block");
46450
+ }
46451
+ events2.sort((a, b) => a.transaction.slot - b.transaction.slot || (indexes.get(a.transaction.slot)?.get(a.transaction.signature) ?? 0) - (indexes.get(b.transaction.slot)?.get(b.transaction.signature) ?? 0));
46452
+ let state = {
46453
+ position: 0n,
46454
+ entryPriceE8: 0n,
46455
+ fundingCheckpoint: 0n,
46456
+ collateral: 0n
46457
+ };
46458
+ for (const event of events2) {
46459
+ if ("transfer" in event) {
46460
+ state = replayMargin(state, BigInt(event.transfer.amount.toString()), event.transfer.toMarket);
46461
+ continue;
46462
+ }
46463
+ if ("liquidation" in event.order.kind) {
46464
+ if (!event.order.trader.equals(this.owner))
46465
+ throw new Error("Historical backstop exposure requires an authorized historical position view");
46466
+ state = {
46467
+ position: 0n,
46468
+ entryPriceE8: 0n,
46469
+ fundingCheckpoint: BigInt(event.order.fundingIndex.toString())
46470
+ };
46471
+ continue;
46472
+ }
46473
+ const fill = await this.fill(event.id);
46474
+ const result = replayFill(state, fill, BigInt(event.order.fundingIndex.toString()), event.order.maker.equals(this.owner));
46475
+ state = result.state;
46476
+ if (event.id.equals(target))
46477
+ return { id: target, fill, pnl: result.pnl, transaction: targetTx };
46478
+ }
46479
+ throw new Error("Historical execution could not be reconciled");
46480
+ }
46481
+ async settlement(id) {
46482
+ const key = id.toBase58();
46483
+ const cached = this.transactions.get(key);
46484
+ if (cached)
46485
+ return { ...cached, orderId: id };
46486
+ const result = await settlementTransaction(this.connection, this.program, id, { orderId: id });
46487
+ this.transactions.set(key, result);
46488
+ return result;
46489
+ }
46490
+ async scan(name2, offset2) {
46491
+ const accounts2 = await this.connection.getProgramAccounts(this.program.programId, {
46492
+ commitment: "confirmed",
46493
+ filters: [
46494
+ { memcmp: this.program.coder.accounts.memcmp(name2) },
46495
+ { memcmp: { offset: offset2, bytes: this.owner.toBase58() } }
46496
+ ]
46497
+ });
46498
+ if (accounts2.some((item) => !item.account.owner.equals(this.program.programId)))
46499
+ throw new Error("History account owner is invalid");
46500
+ return accounts2;
46501
+ }
46502
+ }
46503
+
46069
46504
  // src/trade/amount.ts
46070
46505
  function resolveAmount(selector, available, name2) {
46071
46506
  u64(available, "available");
@@ -46119,7 +46554,7 @@ function tradeLimit(input, direction, oraclePriceE8) {
46119
46554
  }
46120
46555
 
46121
46556
  // src/trade/flow.ts
46122
- import { transferAddress as transferAddress3 } from "@depthhq/bindings";
46557
+ import { transferAddress as transferAddress4 } from "@depthhq/bindings";
46123
46558
 
46124
46559
  class TradeFlow {
46125
46560
  client;
@@ -46133,7 +46568,7 @@ class TradeFlow {
46133
46568
  throw new RangeError("clientNonce must be an unsigned 64-bit bigint");
46134
46569
  }
46135
46570
  this.id = client.trade.operation(nonce).id;
46136
- this.allocationId = transferAddress3(client.options.wallet.publicKey, nonce, client.program.programId);
46571
+ this.allocationId = transferAddress4(client.options.wallet.publicKey, nonce, client.program.programId);
46137
46572
  }
46138
46573
  async status() {
46139
46574
  const [order, allocation] = await this.client.options.connection.getMultipleAccountsInfo([this.id, this.allocationId], "confirmed");
@@ -46329,10 +46764,10 @@ class DepthView {
46329
46764
 
46330
46765
  // src/client/client.ts
46331
46766
  function pda(seeds, programId = DEPTH_PROGRAM_ID7) {
46332
- return PublicKey8.findProgramAddressSync(seeds, programId)[0];
46767
+ return PublicKey9.findProgramAddressSync(seeds, programId)[0];
46333
46768
  }
46334
46769
  function nonce() {
46335
- return new anchor6.BN(randomBytes3(8), "le");
46770
+ return new anchor8.BN(randomBytes3(8), "le");
46336
46771
  }
46337
46772
  function enumName2(value2) {
46338
46773
  return Object.keys(value2)[0] ?? "unknown";
@@ -46343,7 +46778,7 @@ class DepthClient {
46343
46778
  program;
46344
46779
  provider;
46345
46780
  position;
46346
- marketAddress = marketAddress6();
46781
+ marketAddress = marketAddress7();
46347
46782
  protocolAddress = protocolAddress4();
46348
46783
  mxeAddress = getMXEAccAddress(DEPTH_PROGRAM_ID7);
46349
46784
  get catalog() {
@@ -46358,17 +46793,21 @@ class DepthClient {
46358
46793
  get recovery() {
46359
46794
  return new DepthRecovery(this.program, this.options.connection, this.options.wallet.publicKey);
46360
46795
  }
46796
+ historyClient;
46797
+ get history() {
46798
+ return this.historyClient ??= new ExecutionHistory(this.program, this.options.connection, this.options.wallet.publicKey, (id) => this.requestFillView(id));
46799
+ }
46361
46800
  constructor(options) {
46362
46801
  this.options = options;
46363
46802
  this.provider = new DepthProvider(options.connection, options.wallet, {
46364
46803
  commitment: "confirmed",
46365
46804
  preflightCommitment: "confirmed"
46366
46805
  });
46367
- this.program = new anchor6.Program(DEPTH_IDL3, this.provider);
46806
+ this.program = new anchor8.Program(DEPTH_IDL3, this.provider);
46368
46807
  this.position = this.positionActions();
46369
46808
  }
46370
46809
  static async create(options) {
46371
- const appId = typeof options.appId === "string" ? new PublicKey8(options.appId) : options.appId;
46810
+ const appId = typeof options.appId === "string" ? new PublicKey9(options.appId) : options.appId;
46372
46811
  const resolved = {
46373
46812
  ...options,
46374
46813
  ...await resolveConnection(options),
@@ -46472,7 +46911,7 @@ class DepthClient {
46472
46911
  }
46473
46912
  async requestFillView(order) {
46474
46913
  const record = await this.read("OrderRecord", order);
46475
- if (!record.trader.equals(this.options.wallet.publicKey) || !record.market.equals(this.marketAddress) || enumName2(record.kind) !== "trade" || enumName2(record.status) !== "filled")
46914
+ if (!record.trader.equals(this.options.wallet.publicKey) && !record.maker?.equals(this.options.wallet.publicKey) || !record.market.equals(this.marketAddress) || enumName2(record.kind) !== "trade" || enumName2(record.status) !== "filled")
46476
46915
  throw new Error("Filled trade does not belong to this wallet and market");
46477
46916
  const viewNonce = nonce();
46478
46917
  const view = pda([
@@ -46586,7 +47025,7 @@ class DepthClient {
46586
47025
  return this.funding.release(amount, clientNonce ?? BigInt(nonce().toString()));
46587
47026
  }
46588
47027
  async depositRequest(sourceOrAmount, amount, clientNonce) {
46589
- if (sourceOrAmount instanceof PublicKey8) {
47028
+ if (sourceOrAmount instanceof PublicKey9) {
46590
47029
  if (amount === undefined || clientNonce === undefined)
46591
47030
  throw new RangeError("Source deposits require amount and client nonce");
46592
47031
  return this.funding.deposit(sourceOrAmount, amount, clientNonce);
@@ -46597,7 +47036,7 @@ class DepthClient {
46597
47036
  return this.funding.deposit(source, sourceOrAmount, amount ?? BigInt(nonce().toString()));
46598
47037
  }
46599
47038
  async withdrawRequest(destinationOrAmount, amount, clientNonce) {
46600
- if (destinationOrAmount instanceof PublicKey8) {
47039
+ if (destinationOrAmount instanceof PublicKey9) {
46601
47040
  if (amount === undefined || clientNonce === undefined)
46602
47041
  throw new RangeError("Destination withdrawals require amount and client nonce");
46603
47042
  return this.funding.withdraw(destinationOrAmount, amount, clientNonce);
@@ -46612,6 +47051,8 @@ class DepthClient {
46612
47051
  }
46613
47052
  accountActions() {
46614
47053
  const actions = {
47054
+ detail: (item) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).detail(item),
47055
+ transaction: (item) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).transaction(item),
46615
47056
  history: (options) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).history(options),
46616
47057
  pending: (options) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).pending(options),
46617
47058
  cancelOpen: () => this.funding.cancelOpenBalance(),
@@ -46646,6 +47087,23 @@ class DepthClient {
46646
47087
  addMargin: (amount, clientNonce) => typeof amount === "bigint" && clientNonce !== undefined ? this.funding.allocate(amount, clientNonce) : this.allocateRequest({ marketId: SOL_USD_MARKET_ID3, amount }, clientNonce),
46647
47088
  removeMargin: (amount, clientNonce) => typeof amount === "bigint" && clientNonce !== undefined ? this.funding.release(amount, clientNonce) : this.releaseRequest({ marketId: SOL_USD_MARKET_ID3, amount }, clientNonce),
46648
47089
  open: async () => this.funding.openMarket(),
47090
+ transaction: () => settlementTransaction(this.options.connection, this.program, address2, {
47091
+ trader: this.options.wallet.publicKey,
47092
+ market: this.marketAddress
47093
+ }),
47094
+ pnl: async () => {
47095
+ const position = await this.positionActions(id).summary();
47096
+ const [market, account] = await Promise.all([
47097
+ this.market(),
47098
+ this.read("MarketAccount", address2)
47099
+ ]);
47100
+ const age = Math.floor(Date.now() / 1000) - market.state.oracleTimestamp.toNumber();
47101
+ if (age < 0 || age > market.state.config.maxOracleAgeSeconds)
47102
+ throw new Error("A fresh oracle price is required to value this position");
47103
+ if (position.version !== BigInt(account.version.toString()) || enumName2(account.status) !== "ready")
47104
+ throw new Error("The position changed during valuation; refresh its private view");
47105
+ return positionPnl(position, BigInt(market.state.oraclePriceE8.toString()), BigInt(market.state.fundingIndex.toString()));
47106
+ },
46649
47107
  summary: async (options = {
46650
47108
  timeoutMs: 180000
46651
47109
  }) => {
@@ -46700,7 +47158,12 @@ class DepthClient {
46700
47158
  reduce: (input) => this.submitTrade(input, "reduce"),
46701
47159
  close: (input) => this.submitTrade(input, "close"),
46702
47160
  reverse: (input) => this.submitTrade(input, "reverse"),
46703
- operation: (clientNonce) => new DepthOperation(this.orderAddress(clientNonce), undefined, this.program, this.options.connection, (order) => this.requestFillView(order)),
47161
+ operation: (clientNonce) => new DepthOperation(this.orderAddress(clientNonce), undefined, this.program, this.options.connection, (order) => this.requestFillView(order), undefined, async () => {
47162
+ const detail = await this.history.execution(clientNonce);
47163
+ if (!detail.pnl)
47164
+ throw new Error("This execution does not close any exposure");
47165
+ return detail.pnl;
47166
+ }),
46704
47167
  flow: (clientNonce) => new TradeFlow(this, clientNonce),
46705
47168
  unpairedAllocations: (options) => new FundingDiscovery(this.program, this.options.connection, this.options.wallet.publicKey).unpairedAllocations(options)
46706
47169
  };
@@ -46852,7 +47315,7 @@ class DepthClient {
46852
47315
  }), inputNonce);
46853
47316
  const offset2 = nonce();
46854
47317
  const queue = await this.queue("match_order", offset2);
46855
- const signature = await this.program.methods.submitOrder(offset2, orderNonce, appId, app.feeBps, app.version, new anchor6.BN(deadline), market.state.revision, market.state.oracleTimestamp, ciphertexts, Array.from(inputKey), new anchor6.BN(inputNonce, "le")).accountsPartial({
47318
+ const signature = await this.program.methods.submitOrder(offset2, orderNonce, appId, app.feeBps, app.version, new anchor8.BN(deadline), market.state.revision, market.state.oracleTimestamp, ciphertexts, Array.from(inputKey), new anchor8.BN(inputNonce, "le")).accountsPartial({
46856
47319
  ...queue,
46857
47320
  trader: this.options.wallet.publicKey,
46858
47321
  protocol: this.protocolAddress,
@@ -46873,7 +47336,7 @@ class DepthClient {
46873
47336
  isWritable: true
46874
47337
  }
46875
47338
  ]).rpc({ commitment: "confirmed" }).catch((error) => submissionError(order.toBase58(), error));
46876
- return new DepthOperation(order, signature, this.program, this.options.connection, (id) => this.requestFillView(id));
47339
+ return new DepthOperation(order, signature, this.program, this.options.connection, (id) => this.requestFillView(id), position);
46877
47340
  }
46878
47341
  validateTrade(market, protocol, account, app, appId, intent = "increase", deadline) {
46879
47342
  const now = Math.floor(Date.now() / 1000);
@@ -47043,6 +47506,7 @@ export {
47043
47506
  verifyDeployment,
47044
47507
  resolveConnection,
47045
47508
  resolveAmount,
47509
+ positionPnl,
47046
47510
  manifestBytes,
47047
47511
  create_depth_data,
47048
47512
  createDepth as create_depth,
@@ -47056,6 +47520,7 @@ export {
47056
47520
  MarketCatalog,
47057
47521
  FundingDiscovery,
47058
47522
  FundingClient,
47523
+ ExecutionHistory,
47059
47524
  DepthView,
47060
47525
  DepthRecovery,
47061
47526
  DepthProvider,
@@ -1,17 +1,24 @@
1
1
  import * as anchor from "@anchor-lang/core";
2
2
  import type { OperationSnapshot } from "@depthhq/schema";
3
3
  import { Connection, PublicKey } from "@solana/web3.js";
4
- import type { DepthView, FillSnapshot } from "../view/view.js";
4
+ import type { DepthView, FillSnapshot, PositionSnapshot } from "../view/view.js";
5
+ import { type PositionPnl } from "../position/pnl.js";
6
+ import { type SettlementTransaction } from "../chain/settlement.js";
5
7
  export declare class DepthOperation {
6
8
  readonly id: PublicKey;
7
9
  readonly signature: string | undefined;
8
10
  private readonly program;
9
11
  private readonly connection;
10
12
  private readonly requestFillView?;
13
+ private readonly priorPosition?;
14
+ private readonly historicalPnl?;
11
15
  private viewPromise?;
12
16
  private view?;
13
17
  private fill?;
14
- constructor(id: PublicKey, signature: string | undefined, program: anchor.Program, connection: Connection, requestFillView?: ((order: PublicKey) => Promise<DepthView>) | undefined);
18
+ private settlement?;
19
+ constructor(id: PublicKey, signature: string | undefined, program: anchor.Program, connection: Connection, requestFillView?: ((order: PublicKey) => Promise<DepthView>) | undefined, priorPosition?: PositionSnapshot | undefined, historicalPnl?: (() => Promise<PositionPnl>) | undefined);
20
+ transaction(): Promise<SettlementTransaction>;
21
+ pnl(): Promise<PositionPnl>;
15
22
  private readOrder;
16
23
  status(): Promise<OperationSnapshot>;
17
24
  cancel(): Promise<OperationSnapshot>;
@@ -0,0 +1,14 @@
1
+ import type { FillSnapshot, PositionSnapshot } from "../view/view.js";
2
+ export type PositionPnl = {
3
+ side: "long" | "short";
4
+ state: "open" | "closed" | "reduced" | "reversed";
5
+ entryPriceE8: bigint;
6
+ priceE8: bigint;
7
+ collateral: bigint | null;
8
+ gross: bigint;
9
+ funding: bigint;
10
+ fee: bigint;
11
+ net: bigint;
12
+ returnBps: bigint | null;
13
+ };
14
+ export declare function positionPnl(position: PositionSnapshot, priceE8: bigint, fundingIndex: bigint, fill?: FillSnapshot): PositionPnl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depthhq/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -39,13 +39,13 @@
39
39
  "dependencies": {
40
40
  "@anchor-lang/core": "1.0.2",
41
41
  "@arcium-hq/client": "0.13.2",
42
- "@depthhq/bindings": "0.1.0",
43
- "@depthhq/schema": "0.1.0",
44
42
  "@noble/ciphers": "1.3.0",
45
43
  "@noble/ed25519": "1.7.5",
46
44
  "@noble/hashes": "1.8.0",
47
45
  "@solana/web3.js": "1.99.0",
48
- "buffer": "6.0.3"
46
+ "buffer": "6.0.3",
47
+ "@depthhq/schema": "0.1.1",
48
+ "@depthhq/bindings": "0.1.1"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "node ../../scripts/build-package.mjs sdk",