@acta-markets/ts-sdk 0.0.12-beta → 0.0.14-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/chain/fetch.d.ts +1 -1
  2. package/dist/chain/fetch.js +1 -1
  3. package/dist/cjs/chain/fetch.js +1 -1
  4. package/dist/cjs/events.test.js +3 -1
  5. package/dist/cjs/generated/errors/actaContract.js +4 -1
  6. package/dist/cjs/generated/instructions/closeMarket.js +1 -1
  7. package/dist/cjs/generated/instructions/createMarket.js +1 -1
  8. package/dist/cjs/generated/instructions/openPosition.js +1 -1
  9. package/dist/cjs/generated/instructions/withdrawPremium.js +1 -1
  10. package/dist/cjs/generated/types/actaEvent.js +2 -0
  11. package/dist/cjs/idl/acta_contract.json +13 -4
  12. package/dist/cjs/idl/hash.js +1 -1
  13. package/dist/cjs/ws/index.js +1 -0
  14. package/dist/cjs/ws/sizing.js +79 -0
  15. package/dist/cjs/ws/sizing.test.js +100 -0
  16. package/dist/events.test.js +3 -1
  17. package/dist/generated/errors/actaContract.d.ts +3 -1
  18. package/dist/generated/errors/actaContract.js +3 -0
  19. package/dist/generated/instructions/closeMarket.d.ts +2 -2
  20. package/dist/generated/instructions/closeMarket.js +1 -1
  21. package/dist/generated/instructions/createMarket.d.ts +2 -2
  22. package/dist/generated/instructions/createMarket.js +1 -1
  23. package/dist/generated/instructions/openPosition.d.ts +1 -1
  24. package/dist/generated/instructions/openPosition.js +1 -1
  25. package/dist/generated/instructions/withdrawPremium.d.ts +1 -1
  26. package/dist/generated/instructions/withdrawPremium.js +1 -1
  27. package/dist/generated/types/actaEvent.d.ts +2 -0
  28. package/dist/generated/types/actaEvent.js +2 -0
  29. package/dist/idl/acta_contract.json +13 -4
  30. package/dist/idl/hash.d.ts +1 -1
  31. package/dist/idl/hash.js +1 -1
  32. package/dist/ws/index.d.ts +1 -0
  33. package/dist/ws/index.js +1 -0
  34. package/dist/ws/sizing.d.ts +52 -0
  35. package/dist/ws/sizing.js +74 -0
  36. package/dist/ws/sizing.test.d.ts +1 -0
  37. package/dist/ws/sizing.test.js +98 -0
  38. package/dist/ws/types.d.ts +4 -2
  39. package/package.json +1 -1
@@ -37,7 +37,7 @@ export declare const MAKER_ACCOUNT_DISCRIMINATOR = 2;
37
37
  export declare const CONFIG_ACCOUNT_DISCRIMINATOR = 3;
38
38
  export declare const MARKET_ACCOUNT_DISCRIMINATOR = 4;
39
39
  export declare const ORACLE_ACCOUNT_DISCRIMINATOR = 5;
40
- export declare const POSITION_ACCOUNT_SIZE_BYTES = 416;
40
+ export declare const POSITION_ACCOUNT_SIZE_BYTES = 424;
41
41
  export declare const MAKER_ACCOUNT_SIZE_BYTES = 328;
42
42
  export declare const CONFIG_ACCOUNT_SIZE_BYTES = 392;
43
43
  export declare const MARKET_ACCOUNT_SIZE_BYTES = 416;
@@ -41,7 +41,7 @@ export const CONFIG_ACCOUNT_DISCRIMINATOR = 3;
41
41
  export const MARKET_ACCOUNT_DISCRIMINATOR = 4;
42
42
  export const ORACLE_ACCOUNT_DISCRIMINATOR = 5;
43
43
  // Account sizes (bytes). Note: Maker includes 4 bytes of padding on-chain.
44
- export const POSITION_ACCOUNT_SIZE_BYTES = 416;
44
+ export const POSITION_ACCOUNT_SIZE_BYTES = 424;
45
45
  export const MAKER_ACCOUNT_SIZE_BYTES = 328;
46
46
  export const CONFIG_ACCOUNT_SIZE_BYTES = 392;
47
47
  export const MARKET_ACCOUNT_SIZE_BYTES = 416;
@@ -80,7 +80,7 @@ exports.CONFIG_ACCOUNT_DISCRIMINATOR = 3;
80
80
  exports.MARKET_ACCOUNT_DISCRIMINATOR = 4;
81
81
  exports.ORACLE_ACCOUNT_DISCRIMINATOR = 5;
82
82
  // Account sizes (bytes). Note: Maker includes 4 bytes of padding on-chain.
83
- exports.POSITION_ACCOUNT_SIZE_BYTES = 416;
83
+ exports.POSITION_ACCOUNT_SIZE_BYTES = 424;
84
84
  exports.MAKER_ACCOUNT_SIZE_BYTES = 328;
85
85
  exports.CONFIG_ACCOUNT_SIZE_BYTES = 392;
86
86
  exports.MARKET_ACCOUNT_SIZE_BYTES = 416;
@@ -354,7 +354,8 @@ describe("events parsing", () => {
354
354
  Buffer.from(pk(2)),
355
355
  Buffer.from(pk(3)),
356
356
  Buffer.from(pk(4)),
357
- Buffer.from([5]),
357
+ Buffer.from([5]), // finalStatus
358
+ Buffer.from([1]), // isOtm
358
359
  ]));
359
360
  const d = (0, events_1.decodeActaEventLine)(line);
360
361
  expect(d.kind).toBe(events_1.EventKind.SettlePosition);
@@ -365,6 +366,7 @@ describe("events parsing", () => {
365
366
  expect(d.event.positionPda).toBe(addr(3));
366
367
  expect(d.event.marketPda).toBe(addr(4));
367
368
  expect(d.event.finalStatus).toBe(5);
369
+ expect(d.event.isOtm).toBe(1);
368
370
  }
369
371
  }
370
372
  });
@@ -7,7 +7,7 @@
7
7
  * @see https://github.com/codama-idl/codama
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = exports.ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = exports.ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED = exports.ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY = exports.ACTA_CONTRACT_ERROR__UNAUTHORIZED = exports.ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP = exports.ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID = exports.ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS = exports.ACTA_CONTRACT_ERROR__MINT_MISMATCH = exports.ACTA_CONTRACT_ERROR__MATH_OVERFLOW = exports.ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA = exports.ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH = exports.ACTA_CONTRACT_ERROR__SIGNER_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = exports.ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN = exports.ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE = exports.ACTA_CONTRACT_ERROR__ORACLE_INACTIVE = exports.ACTA_CONTRACT_ERROR__ORACLE_STALE = exports.ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY = exports.ACTA_CONTRACT_ERROR__MARKET_EXPIRED = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED = exports.ACTA_CONTRACT_ERROR__MARKET_FINALIZED = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED = exports.ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED = exports.ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT = exports.ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_PDA = exports.ACTA_CONTRACT_ERROR__INVALID_OWNER = exports.ACTA_CONTRACT_ERROR__NOT_SIGNED = void 0;
10
+ exports.ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = exports.ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = exports.ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED = exports.ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY = exports.ACTA_CONTRACT_ERROR__UNAUTHORIZED = exports.ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP = exports.ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID = exports.ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS = exports.ACTA_CONTRACT_ERROR__MINT_MISMATCH = exports.ACTA_CONTRACT_ERROR__MATH_OVERFLOW = exports.ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA = exports.ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH = exports.ACTA_CONTRACT_ERROR__SIGNER_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = exports.ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN = exports.ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE = exports.ACTA_CONTRACT_ERROR__ORACLE_INACTIVE = exports.ACTA_CONTRACT_ERROR__ORACLE_STALE = exports.ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY = exports.ACTA_CONTRACT_ERROR__MARKET_EXPIRED = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED = exports.ACTA_CONTRACT_ERROR__MARKET_FINALIZED = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED = exports.ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED = exports.ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT = exports.ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_PDA = exports.ACTA_CONTRACT_ERROR__INVALID_OWNER = exports.ACTA_CONTRACT_ERROR__NOT_SIGNED = void 0;
11
11
  exports.getActaContractErrorMessage = getActaContractErrorMessage;
