@usesigil/kit 0.15.0 → 0.16.0

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 (229) hide show
  1. package/dist/agent-bootstrap.d.ts +118 -0
  2. package/dist/agent-bootstrap.d.ts.map +1 -0
  3. package/dist/agent-bootstrap.js +211 -0
  4. package/dist/agent-bootstrap.js.map +1 -0
  5. package/dist/agent-errors.d.ts +3 -3
  6. package/dist/agent-errors.d.ts.map +1 -1
  7. package/dist/agent-errors.js +227 -142
  8. package/dist/agent-errors.js.map +1 -1
  9. package/dist/build-unsigned.d.ts +152 -0
  10. package/dist/build-unsigned.d.ts.map +1 -0
  11. package/dist/build-unsigned.js +152 -0
  12. package/dist/build-unsigned.js.map +1 -0
  13. package/dist/constraints/index.d.ts +23 -0
  14. package/dist/constraints/index.d.ts.map +1 -0
  15. package/dist/constraints/index.js +24 -0
  16. package/dist/constraints/index.js.map +1 -0
  17. package/dist/create-vault.d.ts +10 -1
  18. package/dist/create-vault.d.ts.map +1 -1
  19. package/dist/create-vault.js +10 -2
  20. package/dist/create-vault.js.map +1 -1
  21. package/dist/dashboard/constraint-builders.d.ts +82 -0
  22. package/dist/dashboard/constraint-builders.d.ts.map +1 -0
  23. package/dist/dashboard/constraint-builders.js +204 -0
  24. package/dist/dashboard/constraint-builders.js.map +1 -0
  25. package/dist/dashboard/errors.d.ts +37 -0
  26. package/dist/dashboard/errors.d.ts.map +1 -1
  27. package/dist/dashboard/errors.js +76 -0
  28. package/dist/dashboard/errors.js.map +1 -1
  29. package/dist/dashboard/from-json.d.ts.map +1 -1
  30. package/dist/dashboard/from-json.js +1 -2
  31. package/dist/dashboard/from-json.js.map +1 -1
  32. package/dist/dashboard/index.d.ts +29 -3
  33. package/dist/dashboard/index.d.ts.map +1 -1
  34. package/dist/dashboard/index.js +36 -1
  35. package/dist/dashboard/index.js.map +1 -1
  36. package/dist/dashboard/mutations.d.ts +60 -1
  37. package/dist/dashboard/mutations.d.ts.map +1 -1
  38. package/dist/dashboard/mutations.js +127 -20
  39. package/dist/dashboard/mutations.js.map +1 -1
  40. package/dist/dashboard/post-assertion-validation.d.ts +88 -0
  41. package/dist/dashboard/post-assertion-validation.d.ts.map +1 -0
  42. package/dist/dashboard/post-assertion-validation.js +191 -0
  43. package/dist/dashboard/post-assertion-validation.js.map +1 -0
  44. package/dist/dashboard/reads.d.ts +93 -1
  45. package/dist/dashboard/reads.d.ts.map +1 -1
  46. package/dist/dashboard/reads.js +238 -9
  47. package/dist/dashboard/reads.js.map +1 -1
  48. package/dist/dashboard/types.d.ts +147 -11
  49. package/dist/dashboard/types.d.ts.map +1 -1
  50. package/dist/errors/codes.js +1 -1
  51. package/dist/events.d.ts.map +1 -1
  52. package/dist/events.js +2 -1
  53. package/dist/events.js.map +1 -1
  54. package/dist/generated/accounts/pendingAgentPermissionsUpdate.d.ts +12 -0
  55. package/dist/generated/accounts/pendingAgentPermissionsUpdate.d.ts.map +1 -1
  56. package/dist/generated/accounts/pendingAgentPermissionsUpdate.js +3 -1
  57. package/dist/generated/accounts/pendingAgentPermissionsUpdate.js.map +1 -1
  58. package/dist/generated/accounts/pendingCloseConstraints.d.ts +12 -0
  59. package/dist/generated/accounts/pendingCloseConstraints.d.ts.map +1 -1
  60. package/dist/generated/accounts/pendingCloseConstraints.js +4 -2
  61. package/dist/generated/accounts/pendingCloseConstraints.js.map +1 -1
  62. package/dist/generated/accounts/pendingConstraintsUpdate.d.ts +14 -0
  63. package/dist/generated/accounts/pendingConstraintsUpdate.d.ts.map +1 -1
  64. package/dist/generated/accounts/pendingConstraintsUpdate.js +4 -2
  65. package/dist/generated/accounts/pendingConstraintsUpdate.js.map +1 -1
  66. package/dist/generated/accounts/pendingPolicyUpdate.d.ts +24 -4
  67. package/dist/generated/accounts/pendingPolicyUpdate.d.ts.map +1 -1
  68. package/dist/generated/accounts/pendingPolicyUpdate.js +6 -4
  69. package/dist/generated/accounts/pendingPolicyUpdate.js.map +1 -1
  70. package/dist/generated/accounts/policyConfig.d.ts +28 -10
  71. package/dist/generated/accounts/policyConfig.d.ts.map +1 -1
  72. package/dist/generated/accounts/policyConfig.js +4 -4
  73. package/dist/generated/accounts/policyConfig.js.map +1 -1
  74. package/dist/generated/accounts/sessionAuthority.d.ts +18 -4
  75. package/dist/generated/accounts/sessionAuthority.d.ts.map +1 -1
  76. package/dist/generated/accounts/sessionAuthority.js +3 -3
  77. package/dist/generated/accounts/sessionAuthority.js.map +1 -1
  78. package/dist/generated/errors/sigil.d.ts +95 -81
  79. package/dist/generated/errors/sigil.d.ts.map +1 -1
  80. package/dist/generated/errors/sigil.js +107 -86
  81. package/dist/generated/errors/sigil.js.map +1 -1
  82. package/dist/generated/event-discriminators.d.ts.map +1 -1
  83. package/dist/generated/event-discriminators.js +2 -1
  84. package/dist/generated/event-discriminators.js.map +1 -1
  85. package/dist/generated/instructions/cleanupOrphanConstraintsPda.d.ts +67 -0
  86. package/dist/generated/instructions/cleanupOrphanConstraintsPda.d.ts.map +1 -0
  87. package/dist/generated/instructions/cleanupOrphanConstraintsPda.js +120 -0
  88. package/dist/generated/instructions/cleanupOrphanConstraintsPda.js.map +1 -0
  89. package/dist/generated/instructions/freezeVault.d.ts +8 -5
  90. package/dist/generated/instructions/freezeVault.d.ts.map +1 -1
  91. package/dist/generated/instructions/freezeVault.js +14 -3
  92. package/dist/generated/instructions/freezeVault.js.map +1 -1
  93. package/dist/generated/instructions/index.d.ts +1 -0
  94. package/dist/generated/instructions/index.d.ts.map +1 -1
  95. package/dist/generated/instructions/index.js +1 -0
  96. package/dist/generated/instructions/index.js.map +1 -1
  97. package/dist/generated/instructions/initializeVault.d.ts +0 -4
  98. package/dist/generated/instructions/initializeVault.d.ts.map +1 -1
  99. package/dist/generated/instructions/initializeVault.js +0 -2
  100. package/dist/generated/instructions/initializeVault.js.map +1 -1
  101. package/dist/generated/instructions/queuePolicyUpdate.d.ts +8 -8
  102. package/dist/generated/instructions/queuePolicyUpdate.d.ts.map +1 -1
  103. package/dist/generated/instructions/queuePolicyUpdate.js +4 -4
  104. package/dist/generated/instructions/queuePolicyUpdate.js.map +1 -1
  105. package/dist/generated/programs/sigil.d.ts +29 -25
  106. package/dist/generated/programs/sigil.d.ts.map +1 -1
  107. package/dist/generated/programs/sigil.js +37 -25
  108. package/dist/generated/programs/sigil.js.map +1 -1
  109. package/dist/generated/types/accountConstraint.d.ts +16 -1
  110. package/dist/generated/types/accountConstraint.d.ts.map +1 -1
  111. package/dist/generated/types/accountConstraint.js +2 -0
  112. package/dist/generated/types/accountConstraint.js.map +1 -1
  113. package/dist/generated/types/accountConstraintZC.d.ts +7 -0
  114. package/dist/generated/types/accountConstraintZC.d.ts.map +1 -1
  115. package/dist/generated/types/accountConstraintZC.js +4 -2
  116. package/dist/generated/types/accountConstraintZC.js.map +1 -1
  117. package/dist/generated/types/constraintEntry.d.ts +0 -4
  118. package/dist/generated/types/constraintEntry.d.ts.map +1 -1
  119. package/dist/generated/types/constraintEntry.js +1 -3
  120. package/dist/generated/types/constraintEntry.js.map +1 -1
  121. package/dist/generated/types/constraintEntryZC.d.ts +17 -12
  122. package/dist/generated/types/constraintEntryZC.d.ts.map +1 -1
  123. package/dist/generated/types/constraintEntryZC.js +2 -2
  124. package/dist/generated/types/constraintEntryZC.js.map +1 -1
  125. package/dist/generated/types/index.d.ts +1 -0
  126. package/dist/generated/types/index.d.ts.map +1 -1
  127. package/dist/generated/types/index.js +1 -0
  128. package/dist/generated/types/index.js.map +1 -1
  129. package/dist/generated/types/orphanConstraintsPdaCleaned.d.ts +22 -0
  130. package/dist/generated/types/orphanConstraintsPdaCleaned.d.ts.map +1 -0
  131. package/dist/generated/types/orphanConstraintsPdaCleaned.js +26 -0
  132. package/dist/generated/types/orphanConstraintsPdaCleaned.js.map +1 -0
  133. package/dist/generated/types/vaultFrozen.d.ts +12 -0
  134. package/dist/generated/types/vaultFrozen.d.ts.map +1 -1
  135. package/dist/generated/types/vaultFrozen.js +3 -1
  136. package/dist/generated/types/vaultFrozen.js.map +1 -1
  137. package/dist/index.d.ts +11 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +22 -1
  140. package/dist/index.js.map +1 -1
  141. package/dist/inscribe.d.ts +0 -4
  142. package/dist/inscribe.d.ts.map +1 -1
  143. package/dist/inscribe.js +0 -1
  144. package/dist/inscribe.js.map +1 -1
  145. package/dist/kit-adapter.d.ts +1 -1
  146. package/dist/kit-adapter.d.ts.map +1 -1
  147. package/dist/kit-adapter.js +1 -1
  148. package/dist/kit-adapter.js.map +1 -1
  149. package/dist/logger.d.ts +48 -0
  150. package/dist/logger.d.ts.map +1 -1
  151. package/dist/logger.js +36 -0
  152. package/dist/logger.js.map +1 -1
  153. package/dist/owner-transaction.d.ts +8 -0
  154. package/dist/owner-transaction.d.ts.map +1 -1
  155. package/dist/owner-transaction.js +1 -0
  156. package/dist/owner-transaction.js.map +1 -1
  157. package/dist/post-assertions/cross-field-lte.d.ts +134 -0
  158. package/dist/post-assertions/cross-field-lte.d.ts.map +1 -0
  159. package/dist/post-assertions/cross-field-lte.js +129 -0
  160. package/dist/post-assertions/cross-field-lte.js.map +1 -0
  161. package/dist/post-assertions/index.d.ts +28 -0
  162. package/dist/post-assertions/index.d.ts.map +1 -0
  163. package/dist/post-assertions/index.js +28 -0
  164. package/dist/post-assertions/index.js.map +1 -0
  165. package/dist/post-assertions/presets/flash-trade.d.ts +139 -0
  166. package/dist/post-assertions/presets/flash-trade.d.ts.map +1 -0
  167. package/dist/post-assertions/presets/flash-trade.js +154 -0
  168. package/dist/post-assertions/presets/flash-trade.js.map +1 -0
  169. package/dist/presets.d.ts +1 -7
  170. package/dist/presets.d.ts.map +1 -1
  171. package/dist/presets.js +0 -5
  172. package/dist/presets.js.map +1 -1
  173. package/dist/preview-create-vault.d.ts +280 -0
  174. package/dist/preview-create-vault.d.ts.map +1 -0
  175. package/dist/preview-create-vault.js +477 -0
  176. package/dist/preview-create-vault.js.map +1 -0
  177. package/dist/protocol-registry/annotations/drift.json +7 -0
  178. package/dist/protocol-registry/annotations/flash-trade.json +7 -0
  179. package/dist/protocol-registry/annotations/jupiter-borrow.json +7 -0
  180. package/dist/protocol-registry/annotations/jupiter-earn.json +7 -0
  181. package/dist/protocol-registry/annotations/jupiter-lend.json +7 -0
  182. package/dist/protocol-registry/annotations/jupiter.json +7 -0
  183. package/dist/protocol-registry/annotations/kamino.json +7 -0
  184. package/dist/protocol-registry/index.d.ts +45 -0
  185. package/dist/protocol-registry/index.d.ts.map +1 -0
  186. package/dist/protocol-registry/index.js +76 -0
  187. package/dist/protocol-registry/index.js.map +1 -0
  188. package/dist/protocol-tier.d.ts +157 -0
  189. package/dist/protocol-tier.d.ts.map +1 -0
  190. package/dist/protocol-tier.js +104 -0
  191. package/dist/protocol-tier.js.map +1 -0
  192. package/dist/seal.d.ts.map +1 -1
  193. package/dist/seal.js +26 -2
  194. package/dist/seal.js.map +1 -1
  195. package/dist/sigil.d.ts +0 -4
  196. package/dist/sigil.d.ts.map +1 -1
  197. package/dist/simulation.d.ts.map +1 -1
  198. package/dist/simulation.js +72 -91
  199. package/dist/simulation.js.map +1 -1
  200. package/dist/testing/devnet.d.ts.map +1 -1
  201. package/dist/testing/devnet.js +0 -1
  202. package/dist/testing/devnet.js.map +1 -1
  203. package/dist/testing/errors/expect.d.ts +137 -0
  204. package/dist/testing/errors/expect.d.ts.map +1 -0
  205. package/dist/testing/errors/expect.js +372 -0
  206. package/dist/testing/errors/expect.js.map +1 -0
  207. package/dist/testing/errors/index.d.ts +3 -0
  208. package/dist/testing/errors/index.d.ts.map +1 -0
  209. package/dist/testing/errors/index.js +8 -0
  210. package/dist/testing/errors/index.js.map +1 -0
  211. package/dist/testing/errors/names.generated.d.ts +188 -0
  212. package/dist/testing/errors/names.generated.d.ts.map +1 -0
  213. package/dist/testing/errors/names.generated.js +183 -0
  214. package/dist/testing/errors/names.generated.js.map +1 -0
  215. package/dist/testing/index.d.ts +1 -0
  216. package/dist/testing/index.d.ts.map +1 -1
  217. package/dist/testing/index.js +8 -0
  218. package/dist/testing/index.js.map +1 -1
  219. package/dist/testing/mock-rpc.d.ts +8 -0
  220. package/dist/testing/mock-rpc.d.ts.map +1 -1
  221. package/dist/testing/mock-rpc.js +14 -0
  222. package/dist/testing/mock-rpc.js.map +1 -1
  223. package/dist/testing/mock-state.js +2 -2
  224. package/dist/testing/mock-state.js.map +1 -1
  225. package/package.json +15 -3
  226. package/dist/integrations/protocol-handler.d.ts +0 -59
  227. package/dist/integrations/protocol-handler.d.ts.map +0 -1
  228. package/dist/integrations/protocol-handler.js +0 -9
  229. package/dist/integrations/protocol-handler.js.map +0 -1
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @usesigil/kit/post-assertions — CrossFieldLte builder.
3
+ *
4
+ * Constructs a PostAssertionEntry that performs a ratio check on two byte
5
+ * offsets inside the same target account AFTER the DeFi call completes.
6
+ *
7
+ * The on-chain check: `field_A × 10000 ≤ multiplier_bps × field_B`
8
+ * (u128 safe math, cross-multiplication to avoid division).
9
+ *
10
+ * Typical use: leverage caps. field_A = sizeUsd, field_B = collateralUsd,
11
+ * multiplier_bps = maxLeverage × 10000. If the cap is violated, the program
12
+ * raises `PostAssertionFailed` (6068) and the entire transaction reverts.
13
+ *
14
+ * ## Jupiter Perpetuals UX rail — NOT a security boundary
15
+ *
16
+ * `leverageCapLteBps()` throws `JupiterPerpsPostAssertionUnsupportedError`
17
+ * when the caller supplies a target account owned by the Jupiter Perpetuals
18
+ * program. This is a **UX-level misuse-prevention guardrail**, NOT a
19
+ * security guarantee — the on-chain program does **not** reject Jupiter
20
+ * Perps target accounts. A caller who constructs a plain `PostAssertionEntry`
21
+ * object literal (skipping this builder) and passes it to
22
+ * `createPostAssertions(...)` WILL land an entry that targets a Jupiter
23
+ * Perps Position account. That entry will always pass trivially, because:
24
+ *
25
+ * Jupiter Perps uses a 2-transaction keeper-fulfillment model — the user's
26
+ * tx writes a PositionRequest, and a Jupiter-hosted keeper executes the
27
+ * actual position change up to 45 seconds later. Sigil's
28
+ * `finalize_session` reads account state in the USER's tx, not the keeper's,
29
+ * so the Jupiter Position account still reflects pre-trade state at check
30
+ * time. CrossFieldLte post-execution over that account therefore is a
31
+ * **silent constraint bypass** — the user thinks their leverage cap is
32
+ * active when it isn't.
33
+ *
34
+ * For REAL security on Jupiter Perps, combine with pre-execution
35
+ * `InstructionConstraints` (the `@sigil-trade/constraints` package compiles
36
+ * byte-level checks on Jupiter instruction args that the on-chain program
37
+ * enforces BEFORE the request hits the keeper — covers the same attack
38
+ * surface from the opposite direction).
39
+ *
40
+ * Follow-up work (tracked in the Phase 2 PRD as deferred): add an on-chain
41
+ * `target_account.owner` deny-list check in `finalize_session.rs` that
42
+ * rejects CrossFieldLte entries whose target account is owned by Jupiter
43
+ * Perpetuals. Until that lands, this builder's rail is defense-against-
44
+ * typos, nothing more.
45
+ *
46
+ * @see programs/sigil/src/state/post_assertions.rs — on-chain source of truth
47
+ * @see docs/LEVERAGE-ENFORCEMENT.md — full Jupiter Perps gap writeup
48
+ */
49
+ import type { Address } from "@solana/kit";
50
+ import type { PostAssertionEntry } from "../generated/types/postAssertionEntry.js";
51
+ /**
52
+ * Jupiter Perpetuals program. Owner of Position + PositionRequest accounts.
53
+ *
54
+ * This is the ONLY Jupiter program the `leverageCapLteBps` builder refuses
55
+ * at authoring time (see the docblock above for why — UX rail, not on-chain
56
+ * security). Other Jupiter programs (V6 Aggregator, Lend, Earn, Borrow)
57
+ * execute synchronously in the user's transaction and work fine with
58
+ * post-execution assertions.
59
+ */
60
+ export declare const JUPITER_PERPS_PROGRAM_ADDRESS: Address;
61
+ /**
62
+ * Thrown by {@link leverageCapLteBps} when the target account is owned by
63
+ * the Jupiter Perpetuals program. Carries a long, copy-paste-friendly
64
+ * explanation so the error bubbling to the dashboard is actionable.
65
+ */
66
+ export declare class JupiterPerpsPostAssertionUnsupportedError extends Error {
67
+ constructor(message: string);
68
+ }
69
+ /**
70
+ * Options for `leverageCapLteBps`.
71
+ *
72
+ * `targetAccountOwnerProgram` is REQUIRED (not optional) so that callers
73
+ * cannot accidentally bypass the Jupiter Perpetuals safety check by
74
+ * omitting the ownership hint. If the caller doesn't know the owner
75
+ * program, they shouldn't be building a post-execution leverage cap.
76
+ */
77
+ export interface LeverageCapLteOpts {
78
+ /**
79
+ * Address of the account whose bytes will be inspected post-execution.
80
+ * Typically the Position PDA for the protocol being constrained
81
+ * (e.g. Flash Trade Position account).
82
+ */
83
+ targetAccount: Address;
84
+ /**
85
+ * Address of the program that OWNS `targetAccount`. Required for the
86
+ * Jupiter Perpetuals safety rail. When this matches
87
+ * {@link JUPITER_PERPS_PROGRAM_ADDRESS}, the helper throws
88
+ * {@link JupiterPerpsPostAssertionUnsupportedError} — see file header.
89
+ */
90
+ targetAccountOwnerProgram: Address;
91
+ /**
92
+ * Byte offset of field_A (the "numerator" field) inside `targetAccount`.
93
+ * Read as `u64` LE (8 bytes from this offset). Must be in `0..=65535`.
94
+ * Typical: `sizeUsd` offset = 140 on Flash Trade Position.
95
+ */
96
+ fieldAOffset: number;
97
+ /**
98
+ * Byte offset of field_B (the "denominator" field). Read as `u64` LE.
99
+ * Must be in `0..=65535` and MUST differ from `fieldAOffset` — comparing
100
+ * a field against itself is either a no-op or a trap.
101
+ * Typical: `collateralUsd` offset = 172 on Flash Trade Position.
102
+ */
103
+ fieldBOffset: number;
104
+ /**
105
+ * Leverage cap expressed in basis points: `maxBps = leverage × 10_000`.
106
+ *
107
+ * The on-chain check is `field_A × 10_000 ≤ maxBps × field_B`.
108
+ * Examples:
109
+ * - 10× → `maxBps = 100_000`
110
+ * - 50× → `maxBps = 500_000`
111
+ * - 100× → `maxBps = 1_000_000`
112
+ *
113
+ * Must be a positive integer in `1..=u32::MAX`. Prefer conservative caps;
114
+ * never set to the protocol's maximum.
115
+ */
116
+ maxBps: number;
117
+ }
118
+ /**
119
+ * Build a PostAssertionEntry that enforces a leverage cap via the
120
+ * CrossFieldLte ratio check.
121
+ *
122
+ * Validates inputs, rejects Jupiter Perpetuals Position accounts at the
123
+ * call site, and returns an entry ready to pass to
124
+ * `createPostAssertions(rpc, vault, owner, network, [entry])`.
125
+ *
126
+ * @throws {JupiterPerpsPostAssertionUnsupportedError}
127
+ * When `targetAccountOwnerProgram` matches
128
+ * {@link JUPITER_PERPS_PROGRAM_ADDRESS}. See file header for why.
129
+ * @throws {RangeError}
130
+ * When offsets are not integers in `0..=65535`, are equal to each other,
131
+ * or when `maxBps` is not a positive integer in `1..=u32::MAX`.
132
+ */
133
+ export declare function leverageCapLteBps(opts: LeverageCapLteOpts): PostAssertionEntry;
134
+ //# sourceMappingURL=cross-field-lte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-field-lte.d.ts","sourceRoot":"","sources":["../../src/post-assertions/cross-field-lte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,aAAa,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAInF;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B,EACS,OAAO,CAAC;AA2C3D;;;;GAIG;AACH,qBAAa,yCAA0C,SAAQ,KAAK;gBACtD,OAAO,EAAE,MAAM;CAQ5B;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,yBAAyB,EAAE,OAAO,CAAC;IACnC;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,kBAAkB,GACvB,kBAAkB,CAmDpB"}
@@ -0,0 +1,129 @@
1
+ // ─── Constants ────────────────────────────────────────────────────────────
2
+ /**
3
+ * Jupiter Perpetuals program. Owner of Position + PositionRequest accounts.
4
+ *
5
+ * This is the ONLY Jupiter program the `leverageCapLteBps` builder refuses
6
+ * at authoring time (see the docblock above for why — UX rail, not on-chain
7
+ * security). Other Jupiter programs (V6 Aggregator, Lend, Earn, Borrow)
8
+ * execute synchronously in the user's transaction and work fine with
9
+ * post-execution assertions.
10
+ */
11
+ export const JUPITER_PERPS_PROGRAM_ADDRESS = "PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu";
12
+ /**
13
+ * CrossFieldLte enable bit — bit 0 of `cross_field_flags`.
14
+ * Every other bit is reserved; the on-chain validator rejects unknown flags.
15
+ */
16
+ const CROSS_FIELD_LTE_FLAG = 0x01;
17
+ /**
18
+ * Both field_A and field_B are parsed as `u64::from_le_bytes(bytes[0..8])`
19
+ * on-chain when CrossFieldLte is enabled. Entry's `value_len` MUST be 8.
20
+ */
21
+ const CROSS_FIELD_VALUE_LEN = 8;
22
+ /**
23
+ * CrossFieldLte only composes with Absolute assertion_mode. Delta modes
24
+ * (1/2/3) would re-interpret the snapshot bytes as field_A, which is
25
+ * semantically nonsensical — on-chain hard-rejects.
26
+ */
27
+ const ABSOLUTE_ASSERTION_MODE = 0;
28
+ /**
29
+ * Lte operator (3). Not actually consulted at runtime when the CrossField
30
+ * flag is set — the on-chain code branches to the ratio check and ignores
31
+ * operator/expected_value. Set to 3 here as a semantic hint for anyone
32
+ * inspecting the raw entry: "this is a less-than-or-equal check."
33
+ */
34
+ const LTE_OPERATOR = 3;
35
+ /**
36
+ * u16 range guard for byte offsets. Account data is at most ~10MB but
37
+ * PostAssertionEntry.offset is a u16 on-chain, capping at 65535.
38
+ */
39
+ const MAX_U16 = 0xffff;
40
+ /**
41
+ * u32 range guard for `cross_field_multiplier_bps`. The on-chain type is
42
+ * u32. Values above this would overflow deserialization.
43
+ */
44
+ const MAX_U32 = 0xffffffff;
45
+ // ─── Errors ───────────────────────────────────────────────────────────────
46
+ /**
47
+ * Thrown by {@link leverageCapLteBps} when the target account is owned by
48
+ * the Jupiter Perpetuals program. Carries a long, copy-paste-friendly
49
+ * explanation so the error bubbling to the dashboard is actionable.
50
+ */
51
+ export class JupiterPerpsPostAssertionUnsupportedError extends Error {
52
+ constructor(message) {
53
+ super(message);
54
+ this.name = "JupiterPerpsPostAssertionUnsupportedError";
55
+ Object.setPrototypeOf(this, JupiterPerpsPostAssertionUnsupportedError.prototype);
56
+ }
57
+ }
58
+ /**
59
+ * Build a PostAssertionEntry that enforces a leverage cap via the
60
+ * CrossFieldLte ratio check.
61
+ *
62
+ * Validates inputs, rejects Jupiter Perpetuals Position accounts at the
63
+ * call site, and returns an entry ready to pass to
64
+ * `createPostAssertions(rpc, vault, owner, network, [entry])`.
65
+ *
66
+ * @throws {JupiterPerpsPostAssertionUnsupportedError}
67
+ * When `targetAccountOwnerProgram` matches
68
+ * {@link JUPITER_PERPS_PROGRAM_ADDRESS}. See file header for why.
69
+ * @throws {RangeError}
70
+ * When offsets are not integers in `0..=65535`, are equal to each other,
71
+ * or when `maxBps` is not a positive integer in `1..=u32::MAX`.
72
+ */
73
+ export function leverageCapLteBps(opts) {
74
+ // Runtime Jupiter Perps reject (Phase 2 ISC-37, anti-criterion ISC-A1).
75
+ // Fails before any further validation so the error surface points at
76
+ // the real problem rather than incidental validation failures.
77
+ if (opts.targetAccountOwnerProgram === JUPITER_PERPS_PROGRAM_ADDRESS) {
78
+ throw new JupiterPerpsPostAssertionUnsupportedError(`Post-execution CrossFieldLte is NOT viable on Jupiter Perpetuals Position accounts.\n\n` +
79
+ `Reason: Jupiter Perps uses a 2-transaction keeper-fulfillment model. The user's tx writes ` +
80
+ `to a PositionRequest account; a Jupiter-hosted keeper executes the actual position change ` +
81
+ `up to 45 seconds later in a separate tx. Sigil's finalize_session reads account state in ` +
82
+ `the user's tx — at that point the Jupiter Position account still reflects pre-trade state. ` +
83
+ `The leverage check would always pass trivially, creating a silent constraint bypass.\n\n` +
84
+ `Jupiter Perps remains a fully supported protocol for agent use. Configure constraints ` +
85
+ `via pre-execution InstructionConstraints instead — @sigil-trade/constraints compiles ` +
86
+ `byte-level checks on Jupiter instruction args (sizeUsd, collateralUsd in the request) ` +
87
+ `that are enforced BEFORE the request hits the keeper.\n\n` +
88
+ `See docs/LEVERAGE-ENFORCEMENT.md — "Jupiter Perps — use pre-execution constraints".`);
89
+ }
90
+ // Offset range / integrality checks (u16 on-chain).
91
+ requireIntegerInRange(opts.fieldAOffset, "fieldAOffset", 0, MAX_U16);
92
+ requireIntegerInRange(opts.fieldBOffset, "fieldBOffset", 0, MAX_U16);
93
+ if (opts.fieldAOffset === opts.fieldBOffset) {
94
+ throw new RangeError(`leverageCapLteBps: fieldAOffset and fieldBOffset must differ — ratio of a field against itself is nonsensical (got ${opts.fieldAOffset})`);
95
+ }
96
+ // Multiplier range / integrality check (u32 on-chain, must be > 0).
97
+ requireIntegerInRange(opts.maxBps, "maxBps", 1, MAX_U32);
98
+ // All-zero expected_value — the on-chain CrossField path ignores this
99
+ // field, but validate_entries still requires `expected_value.len() >=
100
+ // value_len`. We ship exactly `CROSS_FIELD_VALUE_LEN` (8) bytes to
101
+ // satisfy the size invariant without wasting space.
102
+ const expectedValue = new Uint8Array(CROSS_FIELD_VALUE_LEN);
103
+ return {
104
+ targetAccount: opts.targetAccount,
105
+ offset: opts.fieldAOffset,
106
+ valueLen: CROSS_FIELD_VALUE_LEN,
107
+ operator: LTE_OPERATOR,
108
+ expectedValue,
109
+ assertionMode: ABSOLUTE_ASSERTION_MODE,
110
+ crossFieldOffsetB: opts.fieldBOffset,
111
+ crossFieldMultiplierBps: opts.maxBps,
112
+ crossFieldFlags: CROSS_FIELD_LTE_FLAG,
113
+ };
114
+ }
115
+ // ─── Internal ─────────────────────────────────────────────────────────────
116
+ /**
117
+ * Guard that rejects non-integer, out-of-range, or non-finite values.
118
+ * Matches JS's pre-coercion discipline: a string `"8"` should NOT silently
119
+ * pass an integer check, and `NaN` / `Infinity` must not sneak through.
120
+ */
121
+ function requireIntegerInRange(value, field, min, max) {
122
+ if (typeof value !== "number" || !Number.isInteger(value)) {
123
+ throw new RangeError(`leverageCapLteBps: ${field} must be an integer, got ${JSON.stringify(value)} (${typeof value})`);
124
+ }
125
+ if (value < min || value > max) {
126
+ throw new RangeError(`leverageCapLteBps: ${field} must be in ${min}..=${max}, got ${value}`);
127
+ }
128
+ }
129
+ //# sourceMappingURL=cross-field-lte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-field-lte.js","sourceRoot":"","sources":["../../src/post-assertions/cross-field-lte.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `@usesigil/kit/post-assertions` — builders for post-execution assertion
3
+ * entries.
4
+ *
5
+ * This barrel exposes the typed helpers a dashboard or headless caller
6
+ * needs to author `PostAssertionEntry` values for the
7
+ * `createPostAssertions(...)` mutation without reaching into codegen
8
+ * (covenant D1: no imports from `src/generated/**`).
9
+ *
10
+ * Currently exported:
11
+ * - `leverageCapLteBps({ ... })` — generic CrossFieldLte builder for a
12
+ * "field_A ≤ maxBps × field_B" ratio check
13
+ * - `JupiterPerpsPostAssertionUnsupportedError` — thrown when a caller
14
+ * tries to build a leverage cap against a Jupiter Perpetuals Position
15
+ * account (keeper-fulfillment model breaks post-execution semantics)
16
+ * - `JUPITER_PERPS_PROGRAM_ADDRESS` — re-exported so callers can do their
17
+ * own pre-check if they prefer reporting over throwing
18
+ *
19
+ * Protocol-specific presets (e.g. `flashTradeLeverageCap`) land in a
20
+ * `./presets/` sub-directory as they ship — one preset per protocol,
21
+ * each backed by a committed IDL with a CI drift-check.
22
+ */
23
+ export { JUPITER_PERPS_PROGRAM_ADDRESS, JupiterPerpsPostAssertionUnsupportedError, leverageCapLteBps, } from "./cross-field-lte.js";
24
+ export type { LeverageCapLteOpts } from "./cross-field-lte.js";
25
+ export { FLASH_TRADE_PROGRAM_ADDRESS, FLASH_TRADE_POSITION_SIZE_USD_OFFSET, FLASH_TRADE_POSITION_COLLATERAL_USD_OFFSET, MIN_LEVERAGE_X, MAX_LEVERAGE_X, FlashTradeLeverageOutOfRangeError, flashTradeLeverageCap, } from "./presets/flash-trade.js";
26
+ export type { FlashTradeLeverageCapOpts } from "./presets/flash-trade.js";
27
+ export type { PostAssertionEntry } from "../generated/types/postAssertionEntry.js";
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/post-assertions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EACL,6BAA6B,EAC7B,yCAAyC,EACzC,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK/D,OAAO,EACL,2BAA2B,EAC3B,oCAAoC,EACpC,0CAA0C,EAC1C,cAAc,EACd,cAAc,EACd,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAK1E,YAAY,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `@usesigil/kit/post-assertions` — builders for post-execution assertion
3
+ * entries.
4
+ *
5
+ * This barrel exposes the typed helpers a dashboard or headless caller
6
+ * needs to author `PostAssertionEntry` values for the
7
+ * `createPostAssertions(...)` mutation without reaching into codegen
8
+ * (covenant D1: no imports from `src/generated/**`).
9
+ *
10
+ * Currently exported:
11
+ * - `leverageCapLteBps({ ... })` — generic CrossFieldLte builder for a
12
+ * "field_A ≤ maxBps × field_B" ratio check
13
+ * - `JupiterPerpsPostAssertionUnsupportedError` — thrown when a caller
14
+ * tries to build a leverage cap against a Jupiter Perpetuals Position
15
+ * account (keeper-fulfillment model breaks post-execution semantics)
16
+ * - `JUPITER_PERPS_PROGRAM_ADDRESS` — re-exported so callers can do their
17
+ * own pre-check if they prefer reporting over throwing
18
+ *
19
+ * Protocol-specific presets (e.g. `flashTradeLeverageCap`) land in a
20
+ * `./presets/` sub-directory as they ship — one preset per protocol,
21
+ * each backed by a committed IDL with a CI drift-check.
22
+ */
23
+ export { JUPITER_PERPS_PROGRAM_ADDRESS, JupiterPerpsPostAssertionUnsupportedError, leverageCapLteBps, } from "./cross-field-lte.js";
24
+ // Protocol-specific presets — one file per protocol under `./presets/`.
25
+ // Each preset is backed by a committed IDL source with a drift-check test so
26
+ // any future SDK bump that shifts field offsets fails before shipping.
27
+ export { FLASH_TRADE_PROGRAM_ADDRESS, FLASH_TRADE_POSITION_SIZE_USD_OFFSET, FLASH_TRADE_POSITION_COLLATERAL_USD_OFFSET, MIN_LEVERAGE_X, MAX_LEVERAGE_X, FlashTradeLeverageOutOfRangeError, flashTradeLeverageCap, } from "./presets/flash-trade.js";
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/post-assertions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EACL,6BAA6B,EAC7B,yCAAyC,EACzC,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAG9B,wEAAwE;AACxE,6EAA6E;AAC7E,uEAAuE;AACvE,OAAO,EACL,2BAA2B,EAC3B,oCAAoC,EACpC,0CAA0C,EAC1C,cAAc,EACd,cAAc,EACd,iCAAiC,EACjC,qBAAqB,GACtB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * `@usesigil/kit/post-assertions/presets/flash-trade` — Flash Trade leverage cap preset.
3
+ *
4
+ * Convenience wrapper around `leverageCapLteBps` that fills in the byte offsets
5
+ * of a Flash Trade Position account's `size_usd` and `collateral_usd` fields.
6
+ *
7
+ * Callers provide a position account address + a leverage cap expressed in
8
+ * "x" (multiples), and the preset returns a `PostAssertionEntry` that the
9
+ * on-chain program enforces as:
10
+ *
11
+ * size_usd × 10000 ≤ maxLeverage × 10000 × collateral_usd
12
+ * ⇔ leverage (= size_usd / collateral_usd) ≤ maxLeverage
13
+ *
14
+ * ## Field offsets (pinned to flash-sdk@15.x Perpetuals IDL)
15
+ *
16
+ * Derived from the Anchor IDL shipped with `flash-sdk@^15.14.1`
17
+ * (`node_modules/flash-sdk/dist/idl/perpetuals.json`). Position account
18
+ * Borsh layout, starting after the 8-byte Anchor discriminator:
19
+ *
20
+ * offset field type size
21
+ * 8 owner pubkey 32
22
+ * 40 market pubkey 32
23
+ * 72 delegate pubkey 32
24
+ * 104 open_time i64 8
25
+ * 112 update_time i64 8
26
+ * 120 entry_price OraclePrice { price: u64, exponent: i32 } 12
27
+ * 132 size_amount u64 8
28
+ * → 140 size_usd u64 8
29
+ * 148 locked_amount u64 8
30
+ * 156 locked_usd u64 8
31
+ * 164 price_impact_usd u64 8
32
+ * → 172 collateral_usd u64 8
33
+ * ...
34
+ *
35
+ * A drift-check unit test (`presets/flash-trade.test.ts`) reloads the Anchor
36
+ * IDL from `flash-sdk` at test time and recomputes offsets — any future
37
+ * flash-sdk bump that shifts these fields fails the test before a broken
38
+ * preset can ship.
39
+ *
40
+ * ## Jupiter Perps is NOT supported here
41
+ *
42
+ * Flash Trade executes position changes synchronously in the user's tx, so
43
+ * post-execution assertions are meaningful. Jupiter Perpetuals uses a 2-tx
44
+ * keeper-fulfillment model that silently bypasses post-assertions — that gate
45
+ * is enforced upstream in `leverageCapLteBps` via
46
+ * `JupiterPerpsPostAssertionUnsupportedError`, so a caller who mistakenly
47
+ * plugs a Jupiter Perps Position address here gets an explicit error.
48
+ *
49
+ * ## Bounds on `maxLeverage`
50
+ *
51
+ * `maxLeverage` is an integer multiplier (e.g., 5 = 5x cap). We reject
52
+ * values outside [1, 100]:
53
+ * - 0 would encode `size_usd ≤ 0` — any non-zero position fails, effectively
54
+ * a kill-switch. Safer to reject and let callers use `closePostAssertions`
55
+ * if they want to disable the cap entirely.
56
+ * - Values > 100 exceed any practical Flash Trade leverage (current mainnet
57
+ * caps sit around 25-50x) and are almost certainly caller bugs.
58
+ *
59
+ * @see programs/sigil/src/state/post_assertions.rs — on-chain CrossFieldLte enforcer
60
+ * @see `@usesigil/kit/post-assertions/cross-field-lte.ts` — underlying builder
61
+ */
62
+ import type { Address } from "@solana/kit";
63
+ import type { PostAssertionEntry } from "../../generated/types/postAssertionEntry.js";
64
+ /**
65
+ * Flash Trade Perpetuals program address (mainnet-beta). Owner of Position
66
+ * accounts that this preset targets.
67
+ *
68
+ * Source: `constants` module in `flash-sdk@^15.14.1`. Hard-coded here so the
69
+ * preset is importable without loading the full flash-sdk runtime.
70
+ */
71
+ export declare const FLASH_TRADE_PROGRAM_ADDRESS: Address;
72
+ /**
73
+ * Byte offset of `size_usd` (u64, little-endian) inside Flash Trade Position
74
+ * account data, starting from byte 0 of the account (NOT after discriminator).
75
+ *
76
+ * Pinned to flash-sdk@^15.14.1 Perpetuals IDL. A drift-check unit test
77
+ * reloads the IDL and asserts this value matches.
78
+ */
79
+ export declare const FLASH_TRADE_POSITION_SIZE_USD_OFFSET = 140;
80
+ /**
81
+ * Byte offset of `collateral_usd` (u64, little-endian) inside Flash Trade
82
+ * Position account data.
83
+ *
84
+ * Pinned to flash-sdk@^15.14.1 Perpetuals IDL. Drift-check test guards this.
85
+ */
86
+ export declare const FLASH_TRADE_POSITION_COLLATERAL_USD_OFFSET = 172;
87
+ /**
88
+ * Lowest permitted `maxLeverage` input — 1x. Zero would encode a kill-switch.
89
+ */
90
+ export declare const MIN_LEVERAGE_X = 1;
91
+ /**
92
+ * Highest permitted `maxLeverage` input. 100x is a generous upper bound above
93
+ * any practical Flash Trade cap.
94
+ */
95
+ export declare const MAX_LEVERAGE_X = 100;
96
+ /**
97
+ * Thrown when `maxLeverage` is outside [MIN_LEVERAGE_X, MAX_LEVERAGE_X] or
98
+ * not an integer. Carries a DxError-compatible shape so FE can branch on
99
+ * `.code` without `instanceof` checks that break across module realms.
100
+ */
101
+ export declare class FlashTradeLeverageOutOfRangeError extends Error {
102
+ /** DxError-compatible numeric code. 7009 reserved for preset validation. */
103
+ readonly code: number;
104
+ readonly recovery: readonly string[];
105
+ /**
106
+ * Always `false` — thrown at CLIENT validation time, before any RPC
107
+ * round-trip. Present to satisfy DxError's structural contract (every
108
+ * DxError carries `onChainReverted`; see v2.2 contract C2).
109
+ */
110
+ readonly onChainReverted: boolean;
111
+ readonly received: unknown;
112
+ constructor(received: unknown);
113
+ }
114
+ export interface FlashTradeLeverageCapOpts {
115
+ /** Base-58 pubkey of the Flash Trade Position account to monitor. */
116
+ readonly positionAccount: Address;
117
+ /**
118
+ * Maximum leverage in "x" units (e.g. 5 = 5x). Integer in [1, 100].
119
+ * The preset throws `FlashTradeLeverageOutOfRangeError` on anything else.
120
+ */
121
+ readonly maxLeverage: number;
122
+ }
123
+ /**
124
+ * Build a post-assertion entry that caps Flash Trade leverage at `maxLeverage` × .
125
+ *
126
+ * Equivalent to calling {@link leverageCapLteBps} with Flash Trade's Position
127
+ * `size_usd` / `collateral_usd` offsets filled in, `targetAccountOwnerProgram`
128
+ * set to {@link FLASH_TRADE_PROGRAM_ADDRESS}, and `maxBps = maxLeverage * 10000`.
129
+ *
130
+ * @throws {FlashTradeLeverageOutOfRangeError} if `maxLeverage` is not an
131
+ * integer in [1, 100].
132
+ * @throws {import("../cross-field-lte.js").JupiterPerpsPostAssertionUnsupportedError}
133
+ * re-thrown by the underlying builder if `targetAccountOwnerProgram` ever
134
+ * drifts to Jupiter Perps (defense-in-depth — Flash Trade's program address
135
+ * is hard-coded here, so this throw indicates either a preset bug or a
136
+ * caller who hand-mutated the returned entry before submitting).
137
+ */
138
+ export declare function flashTradeLeverageCap(opts: FlashTradeLeverageCapOpts): PostAssertionEntry;
139
+ //# sourceMappingURL=flash-trade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flash-trade.d.ts","sourceRoot":"","sources":["../../../src/post-assertions/presets/flash-trade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAKtF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EACY,OAAO,CAAC;AAE5D;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,MAAM,CAAC;AAExD;;;;;GAKG;AACH,eAAO,MAAM,0CAA0C,MAAM,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,cAAc,MAAM,CAAC;AAIlC;;;;GAIG;AACH,qBAAa,iCAAkC,SAAQ,KAAK;IAC1D,4EAA4E;IAC5E,SAAgB,IAAI,EAAE,MAAM,CAAQ;IACpC,SAAgB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAGzC;IACF;;;;OAIG;IACH,SAAgB,eAAe,EAAE,OAAO,CAAS;IACjD,SAAgB,QAAQ,EAAE,OAAO,CAAC;gBAEtB,QAAQ,EAAE,OAAO;CAQ9B;AAID,MAAM,WAAW,yBAAyB;IACxC,qEAAqE;IACrE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,yBAAyB,GAC9B,kBAAkB,CAkBpB"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * `@usesigil/kit/post-assertions/presets/flash-trade` — Flash Trade leverage cap preset.
3
+ *
4
+ * Convenience wrapper around `leverageCapLteBps` that fills in the byte offsets
5
+ * of a Flash Trade Position account's `size_usd` and `collateral_usd` fields.
6
+ *
7
+ * Callers provide a position account address + a leverage cap expressed in
8
+ * "x" (multiples), and the preset returns a `PostAssertionEntry` that the
9
+ * on-chain program enforces as:
10
+ *
11
+ * size_usd × 10000 ≤ maxLeverage × 10000 × collateral_usd
12
+ * ⇔ leverage (= size_usd / collateral_usd) ≤ maxLeverage
13
+ *
14
+ * ## Field offsets (pinned to flash-sdk@15.x Perpetuals IDL)
15
+ *
16
+ * Derived from the Anchor IDL shipped with `flash-sdk@^15.14.1`
17
+ * (`node_modules/flash-sdk/dist/idl/perpetuals.json`). Position account
18
+ * Borsh layout, starting after the 8-byte Anchor discriminator:
19
+ *
20
+ * offset field type size
21
+ * 8 owner pubkey 32
22
+ * 40 market pubkey 32
23
+ * 72 delegate pubkey 32
24
+ * 104 open_time i64 8
25
+ * 112 update_time i64 8
26
+ * 120 entry_price OraclePrice { price: u64, exponent: i32 } 12
27
+ * 132 size_amount u64 8
28
+ * → 140 size_usd u64 8
29
+ * 148 locked_amount u64 8
30
+ * 156 locked_usd u64 8
31
+ * 164 price_impact_usd u64 8
32
+ * → 172 collateral_usd u64 8
33
+ * ...
34
+ *
35
+ * A drift-check unit test (`presets/flash-trade.test.ts`) reloads the Anchor
36
+ * IDL from `flash-sdk` at test time and recomputes offsets — any future
37
+ * flash-sdk bump that shifts these fields fails the test before a broken
38
+ * preset can ship.
39
+ *
40
+ * ## Jupiter Perps is NOT supported here
41
+ *
42
+ * Flash Trade executes position changes synchronously in the user's tx, so
43
+ * post-execution assertions are meaningful. Jupiter Perpetuals uses a 2-tx
44
+ * keeper-fulfillment model that silently bypasses post-assertions — that gate
45
+ * is enforced upstream in `leverageCapLteBps` via
46
+ * `JupiterPerpsPostAssertionUnsupportedError`, so a caller who mistakenly
47
+ * plugs a Jupiter Perps Position address here gets an explicit error.
48
+ *
49
+ * ## Bounds on `maxLeverage`
50
+ *
51
+ * `maxLeverage` is an integer multiplier (e.g., 5 = 5x cap). We reject
52
+ * values outside [1, 100]:
53
+ * - 0 would encode `size_usd ≤ 0` — any non-zero position fails, effectively
54
+ * a kill-switch. Safer to reject and let callers use `closePostAssertions`
55
+ * if they want to disable the cap entirely.
56
+ * - Values > 100 exceed any practical Flash Trade leverage (current mainnet
57
+ * caps sit around 25-50x) and are almost certainly caller bugs.
58
+ *
59
+ * @see programs/sigil/src/state/post_assertions.rs — on-chain CrossFieldLte enforcer
60
+ * @see `@usesigil/kit/post-assertions/cross-field-lte.ts` — underlying builder
61
+ */
62
+ import { leverageCapLteBps } from "../cross-field-lte.js";
63
+ // ─── Constants ────────────────────────────────────────────────────────────
64
+ /**
65
+ * Flash Trade Perpetuals program address (mainnet-beta). Owner of Position
66
+ * accounts that this preset targets.
67
+ *
68
+ * Source: `constants` module in `flash-sdk@^15.14.1`. Hard-coded here so the
69
+ * preset is importable without loading the full flash-sdk runtime.
70
+ */
71
+ export const FLASH_TRADE_PROGRAM_ADDRESS = "FLaSh6f6Y5bLsmcfiaxvqRJC3WQLKYh1iCfAsh7uMH8z";
72
+ /**
73
+ * Byte offset of `size_usd` (u64, little-endian) inside Flash Trade Position
74
+ * account data, starting from byte 0 of the account (NOT after discriminator).
75
+ *
76
+ * Pinned to flash-sdk@^15.14.1 Perpetuals IDL. A drift-check unit test
77
+ * reloads the IDL and asserts this value matches.
78
+ */
79
+ export const FLASH_TRADE_POSITION_SIZE_USD_OFFSET = 140;
80
+ /**
81
+ * Byte offset of `collateral_usd` (u64, little-endian) inside Flash Trade
82
+ * Position account data.
83
+ *
84
+ * Pinned to flash-sdk@^15.14.1 Perpetuals IDL. Drift-check test guards this.
85
+ */
86
+ export const FLASH_TRADE_POSITION_COLLATERAL_USD_OFFSET = 172;
87
+ /**
88
+ * Lowest permitted `maxLeverage` input — 1x. Zero would encode a kill-switch.
89
+ */
90
+ export const MIN_LEVERAGE_X = 1;
91
+ /**
92
+ * Highest permitted `maxLeverage` input. 100x is a generous upper bound above
93
+ * any practical Flash Trade cap.
94
+ */
95
+ export const MAX_LEVERAGE_X = 100;
96
+ // ─── Errors ───────────────────────────────────────────────────────────────
97
+ /**
98
+ * Thrown when `maxLeverage` is outside [MIN_LEVERAGE_X, MAX_LEVERAGE_X] or
99
+ * not an integer. Carries a DxError-compatible shape so FE can branch on
100
+ * `.code` without `instanceof` checks that break across module realms.
101
+ */
102
+ export class FlashTradeLeverageOutOfRangeError extends Error {
103
+ /** DxError-compatible numeric code. 7009 reserved for preset validation. */
104
+ code = 7009;
105
+ recovery = [
106
+ `Pass a whole number between ${MIN_LEVERAGE_X} and ${MAX_LEVERAGE_X}.`,
107
+ "To disable an existing leverage cap, call `closePostAssertions(...)`.",
108
+ ];
109
+ /**
110
+ * Always `false` — thrown at CLIENT validation time, before any RPC
111
+ * round-trip. Present to satisfy DxError's structural contract (every
112
+ * DxError carries `onChainReverted`; see v2.2 contract C2).
113
+ */
114
+ onChainReverted = false;
115
+ received;
116
+ constructor(received) {
117
+ super(`flashTradeLeverageCap: maxLeverage must be an integer in [${MIN_LEVERAGE_X}, ${MAX_LEVERAGE_X}] (got ${String(received)})`);
118
+ this.name = "FlashTradeLeverageOutOfRangeError";
119
+ this.received = received;
120
+ // TS target=ES2020 preserves .name/.message across supers; no extra handling needed.
121
+ }
122
+ }
123
+ // ─── Builder ──────────────────────────────────────────────────────────────
124
+ /**
125
+ * Build a post-assertion entry that caps Flash Trade leverage at `maxLeverage` × .
126
+ *
127
+ * Equivalent to calling {@link leverageCapLteBps} with Flash Trade's Position
128
+ * `size_usd` / `collateral_usd` offsets filled in, `targetAccountOwnerProgram`
129
+ * set to {@link FLASH_TRADE_PROGRAM_ADDRESS}, and `maxBps = maxLeverage * 10000`.
130
+ *
131
+ * @throws {FlashTradeLeverageOutOfRangeError} if `maxLeverage` is not an
132
+ * integer in [1, 100].
133
+ * @throws {import("../cross-field-lte.js").JupiterPerpsPostAssertionUnsupportedError}
134
+ * re-thrown by the underlying builder if `targetAccountOwnerProgram` ever
135
+ * drifts to Jupiter Perps (defense-in-depth — Flash Trade's program address
136
+ * is hard-coded here, so this throw indicates either a preset bug or a
137
+ * caller who hand-mutated the returned entry before submitting).
138
+ */
139
+ export function flashTradeLeverageCap(opts) {
140
+ if (!Number.isInteger(opts.maxLeverage) ||
141
+ opts.maxLeverage < MIN_LEVERAGE_X ||
142
+ opts.maxLeverage > MAX_LEVERAGE_X) {
143
+ throw new FlashTradeLeverageOutOfRangeError(opts.maxLeverage);
144
+ }
145
+ const maxBps = opts.maxLeverage * 10_000;
146
+ return leverageCapLteBps({
147
+ targetAccount: opts.positionAccount,
148
+ targetAccountOwnerProgram: FLASH_TRADE_PROGRAM_ADDRESS,
149
+ fieldAOffset: FLASH_TRADE_POSITION_SIZE_USD_OFFSET,
150
+ fieldBOffset: FLASH_TRADE_POSITION_COLLATERAL_USD_OFFSET,
151
+ maxBps,
152
+ });
153
+ }
154
+ //# sourceMappingURL=flash-trade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flash-trade.js","sourceRoot":"","sources":["../../../src/post-assertions/presets/flash-trade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,6EAA6E;AAE7E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,2BAA2B,GACtC,8CAAyD,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0CAA0C,GAAG,GAAG,CAAC;AAE9D;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC,6EAA6E;AAE7E;;;;GAIG;AACH,MAAM,OAAO,iCAAkC,SAAQ,KAAK;IAC1D,4EAA4E;IAC5D,IAAI,GAAW,IAAI,CAAC;IACpB,QAAQ,GAAsB;QAC5C,+BAA+B,cAAc,QAAQ,cAAc,GAAG;QACtE,uEAAuE;KACxE,CAAC;IACF;;;;OAIG;IACa,eAAe,GAAY,KAAK,CAAC;IACjC,QAAQ,CAAU;IAElC,YAAY,QAAiB;QAC3B,KAAK,CACH,6DAA6D,cAAc,KAAK,cAAc,UAAU,MAAM,CAAC,QAAQ,CAAC,GAAG,CAC5H,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;QAChD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,qFAAqF;IACvF,CAAC;CACF;AAcD,6EAA6E;AAE7E;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAA+B;IAE/B,IACE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,cAAc;QACjC,IAAI,CAAC,WAAW,GAAG,cAAc,EACjC,CAAC;QACD,MAAM,IAAI,iCAAiC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;IAEzC,OAAO,iBAAiB,CAAC;QACvB,aAAa,EAAE,IAAI,CAAC,eAAe;QACnC,yBAAyB,EAAE,2BAA2B;QACtD,YAAY,EAAE,oCAAoC;QAClD,YAAY,EAAE,0CAA0C;QACxD,MAAM;KACP,CAAC,CAAC;AACL,CAAC"}