12
12
  exports.isActaContractError = isActaContractError;
13
13
  const kit_1 = require("@solana/kit");
@@ -66,6 +66,8 @@ exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = 0x40a; // 1034
66
66
  exports.ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = 0x40b; // 1035
67
67
  /** PositionTypeMismatch: Position type doesn't match market (call vs put) */
68
68
  exports.ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = 0x40c; // 1036
69
+ /** CannotLiquidateFunded: Cannot liquidate a funded position (use settle instead) */
70
+ exports.ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED = 0x40d; // 1037
69
71
  /** InvalidOrderId: order_id != sha256(preimage) */
70
72
  exports.ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = 0x410; // 1040
71
73
  /** InvalidSignatureCount: Ed25519 instruction has wrong signature count */
@@ -103,6 +105,7 @@ if (process.env.NODE_ENV !== "production") {
103
105
  actaContractErrorMessages = {
104
106
  [exports.ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED]: `Account already initialized`,
105
107
  [exports.ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED]: `Account not initialized`,
108
+ [exports.ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED]: `Cannot liquidate a funded position (use settle instead)`,
106
109
  [exports.ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT]: `Duplicate account passed to instruction`,
107
110
  [exports.ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS]: `Balance is below the required amount`,
108
111
  [exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT]: `Wrong number of accounts`,
@@ -35,7 +35,7 @@ function getCloseMarketInstruction(input, config) {
35
35
  const programAddress = config?.programAddress ?? programs_1.ACTA_CONTRACT_PROGRAM_ADDRESS;
36
36
  // Original accounts.
37
37
  const originalAccounts = {
38
- admin: { value: input.admin ?? null, isWritable: false },
38
+ admin: { value: input.admin ?? null, isWritable: true },
39
39
  configPda: { value: input.configPda ?? null, isWritable: false },
40
40
  marketPda: { value: input.marketPda ?? null, isWritable: true },
41
41
  oracleUnderlying: {
@@ -43,7 +43,7 @@ function getCreateMarketInstruction(input, config) {
43
43
  const programAddress = config?.programAddress ?? programs_1.ACTA_CONTRACT_PROGRAM_ADDRESS;
44
44
  // Original accounts.
45
45
  const originalAccounts = {
46
- admin: { value: input.admin ?? null, isWritable: false },
46
+ admin: { value: input.admin ?? null, isWritable: true },
47
47
  configPda: { value: input.configPda ?? null, isWritable: false },
48
48
  marketPda: { value: input.marketPda ?? null, isWritable: true },
49
49
  underlyingMint: { value: input.underlyingMint ?? null, isWritable: false },
@@ -60,7 +60,7 @@ function getOpenPositionInstruction(input, config) {
60
60
  isWritable: true,
61
61
  },
62
62
  userQuoteAta: { value: input.userQuoteAta ?? null, isWritable: true },
63
- makerPda: { value: input.makerPda ?? null, isWritable: true },
63
+ makerPda: { value: input.makerPda ?? null, isWritable: false },
64
64
  makerPremiumAta: { value: input.makerPremiumAta ?? null, isWritable: true },
65
65
  marketPda: { value: input.marketPda ?? null, isWritable: true },
66
66
  positionPda: { value: input.positionPda ?? null, isWritable: true },
@@ -42,7 +42,7 @@ function getWithdrawPremiumInstruction(input, config) {
42
42
  // Original accounts.
43
43
  const originalAccounts = {
44
44
  makerOwner: { value: input.makerOwner ?? null, isWritable: false },
45
- makerPda: { value: input.makerPda ?? null, isWritable: true },
45
+ makerPda: { value: input.makerPda ?? null, isWritable: false },
46
46
  makerPremiumAta: { value: input.makerPremiumAta ?? null, isWritable: true },
47
47
  makerOwnerPremiumAta: {
48
48
  value: input.makerOwnerPremiumAta ?? null,
@@ -135,6 +135,7 @@ function getActaEventEncoder() {
135
135
  ["positionPda", (0, kit_1.getAddressEncoder)()],
136
136
  ["marketPda", (0, kit_1.getAddressEncoder)()],
137
137
  ["finalStatus", (0, kit_1.getU8Encoder)()],
138
+ ["isOtm", (0, kit_1.getU8Encoder)()],
138
139
  ]),
139
140
  ],
140
141
  [
@@ -297,6 +298,7 @@ function getActaEventDecoder() {
297
298
  ["positionPda", (0, kit_1.getAddressDecoder)()],
298
299
  ["marketPda", (0, kit_1.getAddressDecoder)()],
299
300
  ["finalStatus", (0, kit_1.getU8Decoder)()],
301
+ ["isOtm", (0, kit_1.getU8Decoder)()],
300
302
  ]),
301
303
  ],
302
304
  [
@@ -270,7 +270,7 @@
270
270
  },
271
271
  {
272
272
  "name": "makerPda",
273
- "isMut": true,
273
+ "isMut": false,
274
274
  "isSigner": false,
275
275
  "docs": [
276
276
  "Maker PDA for signer seeds"
@@ -317,7 +317,7 @@
317
317
  "accounts": [
318
318
  {
319
319
  "name": "admin",
320
- "isMut": false,
320
+ "isMut": true,
321
321
  "isSigner": true,
322
322
  "docs": [
323
323
  "Protocol admin authority"
@@ -448,7 +448,7 @@
448
448
  },
449
449
  {
450
450
  "name": "makerPda",
451
- "isMut": true,
451
+ "isMut": false,
452
452
  "isSigner": false,
453
453
  "docs": [
454
454
  "Maker PDA authority"
@@ -994,7 +994,7 @@
994
994
  "accounts": [
995
995
  {
996
996
  "name": "admin",
997
- "isMut": false,
997
+ "isMut": true,
998
998
  "isSigner": true,
999
999
  "docs": [
1000
1000
  "Protocol admin authority"
@@ -2021,6 +2021,10 @@
2021
2021
  {
2022
2022
  "name": "final_status",
2023
2023
  "type": "u8"
2024
+ },
2025
+ {
2026
+ "name": "is_otm",
2027
+ "type": "u8"
2024
2028
  }
2025
2029
  ]
2026
2030
  },
@@ -2270,6 +2274,11 @@
2270
2274
  "name": "PositionNotItm",
2271
2275
  "msg": "Position not ITM (cannot liquidate OTM)"
2272
2276
  },
2277
+ {
2278
+ "code": 1037,
2279
+ "name": "CannotLiquidateFunded",
2280
+ "msg": "Cannot liquidate a funded position (use settle instead)"
2281
+ },
2273
2282
  {
2274
2283
  "code": 1036,
2275
2284
  "name": "PositionTypeMismatch",
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ACTA_IDL_SHA256 = void 0;
4
- exports.ACTA_IDL_SHA256 = "a86d779d49761e2979103c9ebd3eeb10f85fc9c4fc5848d78d11326e3eedab83";
4
+ exports.ACTA_IDL_SHA256 = "85637746c4aabc7c4638de439ca8cf3cf6dfda58b2e26e5347077abdb78958dc";
@@ -21,3 +21,4 @@ __exportStar(require("./flows"), exports);
21
21
  __exportStar(require("./sponsoredTx"), exports);
22
22
  __exportStar(require("./apy"), exports);
23
23
  __exportStar(require("./discovery"), exports);
24
+ __exportStar(require("./sizing"), exports);
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ /**
3
+ * CSP quantity / size-rule conversion helpers.
4
+ *
5
+ * On the wire, `quantity` is always in underlying atomic units (e.g. SOL lamports).
6
+ * For covered calls the user thinks in underlying (SOL), so no conversion is needed.
7
+ * For cash-secured puts the user thinks in quote (USDC), so the frontend must convert
8
+ * between the user's USDC input and the wire's underlying quantity.
9
+ *
10
+ * These helpers handle that conversion and let the frontend display size_rule
11
+ * constraints in quote terms.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.quoteAmountToQuantity = quoteAmountToQuantity;
15
+ exports.quantityToQuoteAmount = quantityToQuoteAmount;
16
+ exports.sizeRuleInQuoteTerms = sizeRuleInQuoteTerms;
17
+ const apy_1 = require("./apy");
18
+ /**
19
+ * Convert a user's quote-denominated deposit (e.g. 450 USDC) to the wire
20
+ * quantity in underlying atomic units.
21
+ *
22
+ * Formula: `round(quoteAmount * 10^underlyingDecimals * PRICE_SCALE / strike1e9)`
23
+ *
24
+ * @param quoteAmount Human-readable quote amount (e.g. 450 for "450 USDC")
25
+ * @param strike1e9 Strike price, 1e9-scaled (e.g. 90_000_000_000 for $90)
26
+ * @param underlyingDecimals Decimals of the underlying mint (e.g. 9 for SOL)
27
+ * @returns Wire quantity (underlying atomic units)
28
+ */
29
+ function quoteAmountToQuantity(quoteAmount, strike1e9, underlyingDecimals) {
30
+ if (!Number.isFinite(quoteAmount) || quoteAmount < 0) {
31
+ throw new Error("quoteAmount must be a non-negative finite number");
32
+ }
33
+ if (!Number.isFinite(strike1e9) || strike1e9 <= 0) {
34
+ throw new Error("strike1e9 must be a positive finite number");
35
+ }
36
+ const atomicFactor = Math.pow(10, underlyingDecimals);
37
+ return Math.round(quoteAmount * atomicFactor * apy_1.PRICE_SCALE / strike1e9);
38
+ }
39
+ /**
40
+ * Convert a wire quantity (underlying atomic units) to a human-readable
41
+ * quote-denominated amount.
42
+ *
43
+ * Formula: `quantity * strike1e9 / PRICE_SCALE / 10^underlyingDecimals`
44
+ *
45
+ * @param quantity Wire quantity (underlying atomic units)
46
+ * @param strike1e9 Strike price, 1e9-scaled
47
+ * @param underlyingDecimals Decimals of the underlying mint
48
+ * @returns Human-readable quote amount (e.g. 450 for "450 USDC")
49
+ */
50
+ function quantityToQuoteAmount(quantity, strike1e9, underlyingDecimals) {
51
+ if (!Number.isFinite(quantity) || quantity < 0) {
52
+ throw new Error("quantity must be a non-negative finite number");
53
+ }
54
+ if (!Number.isFinite(strike1e9) || strike1e9 <= 0) {
55
+ throw new Error("strike1e9 must be a positive finite number");
56
+ }
57
+ const atomicFactor = Math.pow(10, underlyingDecimals);
58
+ return quantity * strike1e9 / apy_1.PRICE_SCALE / atomicFactor;
59
+ }
60
+ /**
61
+ * Convert a size_rule (underlying atomic units) to human-readable quote terms.
62
+ *
63
+ * Example: SOL/USDC CSP, strike $90, rule {min: 1e9, max: 10e9, step: 1e8}
64
+ * → returns {min: 90, max: 900, step: 9} (USDC)
65
+ *
66
+ * @param rule Size rule from MarketDescriptorInfo
67
+ * @param strike1e9 Strike price, 1e9-scaled
68
+ * @param underlyingDecimals Decimals of the underlying mint
69
+ */
70
+ function sizeRuleInQuoteTerms(rule, strike1e9, underlyingDecimals) {
71
+ if (!Number.isFinite(strike1e9) || strike1e9 <= 0) {
72
+ throw new Error("strike1e9 must be a positive finite number");
73
+ }
74
+ return {
75
+ min: quantityToQuoteAmount(rule.min_size, strike1e9, underlyingDecimals),
76
+ max: quantityToQuoteAmount(rule.max_size, strike1e9, underlyingDecimals),
77
+ step: quantityToQuoteAmount(rule.step, strike1e9, underlyingDecimals),
78
+ };
79
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const sizing_1 = require("./sizing");
4
+ describe("ws sizing helpers", () => {
5
+ // SOL: 9 decimals, strike $90 = 90_000_000_000 (1e9-scaled)
6
+ const SOL_DECIMALS = 9;
7
+ const STRIKE_90 = 90_000_000_000;
8
+ describe("quoteAmountToQuantity", () => {
9
+ it("converts 450 USDC at $90 strike to 5 SOL in lamports", () => {
10
+ expect((0, sizing_1.quoteAmountToQuantity)(450, STRIKE_90, SOL_DECIMALS)).toBe(5_000_000_000);
11
+ });
12
+ it("converts 90 USDC (min) to 1 SOL in lamports", () => {
13
+ expect((0, sizing_1.quoteAmountToQuantity)(90, STRIKE_90, SOL_DECIMALS)).toBe(1_000_000_000);
14
+ });
15
+ it("converts 9 USDC (one step) to 0.1 SOL in lamports", () => {
16
+ expect((0, sizing_1.quoteAmountToQuantity)(9, STRIKE_90, SOL_DECIMALS)).toBe(100_000_000);
17
+ });
18
+ it("returns 0 for 0 input", () => {
19
+ expect((0, sizing_1.quoteAmountToQuantity)(0, STRIKE_90, SOL_DECIMALS)).toBe(0);
20
+ });
21
+ it("throws on negative quoteAmount", () => {
22
+ expect(() => (0, sizing_1.quoteAmountToQuantity)(-1, STRIKE_90, SOL_DECIMALS)).toThrow("quoteAmount");
23
+ });
24
+ it("throws on zero strike", () => {
25
+ expect(() => (0, sizing_1.quoteAmountToQuantity)(100, 0, SOL_DECIMALS)).toThrow("strike1e9");
26
+ });
27
+ it("throws on negative strike", () => {
28
+ expect(() => (0, sizing_1.quoteAmountToQuantity)(100, -1, SOL_DECIMALS)).toThrow("strike1e9");
29
+ });
30
+ });
31
+ describe("quantityToQuoteAmount", () => {
32
+ it("converts 5 SOL lamports at $90 strike to 450 USDC", () => {
33
+ expect((0, sizing_1.quantityToQuoteAmount)(5_000_000_000, STRIKE_90, SOL_DECIMALS)).toBeCloseTo(450, 10);
34
+ });
35
+ it("converts 1 SOL lamports to 90 USDC", () => {
36
+ expect((0, sizing_1.quantityToQuoteAmount)(1_000_000_000, STRIKE_90, SOL_DECIMALS)).toBeCloseTo(90, 10);
37
+ });
38
+ it("converts 0.1 SOL lamports to 9 USDC", () => {
39
+ expect((0, sizing_1.quantityToQuoteAmount)(100_000_000, STRIKE_90, SOL_DECIMALS)).toBeCloseTo(9, 10);
40
+ });
41
+ it("returns 0 for 0 quantity", () => {
42
+ expect((0, sizing_1.quantityToQuoteAmount)(0, STRIKE_90, SOL_DECIMALS)).toBe(0);
43
+ });
44
+ it("throws on negative quantity", () => {
45
+ expect(() => (0, sizing_1.quantityToQuoteAmount)(-1, STRIKE_90, SOL_DECIMALS)).toThrow("quantity");
46
+ });
47
+ });
48
+ describe("round-trip", () => {
49
+ it("quoteAmount -> quantity -> quoteAmount is stable", () => {
50
+ const original = 450;
51
+ const quantity = (0, sizing_1.quoteAmountToQuantity)(original, STRIKE_90, SOL_DECIMALS);
52
+ const restored = (0, sizing_1.quantityToQuoteAmount)(quantity, STRIKE_90, SOL_DECIMALS);
53
+ expect(restored).toBeCloseTo(original, 6);
54
+ });
55
+ it("round-trips at step granularity (9 USDC)", () => {
56
+ const original = 9;
57
+ const quantity = (0, sizing_1.quoteAmountToQuantity)(original, STRIKE_90, SOL_DECIMALS);
58
+ const restored = (0, sizing_1.quantityToQuoteAmount)(quantity, STRIKE_90, SOL_DECIMALS);
59
+ expect(restored).toBeCloseTo(original, 6);
60
+ });
61
+ it("round-trips with different strike ($150)", () => {
62
+ const strike150 = 150_000_000_000;
63
+ const original = 300;
64
+ const quantity = (0, sizing_1.quoteAmountToQuantity)(original, strike150, SOL_DECIMALS);
65
+ expect(quantity).toBe(2_000_000_000); // 2 SOL
66
+ const restored = (0, sizing_1.quantityToQuoteAmount)(quantity, strike150, SOL_DECIMALS);
67
+ expect(restored).toBeCloseTo(original, 6);
68
+ });
69
+ });
70
+ describe("sizeRuleInQuoteTerms", () => {
71
+ const rule = { min_size: 1_000_000_000, max_size: 10_000_000_000, step: 100_000_000 };
72
+ it("converts SOL size_rule to USDC terms at $90 strike", () => {
73
+ const result = (0, sizing_1.sizeRuleInQuoteTerms)(rule, STRIKE_90, SOL_DECIMALS);
74
+ expect(result.min).toBeCloseTo(90, 6);
75
+ expect(result.max).toBeCloseTo(900, 6);
76
+ expect(result.step).toBeCloseTo(9, 6);
77
+ });
78
+ it("converts at $150 strike", () => {
79
+ const strike150 = 150_000_000_000;
80
+ const result = (0, sizing_1.sizeRuleInQuoteTerms)(rule, strike150, SOL_DECIMALS);
81
+ expect(result.min).toBeCloseTo(150, 6);
82
+ expect(result.max).toBeCloseTo(1500, 6);
83
+ expect(result.step).toBeCloseTo(15, 6);
84
+ });
85
+ it("throws on zero strike", () => {
86
+ expect(() => (0, sizing_1.sizeRuleInQuoteTerms)(rule, 0, SOL_DECIMALS)).toThrow("strike1e9");
87
+ });
88
+ });
89
+ describe("non-9-decimal underlying", () => {
90
+ // ETH: 8 decimals
91
+ const ETH_DECIMALS = 8;
92
+ const STRIKE_3000 = 3_000_000_000_000; // $3000
93
+ it("converts 6000 USDC at $3000 strike to 2 ETH (8 decimals)", () => {
94
+ expect((0, sizing_1.quoteAmountToQuantity)(6000, STRIKE_3000, ETH_DECIMALS)).toBe(200_000_000);
95
+ });
96
+ it("converts 2 ETH back to 6000 USDC", () => {
97
+ expect((0, sizing_1.quantityToQuoteAmount)(200_000_000, STRIKE_3000, ETH_DECIMALS)).toBeCloseTo(6000, 6);
98
+ });
99
+ });
100
+ });
@@ -352,7 +352,8 @@ describe("events parsing", () => {
352
352
  Buffer.from(pk(2)),
353
353
  Buffer.from(pk(3)),
354
354
  Buffer.from(pk(4)),
355
- Buffer.from([5]),
355
+ Buffer.from([5]), // finalStatus
356
+ Buffer.from([1]), // isOtm
356
357
  ]));
357
358
  const d = decodeActaEventLine(line);
358
359
  expect(d.kind).toBe(EventKind.SettlePosition);
@@ -363,6 +364,7 @@ describe("events parsing", () => {
363
364
  expect(d.event.positionPda).toBe(addr(3));
364
365
  expect(d.event.marketPda).toBe(addr(4));
365
366
  expect(d.event.finalStatus).toBe(5);
367
+ expect(d.event.isOtm).toBe(1);
366
368
  }
367
369
  }
368
370
  });
@@ -60,6 +60,8 @@ export declare const ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = 1034;
60
60
  export declare const ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = 1035;
61
61
  /** PositionTypeMismatch: Position type doesn't match market (call vs put) */
62
62
  export declare const ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = 1036;
63
+ /** CannotLiquidateFunded: Cannot liquidate a funded position (use settle instead) */
64
+ export declare const ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED = 1037;
63
65
  /** InvalidOrderId: order_id != sha256(preimage) */
64
66
  export declare const ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = 1040;
65
67
  /** InvalidSignatureCount: Ed25519 instruction has wrong signature count */
@@ -92,7 +94,7 @@ export declare const ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = 1073;
92
94
  export declare const ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = 1074;
93
95
  /** DuplicateAccount: Duplicate account passed to instruction */
94
96
  export declare const ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = 1075;
95
- export type ActaContractError = typeof ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED | typeof ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED | typeof ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE | typeof ACTA_CONTRACT_ERROR__INVALID_ORDER_ID | typeof ACTA_CONTRACT_ERROR__INVALID_OWNER | typeof ACTA_CONTRACT_ERROR__INVALID_PDA | typeof ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID | typeof ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP | typeof ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED | typeof ACTA_CONTRACT_ERROR__MARKET_EXPIRED | typeof ACTA_CONTRACT_ERROR__MARKET_FINALIZED | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED | typeof ACTA_CONTRACT_ERROR__MATH_OVERFLOW | typeof ACTA_CONTRACT_ERROR__MINT_MISMATCH | typeof ACTA_CONTRACT_ERROR__NOT_SIGNED | typeof ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED | typeof ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY | typeof ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH | typeof ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS | typeof ACTA_CONTRACT_ERROR__ORACLE_INACTIVE | typeof ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE | typeof ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED | typeof ACTA_CONTRACT_ERROR__ORACLE_STALE | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_ITM | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNER_MISMATCH | typeof ACTA_CONTRACT_ERROR__UNAUTHORIZED;
97
+ export type ActaContractError = typeof ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED | typeof ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED | typeof ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED | typeof ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE | typeof ACTA_CONTRACT_ERROR__INVALID_ORDER_ID | typeof ACTA_CONTRACT_ERROR__INVALID_OWNER | typeof ACTA_CONTRACT_ERROR__INVALID_PDA | typeof ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID | typeof ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP | typeof ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED | typeof ACTA_CONTRACT_ERROR__MARKET_EXPIRED | typeof ACTA_CONTRACT_ERROR__MARKET_FINALIZED | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED | typeof ACTA_CONTRACT_ERROR__MATH_OVERFLOW | typeof ACTA_CONTRACT_ERROR__MINT_MISMATCH | typeof ACTA_CONTRACT_ERROR__NOT_SIGNED | typeof ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED | typeof ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY | typeof ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH | typeof ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS | typeof ACTA_CONTRACT_ERROR__ORACLE_INACTIVE | typeof ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE | typeof ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED | typeof ACTA_CONTRACT_ERROR__ORACLE_STALE | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_ITM | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNER_MISMATCH | typeof ACTA_CONTRACT_ERROR__UNAUTHORIZED;
96
98
  export declare function getActaContractErrorMessage(code: ActaContractError): string;
97
99
  export declare function isActaContractError<TProgramErrorCode extends ActaContractError>(error: unknown, transactionMessage: {
98
100
  instructions: Record<number, {
@@ -61,6 +61,8 @@ export const ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = 0x40a; // 1034
61
61
  export const ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = 0x40b; // 1035
62
62
  /** PositionTypeMismatch: Position type doesn't match market (call vs put) */
63
63
  export const ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = 0x40c; // 1036
64
+ /** CannotLiquidateFunded: Cannot liquidate a funded position (use settle instead) */
65
+ export const ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED = 0x40d; // 1037
64
66
  /** InvalidOrderId: order_id != sha256(preimage) */
65
67
  export const ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = 0x410; // 1040
66
68
  /** InvalidSignatureCount: Ed25519 instruction has wrong signature count */
@@ -98,6 +100,7 @@ if (process.env.NODE_ENV !== "production") {
98
100
  actaContractErrorMessages = {
99
101
  [ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED]: `Account already initialized`,
100
102
  [ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED]: `Account not initialized`,
103
+ [ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED]: `Cannot liquidate a funded position (use settle instead)`,
101
104
  [ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT]: `Duplicate account passed to instruction`,
102
105
  [ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS]: `Balance is below the required amount`,
103
106
  [ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT]: `Wrong number of accounts`,
@@ -5,12 +5,12 @@
5
5
  *
6
6
  * @see https://github.com/codama-idl/codama
7
7
  */
8
- import { type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlySignerAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount } from "@solana/kit";
8
+ import { type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount, type WritableSignerAccount } from "@solana/kit";
9
9
  import { ACTA_CONTRACT_PROGRAM_ADDRESS } from "../programs";
10
10
  export declare const CLOSE_MARKET_DISCRIMINATOR = 14;
11
11
  export declare function getCloseMarketDiscriminatorBytes(): ReadonlyUint8Array;
12
12
  export type CloseMarketInstruction<TProgram extends string = typeof ACTA_CONTRACT_PROGRAM_ADDRESS, TAccountAdmin extends string | AccountMeta<string> = string, TAccountConfigPda extends string | AccountMeta<string> = string, TAccountMarketPda extends string | AccountMeta<string> = string, TAccountOracleUnderlying extends string | AccountMeta<string> = string, TAccountOracleQuote extends string | AccountMeta<string> = string, TRemainingAccounts extends readonly AccountMeta<string>[] = []> = Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[
13
- TAccountAdmin extends string ? ReadonlySignerAccount<TAccountAdmin> & AccountSignerMeta<TAccountAdmin> : TAccountAdmin,
13
+ TAccountAdmin extends string ? WritableSignerAccount<TAccountAdmin> & AccountSignerMeta<TAccountAdmin> : TAccountAdmin,
14
14
  TAccountConfigPda extends string ? ReadonlyAccount<TAccountConfigPda> : TAccountConfigPda,
15
15
  TAccountMarketPda extends string ? WritableAccount<TAccountMarketPda> : TAccountMarketPda,
16
16
  TAccountOracleUnderlying extends string ? WritableAccount<TAccountOracleUnderlying> : TAccountOracleUnderlying,
@@ -26,7 +26,7 @@ export function getCloseMarketInstruction(input, config) {
26
26
  const programAddress = config?.programAddress ?? ACTA_CONTRACT_PROGRAM_ADDRESS;
27
27
  // Original accounts.
28
28
  const originalAccounts = {
29
- admin: { value: input.admin ?? null, isWritable: false },
29
+ admin: { value: input.admin ?? null, isWritable: true },
30
30
  configPda: { value: input.configPda ?? null, isWritable: false },
31
31
  marketPda: { value: input.marketPda ?? null, isWritable: true },
32
32
  oracleUnderlying: {
@@ -5,12 +5,12 @@
5
5
  *
6
6
  * @see https://github.com/codama-idl/codama
7
7
  */
8
- import { type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlySignerAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount } from "@solana/kit";
8
+ import { type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount, type WritableSignerAccount } from "@solana/kit";
9
9
  import { ACTA_CONTRACT_PROGRAM_ADDRESS } from "../programs";
10
10
  export declare const CREATE_MARKET_DISCRIMINATOR = 6;
11
11
  export declare function getCreateMarketDiscriminatorBytes(): ReadonlyUint8Array;
12
12
  export type CreateMarketInstruction<TProgram extends string = typeof ACTA_CONTRACT_PROGRAM_ADDRESS, TAccountAdmin extends string | AccountMeta<string> = string, TAccountConfigPda extends string | AccountMeta<string> = string, TAccountMarketPda extends string | AccountMeta<string> = string, TAccountUnderlyingMint extends string | AccountMeta<string> = string, TAccountQuoteMint extends string | AccountMeta<string> = string, TAccountUnderlyingMintAcc extends string | AccountMeta<string> = string, TAccountQuoteMintAcc extends string | AccountMeta<string> = string, TAccountOracleUnderlying extends string | AccountMeta<string> = string, TAccountOracleQuote extends string | AccountMeta<string> = string, TAccountSystemProgram extends string | AccountMeta<string> = "11111111111111111111111111111111", TRemainingAccounts extends readonly AccountMeta<string>[] = []> = Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[
13
- TAccountAdmin extends string ? ReadonlySignerAccount<TAccountAdmin> & AccountSignerMeta<TAccountAdmin> : TAccountAdmin,
13
+ TAccountAdmin extends string ? WritableSignerAccount<TAccountAdmin> & AccountSignerMeta<TAccountAdmin> : TAccountAdmin,
14
14
  TAccountConfigPda extends string ? ReadonlyAccount<TAccountConfigPda> : TAccountConfigPda,
15
15
  TAccountMarketPda extends string ? WritableAccount<TAccountMarketPda> : TAccountMarketPda,
16
16
  TAccountUnderlyingMint extends string ? ReadonlyAccount<TAccountUnderlyingMint> : TAccountUnderlyingMint,
@@ -34,7 +34,7 @@ export function getCreateMarketInstruction(input, config) {
34
34
  const programAddress = config?.programAddress ?? ACTA_CONTRACT_PROGRAM_ADDRESS;
35
35
  // Original accounts.
36
36
  const originalAccounts = {
37
- admin: { value: input.admin ?? null, isWritable: false },
37
+ admin: { value: input.admin ?? null, isWritable: true },
38
38
  configPda: { value: input.configPda ?? null, isWritable: false },
39
39
  marketPda: { value: input.marketPda ?? null, isWritable: true },
40
40
  underlyingMint: { value: input.underlyingMint ?? null, isWritable: false },
@@ -14,7 +14,7 @@ export type OpenPositionInstruction<TProgram extends string = typeof ACTA_CONTRA
14
14
  TAccountUser extends string ? ReadonlySignerAccount<TAccountUser> & AccountSignerMeta<TAccountUser> : TAccountUser,
15
15
  TAccountUserUnderlyingAta extends string ? WritableAccount<TAccountUserUnderlyingAta> : TAccountUserUnderlyingAta,
16
16
  TAccountUserQuoteAta extends string ? WritableAccount<TAccountUserQuoteAta> : TAccountUserQuoteAta,
17
- TAccountMakerPda extends string ? WritableAccount<TAccountMakerPda> : TAccountMakerPda,
17
+ TAccountMakerPda extends string ? ReadonlyAccount<TAccountMakerPda> : TAccountMakerPda,
18
18
  TAccountMakerPremiumAta extends string ? WritableAccount<TAccountMakerPremiumAta> : TAccountMakerPremiumAta,
19
19
  TAccountMarketPda extends string ? WritableAccount<TAccountMarketPda> : TAccountMarketPda,
20
20
  TAccountPositionPda extends string ? WritableAccount<TAccountPositionPda> : TAccountPositionPda,
@@ -51,7 +51,7 @@ export function getOpenPositionInstruction(input, config) {
51
51
  isWritable: true,
52
52
  },
53
53
  userQuoteAta: { value: input.userQuoteAta ?? null, isWritable: true },
54
- makerPda: { value: input.makerPda ?? null, isWritable: true },
54
+ makerPda: { value: input.makerPda ?? null, isWritable: false },
55
55
  makerPremiumAta: { value: input.makerPremiumAta ?? null, isWritable: true },
56
56
  marketPda: { value: input.marketPda ?? null, isWritable: true },
57
57
  positionPda: { value: input.positionPda ?? null, isWritable: true },
@@ -11,7 +11,7 @@ export declare const WITHDRAW_PREMIUM_DISCRIMINATOR = 5;
11
11
  export declare function getWithdrawPremiumDiscriminatorBytes(): ReadonlyUint8Array;
12
12
  export type WithdrawPremiumInstruction<TProgram extends string = typeof ACTA_CONTRACT_PROGRAM_ADDRESS, TAccountMakerOwner extends string | AccountMeta<string> = string, TAccountMakerPda extends string | AccountMeta<string> = string, TAccountMakerPremiumAta extends string | AccountMeta<string> = string, TAccountMakerOwnerPremiumAta extends string | AccountMeta<string> = string, TAccountTokenProgram extends string | AccountMeta<string> = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", TRemainingAccounts extends readonly AccountMeta<string>[] = []> = Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[
13
13
  TAccountMakerOwner extends string ? ReadonlySignerAccount<TAccountMakerOwner> & AccountSignerMeta<TAccountMakerOwner> : TAccountMakerOwner,
14
- TAccountMakerPda extends string ? WritableAccount<TAccountMakerPda> : TAccountMakerPda,
14
+ TAccountMakerPda extends string ? ReadonlyAccount<TAccountMakerPda> : TAccountMakerPda,
15
15
  TAccountMakerPremiumAta extends string ? WritableAccount<TAccountMakerPremiumAta> : TAccountMakerPremiumAta,
16
16
  TAccountMakerOwnerPremiumAta extends string ? WritableAccount<TAccountMakerOwnerPremiumAta> : TAccountMakerOwnerPremiumAta,
17
17
  TAccountTokenProgram extends string ? ReadonlyAccount<TAccountTokenProgram> : TAccountTokenProgram,
@@ -33,7 +33,7 @@ export function getWithdrawPremiumInstruction(input, config) {
33
33
  // Original accounts.
34
34
  const originalAccounts = {
35
35
  makerOwner: { value: input.makerOwner ?? null, isWritable: false },
36
- makerPda: { value: input.makerPda ?? null, isWritable: true },
36
+ makerPda: { value: input.makerPda ?? null, isWritable: false },
37
37
  makerPremiumAta: { value: input.makerPremiumAta ?? null, isWritable: true },
38
38
  makerOwnerPremiumAta: {
39
39
  value: input.makerOwnerPremiumAta ?? null,
@@ -91,6 +91,7 @@ export type ActaEvent = {
91
91
  positionPda: Address;
92
92
  marketPda: Address;
93
93
  finalStatus: number;
94
+ isOtm: number;
94
95
  } | {
95
96
  __kind: "CreateOracle";
96
97
  oraclePda: Address;
@@ -203,6 +204,7 @@ export type ActaEventArgs = {
203
204
  positionPda: Address;
204
205
  marketPda: Address;
205
206
  finalStatus: number;
207
+ isOtm: number;
206
208
  } | {
207
209
  __kind: "CreateOracle";
208
210
  oraclePda: Address;
@@ -128,6 +128,7 @@ export function getActaEventEncoder() {
128
128
  ["positionPda", getAddressEncoder()],
129
129
  ["marketPda", getAddressEncoder()],
130
130
  ["finalStatus", getU8Encoder()],
131
+ ["isOtm", getU8Encoder()],
131
132
  ]),
132
133
  ],
133
134
  [
@@ -290,6 +291,7 @@ export function getActaEventDecoder() {
290
291
  ["positionPda", getAddressDecoder()],
291
292
  ["marketPda", getAddressDecoder()],
292
293
  ["finalStatus", getU8Decoder()],
294
+ ["isOtm", getU8Decoder()],
293
295
  ]),
294
296
  ],
295
297
  [
@@ -270,7 +270,7 @@
270
270
  },
271
271
  {
272
272
  "name": "makerPda",
273
- "isMut": true,
273
+ "isMut": false,
274
274
  "isSigner": false,
275
275
  "docs": [
276
276
  "Maker PDA for signer seeds"
@@ -317,7 +317,7 @@
317
317
  "accounts": [
318
318
  {
319
319
  "name": "admin",
320
- "isMut": false,
320
+ "isMut": true,
321
321
  "isSigner": true,
322
322
  "docs": [
323
323
  "Protocol admin authority"
@@ -448,7 +448,7 @@
448
448
  },
449
449
  {
450
450
  "name": "makerPda",
451
- "isMut": true,
451
+ "isMut": false,
452
452
  "isSigner": false,
453
453
  "docs": [
454
454
  "Maker PDA authority"
@@ -994,7 +994,7 @@
994
994
  "accounts": [
995
995
  {
996
996
  "name": "admin",
997
- "isMut": false,
997
+ "isMut": true,
998
998
  "isSigner": true,
999
999
  "docs": [
1000
1000
  "Protocol admin authority"
@@ -2021,6 +2021,10 @@
2021
2021
  {
2022
2022
  "name": "final_status",
2023
2023
  "type": "u8"
2024
+ },
2025
+ {
2026
+ "name": "is_otm",
2027
+ "type": "u8"
2024
2028
  }
2025
2029
  ]
2026
2030
  },
@@ -2270,6 +2274,11 @@
2270
2274
  "name": "PositionNotItm",
2271
2275
  "msg": "Position not ITM (cannot liquidate OTM)"
2272
2276
  },
2277
+ {
2278
+ "code": 1037,
2279
+ "name": "CannotLiquidateFunded",
2280
+ "msg": "Cannot liquidate a funded position (use settle instead)"
2281
+ },
2273
2282
  {
2274
2283
  "code": 1036,
2275
2284
  "name": "PositionTypeMismatch",
@@ -1 +1 @@
1
- export declare const ACTA_IDL_SHA256 = "a86d779d49761e2979103c9ebd3eeb10f85fc9c4fc5848d78d11326e3eedab83";
1
+ export declare const ACTA_IDL_SHA256 = "85637746c4aabc7c4638de439ca8cf3cf6dfda58b2e26e5347077abdb78958dc";
package/dist/idl/hash.js CHANGED
@@ -1 +1 @@
1
- export const ACTA_IDL_SHA256 = "a86d779d49761e2979103c9ebd3eeb10f85fc9c4fc5848d78d11326e3eedab83";
1
+ export const ACTA_IDL_SHA256 = "85637746c4aabc7c4638de439ca8cf3cf6dfda58b2e26e5347077abdb78958dc";
@@ -5,3 +5,4 @@ export * from "./flows";
5
5
  export * from "./sponsoredTx";
6
6
  export * from "./apy";
7
7
  export * from "./discovery";
8
+ export * from "./sizing";
package/dist/ws/index.js CHANGED
@@ -5,3 +5,4 @@ export * from "./flows";
5
5
  export * from "./sponsoredTx";
6
6
  export * from "./apy";
7
7
  export * from "./discovery";
8
+ export * from "./sizing";
@@ -0,0 +1,52 @@
1
+ /**
2
+ * CSP quantity / size-rule conversion helpers.
3
+ *
4
+ * On the wire, `quantity` is always in underlying atomic units (e.g. SOL lamports).
5
+ * For covered calls the user thinks in underlying (SOL), so no conversion is needed.
6
+ * For cash-secured puts the user thinks in quote (USDC), so the frontend must convert
7
+ * between the user's USDC input and the wire's underlying quantity.
8
+ *
9
+ * These helpers handle that conversion and let the frontend display size_rule
10
+ * constraints in quote terms.
11
+ */
12
+ import type { QuantitySizeRuleLike } from "./wirePolicy";
13
+ /**
14
+ * Convert a user's quote-denominated deposit (e.g. 450 USDC) to the wire
15
+ * quantity in underlying atomic units.
16
+ *
17
+ * Formula: `round(quoteAmount * 10^underlyingDecimals * PRICE_SCALE / strike1e9)`
18
+ *
19
+ * @param quoteAmount Human-readable quote amount (e.g. 450 for "450 USDC")
20
+ * @param strike1e9 Strike price, 1e9-scaled (e.g. 90_000_000_000 for $90)
21
+ * @param underlyingDecimals Decimals of the underlying mint (e.g. 9 for SOL)
22
+ * @returns Wire quantity (underlying atomic units)
23
+ */
24
+ export declare function quoteAmountToQuantity(quoteAmount: number, strike1e9: number, underlyingDecimals: number): number;
25
+ /**
26
+ * Convert a wire quantity (underlying atomic units) to a human-readable
27
+ * quote-denominated amount.
28
+ *
29
+ * Formula: `quantity * strike1e9 / PRICE_SCALE / 10^underlyingDecimals`
30
+ *
31
+ * @param quantity Wire quantity (underlying atomic units)
32
+ * @param strike1e9 Strike price, 1e9-scaled
33
+ * @param underlyingDecimals Decimals of the underlying mint
34
+ * @returns Human-readable quote amount (e.g. 450 for "450 USDC")
35
+ */
36
+ export declare function quantityToQuoteAmount(quantity: number, strike1e9: number, underlyingDecimals: number): number;
37
+ export type QuoteDenominatedSizeRule = {
38
+ min: number;
39
+ max: number;
40
+ step: number;
41
+ };
42
+ /**
43
+ * Convert a size_rule (underlying atomic units) to human-readable quote terms.
44
+ *
45
+ * Example: SOL/USDC CSP, strike $90, rule {min: 1e9, max: 10e9, step: 1e8}
46
+ * → returns {min: 90, max: 900, step: 9} (USDC)
47
+ *
48
+ * @param rule Size rule from MarketDescriptorInfo
49
+ * @param strike1e9 Strike price, 1e9-scaled
50
+ * @param underlyingDecimals Decimals of the underlying mint
51
+ */
52
+ export declare function sizeRuleInQuoteTerms(rule: QuantitySizeRuleLike, strike1e9: number, underlyingDecimals: number): QuoteDenominatedSizeRule;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * CSP quantity / size-rule conversion helpers.
3
+ *
4
+ * On the wire, `quantity` is always in underlying atomic units (e.g. SOL lamports).
5
+ * For covered calls the user thinks in underlying (SOL), so no conversion is needed.
6
+ * For cash-secured puts the user thinks in quote (USDC), so the frontend must convert
7
+ * between the user's USDC input and the wire's underlying quantity.
8
+ *
9
+ * These helpers handle that conversion and let the frontend display size_rule
10
+ * constraints in quote terms.
11
+ */
12
+ import { PRICE_SCALE } from "./apy";
13
+ /**
14
+ * Convert a user's quote-denominated deposit (e.g. 450 USDC) to the wire
15
+ * quantity in underlying atomic units.
16
+ *
17
+ * Formula: `round(quoteAmount * 10^underlyingDecimals * PRICE_SCALE / strike1e9)`
18
+ *
19
+ * @param quoteAmount Human-readable quote amount (e.g. 450 for "450 USDC")
20
+ * @param strike1e9 Strike price, 1e9-scaled (e.g. 90_000_000_000 for $90)
21
+ * @param underlyingDecimals Decimals of the underlying mint (e.g. 9 for SOL)
22
+ * @returns Wire quantity (underlying atomic units)
23
+ */
24
+ export function quoteAmountToQuantity(quoteAmount, strike1e9, underlyingDecimals) {
25
+ if (!Number.isFinite(quoteAmount) || quoteAmount < 0) {
26
+ throw new Error("quoteAmount must be a non-negative finite number");
27
+ }
28
+ if (!Number.isFinite(strike1e9) || strike1e9 <= 0) {
29
+ throw new Error("strike1e9 must be a positive finite number");
30
+ }
31
+ const atomicFactor = Math.pow(10, underlyingDecimals);
32
+ return Math.round(quoteAmount * atomicFactor * PRICE_SCALE / strike1e9);
33
+ }
34
+ /**
35
+ * Convert a wire quantity (underlying atomic units) to a human-readable
36
+ * quote-denominated amount.
37
+ *
38
+ * Formula: `quantity * strike1e9 / PRICE_SCALE / 10^underlyingDecimals`
39
+ *
40
+ * @param quantity Wire quantity (underlying atomic units)
41
+ * @param strike1e9 Strike price, 1e9-scaled
42
+ * @param underlyingDecimals Decimals of the underlying mint
43
+ * @returns Human-readable quote amount (e.g. 450 for "450 USDC")
44
+ */
45
+ export function quantityToQuoteAmount(quantity, strike1e9, underlyingDecimals) {
46
+ if (!Number.isFinite(quantity) || quantity < 0) {
47
+ throw new Error("quantity must be a non-negative finite number");
48
+ }
49
+ if (!Number.isFinite(strike1e9) || strike1e9 <= 0) {
50
+ throw new Error("strike1e9 must be a positive finite number");
51
+ }
52
+ const atomicFactor = Math.pow(10, underlyingDecimals);
53
+ return quantity * strike1e9 / PRICE_SCALE / atomicFactor;
54
+ }
55
+ /**
56
+ * Convert a size_rule (underlying atomic units) to human-readable quote terms.
57
+ *
58
+ * Example: SOL/USDC CSP, strike $90, rule {min: 1e9, max: 10e9, step: 1e8}
59
+ * → returns {min: 90, max: 900, step: 9} (USDC)
60
+ *
61
+ * @param rule Size rule from MarketDescriptorInfo
62
+ * @param strike1e9 Strike price, 1e9-scaled
63
+ * @param underlyingDecimals Decimals of the underlying mint
64
+ */
65
+ export function sizeRuleInQuoteTerms(rule, strike1e9, underlyingDecimals) {
66
+ if (!Number.isFinite(strike1e9) || strike1e9 <= 0) {
67
+ throw new Error("strike1e9 must be a positive finite number");
68
+ }
69
+ return {
70
+ min: quantityToQuoteAmount(rule.min_size, strike1e9, underlyingDecimals),
71
+ max: quantityToQuoteAmount(rule.max_size, strike1e9, underlyingDecimals),
72
+ step: quantityToQuoteAmount(rule.step, strike1e9, underlyingDecimals),
73
+ };
74
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,98 @@
1
+ import { quoteAmountToQuantity, quantityToQuoteAmount, sizeRuleInQuoteTerms, } from "./sizing";
2
+ describe("ws sizing helpers", () => {
3
+ // SOL: 9 decimals, strike $90 = 90_000_000_000 (1e9-scaled)
4
+ const SOL_DECIMALS = 9;
5
+ const STRIKE_90 = 90_000_000_000;
6
+ describe("quoteAmountToQuantity", () => {
7
+ it("converts 450 USDC at $90 strike to 5 SOL in lamports", () => {
8
+ expect(quoteAmountToQuantity(450, STRIKE_90, SOL_DECIMALS)).toBe(5_000_000_000);
9
+ });
10
+ it("converts 90 USDC (min) to 1 SOL in lamports", () => {
11
+ expect(quoteAmountToQuantity(90, STRIKE_90, SOL_DECIMALS)).toBe(1_000_000_000);
12
+ });
13
+ it("converts 9 USDC (one step) to 0.1 SOL in lamports", () => {
14
+ expect(quoteAmountToQuantity(9, STRIKE_90, SOL_DECIMALS)).toBe(100_000_000);
15
+ });
16
+ it("returns 0 for 0 input", () => {
17
+ expect(quoteAmountToQuantity(0, STRIKE_90, SOL_DECIMALS)).toBe(0);
18
+ });
19
+ it("throws on negative quoteAmount", () => {
20
+ expect(() => quoteAmountToQuantity(-1, STRIKE_90, SOL_DECIMALS)).toThrow("quoteAmount");
21
+ });
22
+ it("throws on zero strike", () => {
23
+ expect(() => quoteAmountToQuantity(100, 0, SOL_DECIMALS)).toThrow("strike1e9");
24
+ });
25
+ it("throws on negative strike", () => {
26
+ expect(() => quoteAmountToQuantity(100, -1, SOL_DECIMALS)).toThrow("strike1e9");
27
+ });
28
+ });
29
+ describe("quantityToQuoteAmount", () => {
30
+ it("converts 5 SOL lamports at $90 strike to 450 USDC", () => {
31
+ expect(quantityToQuoteAmount(5_000_000_000, STRIKE_90, SOL_DECIMALS)).toBeCloseTo(450, 10);
32
+ });
33
+ it("converts 1 SOL lamports to 90 USDC", () => {
34
+ expect(quantityToQuoteAmount(1_000_000_000, STRIKE_90, SOL_DECIMALS)).toBeCloseTo(90, 10);
35
+ });
36
+ it("converts 0.1 SOL lamports to 9 USDC", () => {
37
+ expect(quantityToQuoteAmount(100_000_000, STRIKE_90, SOL_DECIMALS)).toBeCloseTo(9, 10);
38
+ });
39
+ it("returns 0 for 0 quantity", () => {
40
+ expect(quantityToQuoteAmount(0, STRIKE_90, SOL_DECIMALS)).toBe(0);
41
+ });
42
+ it("throws on negative quantity", () => {
43
+ expect(() => quantityToQuoteAmount(-1, STRIKE_90, SOL_DECIMALS)).toThrow("quantity");
44
+ });
45
+ });
46
+ describe("round-trip", () => {
47
+ it("quoteAmount -> quantity -> quoteAmount is stable", () => {
48
+ const original = 450;
49
+ const quantity = quoteAmountToQuantity(original, STRIKE_90, SOL_DECIMALS);
50
+ const restored = quantityToQuoteAmount(quantity, STRIKE_90, SOL_DECIMALS);
51
+ expect(restored).toBeCloseTo(original, 6);
52
+ });
53
+ it("round-trips at step granularity (9 USDC)", () => {
54
+ const original = 9;
55
+ const quantity = quoteAmountToQuantity(original, STRIKE_90, SOL_DECIMALS);
56
+ const restored = quantityToQuoteAmount(quantity, STRIKE_90, SOL_DECIMALS);
57
+ expect(restored).toBeCloseTo(original, 6);
58
+ });
59
+ it("round-trips with different strike ($150)", () => {
60
+ const strike150 = 150_000_000_000;
61
+ const original = 300;
62
+ const quantity = quoteAmountToQuantity(original, strike150, SOL_DECIMALS);
63
+ expect(quantity).toBe(2_000_000_000); // 2 SOL
64
+ const restored = quantityToQuoteAmount(quantity, strike150, SOL_DECIMALS);
65
+ expect(restored).toBeCloseTo(original, 6);
66
+ });
67
+ });
68
+ describe("sizeRuleInQuoteTerms", () => {
69
+ const rule = { min_size: 1_000_000_000, max_size: 10_000_000_000, step: 100_000_000 };
70
+ it("converts SOL size_rule to USDC terms at $90 strike", () => {
71
+ const result = sizeRuleInQuoteTerms(rule, STRIKE_90, SOL_DECIMALS);
72
+ expect(result.min).toBeCloseTo(90, 6);
73
+ expect(result.max).toBeCloseTo(900, 6);
74
+ expect(result.step).toBeCloseTo(9, 6);
75
+ });
76
+ it("converts at $150 strike", () => {
77
+ const strike150 = 150_000_000_000;
78
+ const result = sizeRuleInQuoteTerms(rule, strike150, SOL_DECIMALS);
79
+ expect(result.min).toBeCloseTo(150, 6);
80
+ expect(result.max).toBeCloseTo(1500, 6);
81
+ expect(result.step).toBeCloseTo(15, 6);
82
+ });
83
+ it("throws on zero strike", () => {
84
+ expect(() => sizeRuleInQuoteTerms(rule, 0, SOL_DECIMALS)).toThrow("strike1e9");
85
+ });
86
+ });
87
+ describe("non-9-decimal underlying", () => {
88
+ // ETH: 8 decimals
89
+ const ETH_DECIMALS = 8;
90
+ const STRIKE_3000 = 3_000_000_000_000; // $3000
91
+ it("converts 6000 USDC at $3000 strike to 2 ETH (8 decimals)", () => {
92
+ expect(quoteAmountToQuantity(6000, STRIKE_3000, ETH_DECIMALS)).toBe(200_000_000);
93
+ });
94
+ it("converts 2 ETH back to 6000 USDC", () => {
95
+ expect(quantityToQuoteAmount(200_000_000, STRIKE_3000, ETH_DECIMALS)).toBeCloseTo(6000, 6);
96
+ });
97
+ });
98
+ });
@@ -741,10 +741,11 @@ export type MakerPositionInfo = {
741
741
  quantity: WsU64;
742
742
  price: WsU64;
743
743
  /** Net premium amount from on-chain position state (quote token base units). */
744
- total_premium: WsU64;
744
+ total_premium?: WsU64;
745
745
  collateral_locked: WsU64;
746
746
  created_at: WsU64;
747
747
  expiry_ts: WsU64;
748
+ is_otm?: boolean;
748
749
  };
749
750
  export type MyQuotesMessage = {
750
751
  request_id: RequestId;
@@ -1013,10 +1014,11 @@ export type PositionInfo = {
1013
1014
  quantity: WsU64;
1014
1015
  price: WsU64;
1015
1016
  /** Net premium amount from on-chain position state (quote token base units). */
1016
- total_premium: WsU64;
1017
+ total_premium?: WsU64;
1017
1018
  created_at: WsU64;
1018
1019
  /** Market expiry timestamp (unix seconds), sourced from markets table join. */
1019
1020
  expiry_ts: WsU64;
1021
+ is_otm?: boolean;
1020
1022
  };
1021
1023
  export type TradeInfo = {
1022
1024
  id: UuidString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acta-markets/ts-sdk",
3
- "version": "0.0.12-beta",
3
+ "version": "0.0.14-beta",
4
4
  "description": "TypeScript SDK for Acta Protocol",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",