@crediolabs/policy-synth 0.1.18 → 0.3.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 (159) hide show
  1. package/README.md +6 -5
  2. package/dist/adapters/interpreter/adapter.d.ts +19 -25
  3. package/dist/adapters/interpreter/adapter.js +54 -487
  4. package/dist/adapters/interpreter/index.d.ts +1 -1
  5. package/dist/adapters/interpreter/index.js +1 -1
  6. package/dist/adapters/oz/adapter.js +1 -15
  7. package/dist/errors.d.ts +1 -1
  8. package/dist/index.d.ts +1 -4
  9. package/dist/index.js +1 -4
  10. package/dist/install/build-add-context-rule.d.ts +3 -11
  11. package/dist/install/build-add-context-rule.js +2 -97
  12. package/dist/install/build-install-policy.d.ts +4 -53
  13. package/dist/install/build-install-policy.js +44 -123
  14. package/dist/ir/index.d.ts +1 -1
  15. package/dist/ir/types.d.ts +7 -76
  16. package/dist/ir/types.js +0 -2
  17. package/dist/predicate/decode.d.ts +1 -1
  18. package/dist/predicate/decode.js +2 -70
  19. package/dist/predicate/encode.js +45 -229
  20. package/dist/predicate/from-json.js +1 -42
  21. package/dist/record/decode.js +3 -8
  22. package/dist/review-card/builder.d.ts +4 -3
  23. package/dist/review-card/builder.js +18 -162
  24. package/dist/review-card/cross-check.js +2 -105
  25. package/dist/review-card/render-leaf.d.ts +4 -0
  26. package/dist/review-card/render-leaf.js +47 -0
  27. package/dist/run/index.d.ts +35 -53
  28. package/dist/run/index.js +115 -156
  29. package/dist/run/schemas.d.ts +168 -1650
  30. package/dist/run/schemas.js +36 -199
  31. package/dist/seams/types.d.ts +0 -2
  32. package/dist/simulate/deny-cases.d.ts +26 -0
  33. package/dist/simulate/deny-cases.js +282 -0
  34. package/dist/simulate/evaluate.d.ts +18 -0
  35. package/dist/simulate/evaluate.js +271 -0
  36. package/dist/simulate/index.d.ts +4 -0
  37. package/dist/simulate/index.js +8 -0
  38. package/dist/synth/compose-from-recording.d.ts +24 -51
  39. package/dist/synth/compose-from-recording.js +120 -282
  40. package/dist/synth/deny-cases.d.ts +5 -7
  41. package/dist/synth/deny-cases.js +23 -373
  42. package/dist/synth/evaluate.d.ts +0 -21
  43. package/dist/synth/evaluate.js +56 -336
  44. package/dist/synth/index.d.ts +0 -5
  45. package/dist/synth/index.js +0 -5
  46. package/dist/synth/permit-context.d.ts +2 -9
  47. package/dist/synth/permit-context.js +1 -82
  48. package/dist/synth/synthesize-from-recording.d.ts +1 -29
  49. package/dist/synth/synthesize-from-recording.js +41 -356
  50. package/dist/types.d.ts +8 -60
  51. package/dist/types.js +5 -2
  52. package/dist/verify/simulate.d.ts +1 -14
  53. package/dist/verify/simulate.js +2 -88
  54. package/dist/verify/verify.d.ts +1 -7
  55. package/dist/verify/verify.js +0 -8
  56. package/dist-cjs/adapters/interpreter/adapter.d.ts +19 -25
  57. package/dist-cjs/adapters/interpreter/adapter.js +56 -489
  58. package/dist-cjs/adapters/interpreter/index.d.ts +1 -1
  59. package/dist-cjs/adapters/interpreter/index.js +1 -2
  60. package/dist-cjs/adapters/oz/adapter.js +1 -15
  61. package/dist-cjs/errors.d.ts +1 -1
  62. package/dist-cjs/index.d.ts +1 -4
  63. package/dist-cjs/index.js +1 -4
  64. package/dist-cjs/install/build-add-context-rule.d.ts +3 -11
  65. package/dist-cjs/install/build-add-context-rule.js +1 -96
  66. package/dist-cjs/install/build-install-policy.d.ts +4 -53
  67. package/dist-cjs/install/build-install-policy.js +44 -122
  68. package/dist-cjs/ir/index.d.ts +1 -1
  69. package/dist-cjs/ir/types.d.ts +7 -76
  70. package/dist-cjs/ir/types.js +0 -2
  71. package/dist-cjs/predicate/decode.d.ts +1 -1
  72. package/dist-cjs/predicate/decode.js +2 -70
  73. package/dist-cjs/predicate/encode.js +45 -229
  74. package/dist-cjs/predicate/from-json.js +1 -42
  75. package/dist-cjs/record/decode.js +3 -8
  76. package/dist-cjs/review-card/builder.d.ts +4 -3
  77. package/dist-cjs/review-card/builder.js +23 -167
  78. package/dist-cjs/review-card/cross-check.js +7 -110
  79. package/dist-cjs/review-card/render-leaf.d.ts +4 -0
  80. package/dist-cjs/review-card/render-leaf.js +52 -0
  81. package/dist-cjs/run/index.d.ts +35 -53
  82. package/dist-cjs/run/index.js +116 -162
  83. package/dist-cjs/run/schemas.d.ts +168 -1650
  84. package/dist-cjs/run/schemas.js +37 -200
  85. package/dist-cjs/seams/types.d.ts +0 -2
  86. package/dist-cjs/simulate/deny-cases.d.ts +26 -0
  87. package/dist-cjs/simulate/deny-cases.js +286 -0
  88. package/dist-cjs/simulate/evaluate.d.ts +18 -0
  89. package/dist-cjs/simulate/evaluate.js +274 -0
  90. package/dist-cjs/simulate/index.d.ts +4 -0
  91. package/dist-cjs/simulate/index.js +13 -0
  92. package/dist-cjs/synth/compose-from-recording.d.ts +24 -51
  93. package/dist-cjs/synth/compose-from-recording.js +120 -282
  94. package/dist-cjs/synth/deny-cases.d.ts +5 -7
  95. package/dist-cjs/synth/deny-cases.js +23 -374
  96. package/dist-cjs/synth/evaluate.d.ts +0 -21
  97. package/dist-cjs/synth/evaluate.js +57 -337
  98. package/dist-cjs/synth/index.d.ts +0 -5
  99. package/dist-cjs/synth/index.js +1 -11
  100. package/dist-cjs/synth/permit-context.d.ts +2 -9
  101. package/dist-cjs/synth/permit-context.js +1 -82
  102. package/dist-cjs/synth/synthesize-from-recording.d.ts +1 -29
  103. package/dist-cjs/synth/synthesize-from-recording.js +39 -354
  104. package/dist-cjs/types.d.ts +8 -60
  105. package/dist-cjs/types.js +6 -3
  106. package/dist-cjs/verify/simulate.d.ts +1 -14
  107. package/dist-cjs/verify/simulate.js +2 -88
  108. package/dist-cjs/verify/verify.d.ts +1 -7
  109. package/dist-cjs/verify/verify.js +0 -8
  110. package/package.json +4 -4
  111. package/src/adapters/interpreter/adapter.ts +76 -572
  112. package/src/errors.ts +0 -19
  113. package/src/index.ts +1 -4
  114. package/src/install/build-add-context-rule.ts +4 -127
  115. package/src/install/build-install-policy.ts +93 -214
  116. package/src/predicate/decode.ts +2 -70
  117. package/src/predicate/encode.ts +49 -261
  118. package/src/predicate/from-json.ts +1 -43
  119. package/src/record/decode.ts +3 -8
  120. package/src/review-card/builder.ts +19 -168
  121. package/src/review-card/cross-check.ts +3 -105
  122. package/src/review-card/render-leaf.ts +48 -0
  123. package/src/run/index.ts +130 -186
  124. package/src/run/schemas.ts +38 -214
  125. package/src/simulate/deny-cases.ts +334 -0
  126. package/src/simulate/evaluate.ts +284 -0
  127. package/src/simulate/index.ts +11 -0
  128. package/src/synth/compose-from-recording.ts +148 -347
  129. package/src/synth/index.ts +0 -13
  130. package/src/synth/synthesize-from-recording.ts +43 -456
  131. package/src/types.ts +13 -49
  132. package/dist/install/build-install-predicate.d.ts +0 -96
  133. package/dist/install/build-install-predicate.js +0 -444
  134. package/dist-cjs/install/build-install-predicate.d.ts +0 -96
  135. package/dist-cjs/install/build-install-predicate.js +0 -479
  136. package/src/adapters/interpreter/index.ts +0 -8
  137. package/src/adapters/oz/adapter.ts +0 -376
  138. package/src/adapters/oz/index.ts +0 -9
  139. package/src/codegen/compile-gate.ts +0 -167
  140. package/src/codegen/index.ts +0 -17
  141. package/src/codegen/template.ts +0 -165
  142. package/src/ir/index.ts +0 -13
  143. package/src/ir/types.ts +0 -132
  144. package/src/mandate/index.ts +0 -4
  145. package/src/mandate/to-ir.ts +0 -71
  146. package/src/mandate/types.ts +0 -21
  147. package/src/seams/index.ts +0 -11
  148. package/src/seams/types.ts +0 -81
  149. package/src/synth/deny-cases.ts +0 -663
  150. package/src/synth/evaluate.ts +0 -613
  151. package/src/synth/harness.ts +0 -68
  152. package/src/synth/minimize.ts +0 -48
  153. package/src/synth/permit-context.ts +0 -136
  154. package/src/synth/predicate-literals.ts +0 -27
  155. package/src/synth/synthesize-from-mandate.ts +0 -82
  156. package/src/verify/envelope.ts +0 -28
  157. package/src/verify/index.ts +0 -5
  158. package/src/verify/simulate.ts +0 -311
  159. package/src/verify/verify.ts +0 -243
@@ -7,7 +7,7 @@
7
7
  // expiry.validUntilLedger -> ContextRuleDraft.validUntilLedger
8
8
  // window_spent(t,w) <= L -> `spending_limit` primitive
9
9
  // approval.threshold -> `simple_threshold` / `weighted_threshold`
10
- // Anything needing a capability this backend lacks (oracle price, invocation
10
+ // Anything needing a capability this backend lacks (invocation
11
11
  // count, per-arg comparison/allowlist, guard, nested boolean predicate) is NOT
12
12
  // emitted: it is named in `uncovered` and `covered` is set false. Nothing is
13
13
  // silently dropped.
@@ -45,8 +45,6 @@ const CAPABILITIES = {
45
45
  supportsSpendWindow: true,
46
46
  supportsThreshold: true,
47
47
  supportsTimeExpiry: true,
48
- supportsOraclePrice: false,
49
- supportsInvocationCount: false,
50
48
  supportsGeneralPredicate: false,
51
49
  };
52
50
  function createOzAdapter(config) {
@@ -211,10 +209,6 @@ function matchSpendingLimit(c) {
211
209
  * cannot express, used to populate `uncovered`. */
212
210
  function describeCondition(cond) {
213
211
  switch (cond.op) {
214
- case 'slippage_floor':
215
- // OZ primitives bound a value against a constant; this bounds one call
216
- // argument against another, which none of them can express.
217
- return `slippage floor on arg[${cond.outArgIndex}] (OZ built-ins cannot bound one argument against another)`;
218
212
  case 'in':
219
213
  return `value allowlist on ${describeSelector(cond.selector)} (arg allowlist)`;
220
214
  case 'eq_seq':
@@ -227,10 +221,6 @@ function describeCondition(cond) {
227
221
  case 'compare': {
228
222
  const s = cond.compare.selector;
229
223
  switch (s.kind) {
230
- case 'oracle_price':
231
- return `oracle price condition on ${s.asset} (oracle price not supported in week-1)`;
232
- case 'invocation_count':
233
- return `invocation-count window (${s.windowSeconds}s) condition (not supported in week-1)`;
234
224
  case 'window_spent':
235
225
  return `spend-window comparison with operator '${cond.compare.operator}' (only 'lte' lowers to spending_limit)`;
236
226
  case 'amount':
@@ -264,10 +254,6 @@ function describeSelector(s) {
264
254
  return `amount(${s.token})`;
265
255
  case 'window_spent':
266
256
  return `window_spent(${s.token})`;
267
- case 'oracle_price':
268
- return `oracle_price(${s.asset})`;
269
- case 'invocation_count':
270
- return `invocation_count(${s.windowSeconds}s)`;
271
257
  case 'calldata':
272
258
  return `calldata[${s.offset}:${s.offset + s.length}]`;
273
259
  default:
@@ -1,4 +1,4 @@
1
- export type ErrorCode = 'RECORDING_FAILED' | 'RECORDING_VALIDATION_FAILED' | 'SCOPE_UNRESOLVED' | 'SYNTHESIS_ERROR' | 'MALFORMED_PREDICATE' | 'SIMULATION_ERROR' | 'VERIFICATION_FAILED' | 'DENY_CASE_FAILURE' | 'PERMIT_CASE_FAILED' | 'SUMMARY_DRIFT' | 'INSTALL_BUILD_FAILED' | 'INSTALL_CONFIRM_MISSING' | 'INSTALL_CONFIRM_EXPIRED' | 'REVOKE_BUILD_FAILED' | 'REVOKE_CONFIRM_MISSING' | 'USER_REJECTED_SIGN' | 'WALLET_TIMEOUT' | 'WALLET_UNAVAILABLE' | 'PREDICATE_TOO_LARGE' | 'PREDICATE_TOO_DEEP' | 'TOO_MANY_LEAVES' | 'IN_OPERAND_LIMIT' | 'PREDICATE_ORACLE_OVER_LIMIT' | 'POLICY_CAP_EXCEEDED' | 'WASM_TOO_LARGE' | 'MASTER_AUTH_REQUIRED' | 'NONCE_REPLAY' | 'VERSION_MISMATCH' | 'ARITHMETIC_OVERFLOW' | 'AMOUNT_OVERFLOW' | 'RULE_SIGNERS_CHANGED' | 'SCOPE_SELF_CALL' | 'ARG_MISMATCH' | 'CONTRACT_SCOPE' | 'UNSUPPORTED_NODE' | 'STATEFUL_BOUND' | 'NOT_IN_ALLOWLIST' | 'FREQUENCY' | 'SLIPPAGE_FLOOR' | 'ORACLE_STALE' | 'ORACLE_MISSING' | 'ORACLE_NO_CONFIRMATION' | 'ORACLE_DEVIATION_EXCEEDED' | 'ORACLE_MALFORMED_HISTORY' | 'ORACLE_FINGERPRINT_DRIFT' | 'ORACLE_PAUSED' | 'ORACLE_LEAF_INVALID_POSITION' | 'ORACLE_PARAMS_OUT_OF_RANGE' | 'ORACLE_DECIMALS_MISMATCH' | 'ORACLE_THRESHOLD_DECIMALS_OUT_OF_RANGE' | 'ORACLE_THRESHOLD_BASIS_REQUIRED' | 'COMPILE_OK' | 'COMPILE_GATE_FAILED';
1
+ export type ErrorCode = 'RECORDING_FAILED' | 'RECORDING_VALIDATION_FAILED' | 'SCOPE_UNRESOLVED' | 'SYNTHESIS_ERROR' | 'MALFORMED_PREDICATE' | 'SIMULATION_ERROR' | 'VERIFICATION_FAILED' | 'DENY_CASE_FAILURE' | 'PERMIT_CASE_FAILED' | 'SUMMARY_DRIFT' | 'INSTALL_BUILD_FAILED' | 'INSTALL_CONFIRM_MISSING' | 'INSTALL_CONFIRM_EXPIRED' | 'REVOKE_BUILD_FAILED' | 'REVOKE_CONFIRM_MISSING' | 'USER_REJECTED_SIGN' | 'WALLET_TIMEOUT' | 'WALLET_UNAVAILABLE' | 'PREDICATE_TOO_LARGE' | 'PREDICATE_TOO_DEEP' | 'TOO_MANY_LEAVES' | 'IN_OPERAND_LIMIT' | 'POLICY_CAP_EXCEEDED' | 'WASM_TOO_LARGE' | 'MASTER_AUTH_REQUIRED' | 'NONCE_REPLAY' | 'VERSION_MISMATCH' | 'ARITHMETIC_OVERFLOW' | 'AMOUNT_OVERFLOW' | 'RULE_SIGNERS_CHANGED' | 'SCOPE_SELF_CALL' | 'ARG_MISMATCH' | 'CONTRACT_SCOPE' | 'UNSUPPORTED_NODE' | 'STATEFUL_BOUND' | 'NOT_IN_ALLOWLIST' | 'COMPILE_OK' | 'COMPILE_GATE_FAILED';
2
2
  export interface ToolError {
3
3
  code: ErrorCode;
4
4
  message: string;
@@ -1,11 +1,8 @@
1
- export * from './adapters/oz/index.ts';
2
1
  export * from './errors.ts';
3
- export * from './ir/index.ts';
4
- export * from './mandate/index.ts';
5
2
  export * from './predicate/index.ts';
6
3
  export * from './record/index.ts';
7
4
  export * from './registry/index.ts';
8
5
  export * from './review-card/index.ts';
9
- export * from './seams/index.ts';
6
+ export * from './simulate/index.ts';
10
7
  export * from './synth/index.ts';
11
8
  export * from './types.ts';
package/dist-cjs/index.js CHANGED
@@ -14,14 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./adapters/oz/index.js"), exports);
18
17
  __exportStar(require("./errors.js"), exports);
19
- __exportStar(require("./ir/index.js"), exports);
20
- __exportStar(require("./mandate/index.js"), exports);
21
18
  __exportStar(require("./predicate/index.js"), exports);
22
19
  __exportStar(require("./record/index.js"), exports);
23
20
  __exportStar(require("./registry/index.js"), exports);
24
21
  __exportStar(require("./review-card/index.js"), exports);
25
- __exportStar(require("./seams/index.js"), exports);
22
+ __exportStar(require("./simulate/index.js"), exports);
26
23
  __exportStar(require("./synth/index.js"), exports);
27
24
  __exportStar(require("./types.js"), exports);
@@ -8,8 +8,8 @@ export interface BuildAddContextRuleArgs {
8
8
  * admin session. The deployer signs the install call via the admin rule
9
9
  * already on the account, which is separate from this list. */
10
10
  signers: SignerDraft[];
11
- /** The policy(ies) to attach to the new rule. Only `interpreter` refs
12
- * reach the wire today; `oz_builtin` is reserved for Phase 06 follow-ups. */
11
+ /** The policy(ies) to attach to the new rule. `interpreter` is the only
12
+ * kind: the OpenZeppelin built-in backend was removed. */
13
13
  policies: PolicyRef[];
14
14
  /** Per-policy install nonce; 1 for a fresh install. */
15
15
  installNonce: number;
@@ -19,19 +19,11 @@ export interface BuildAddContextRuleArgs {
19
19
  encodedPredicate: string;
20
20
  /** Hex sha256 of the canonical predicate XDR bytes. */
21
21
  predicateHash: string;
22
- /** Per-policy oracle overrides. Absent on any key uses the wasm default. */
23
- oracleParams?: {
24
- maxStalenessSeconds?: number;
25
- maxDeviationBps?: number;
26
- /** Bound between the primary and secondary feeds. Tighten-only against
27
- * the wasm default, like the other two. */
28
- maxCrossFeedDeviationBps?: number;
29
- };
30
22
  /** Hard pin to the interpreter's wasm grammar. Refusing here fails closed
31
23
  * before the chain does; the contract will refuse a mismatch again. */
32
24
  grammarVersion?: number;
33
25
  }
34
- export declare const DEFAULT_GRAMMAR_VERSION: 1;
26
+ export declare const DEFAULT_GRAMMAR_VERSION: 3;
35
27
  /** The verb `add_context_rule` takes on the wire. */
36
28
  export declare const ADD_CONTEXT_RULE_SYMBOL: "add_context_rule";
37
29
  /** Tuple of `ScVal` arguments to pass to `Operation.invokeHostFunction` for
@@ -53,7 +53,7 @@ exports.buildAddContextRuleArgs = buildAddContextRuleArgs;
53
53
  const node_crypto_1 = require("node:crypto");
54
54
  const stellar_sdk_1 = require("@stellar/stellar-sdk");
55
55
  const types_ts_1 = require("../types.js");
56
- exports.DEFAULT_GRAMMAR_VERSION = 1;
56
+ exports.DEFAULT_GRAMMAR_VERSION = types_ts_1.GRAMMAR_VERSION;
57
57
  /** The verb `add_context_rule` takes on the wire. */
58
58
  exports.ADD_CONTEXT_RULE_SYMBOL = 'add_context_rule';
59
59
  /** Build the `add_context_rule` invocation args. Throws a `ToolError`-shaped
@@ -69,15 +69,6 @@ function buildAddContextRuleArgs(draft, args) {
69
69
  if (args.signers.length === 0 && args.policies.length === 0) {
70
70
  throw limitError('INSTALL_BUILD_FAILED', 'a rule with no signers and no policies is refused at install (NoSignersAndPolicies)');
71
71
  }
72
- // OZ's spending_limit caps spend on the CONTEXT CONTRACT - it takes no
73
- // token argument - so it refuses a Default rule on chain with a bare
74
- // #3227. Say which rule shape it needs here, before the encoding, rather
75
- // than letting the user read a numeric trap.
76
- if (args.policies.some((p) => p.kind === 'oz_builtin' && p.primitive.primitive === 'spending_limit')) {
77
- if (draft.contextRuleType.kind !== 'call_contract') {
78
- throw limitError('INSTALL_BUILD_FAILED', `spending_limit caps spend on the rule's context contract, so the rule must be call_contract-scoped to that token - a "${draft.contextRuleType.kind}" rule is refused on chain (#3227)`);
79
- }
80
- }
81
72
  // ---- 2. context_type encoding ----
82
73
  const contextType = encodeContextRuleType(draft.contextRuleType);
83
74
  // ---- 3. name (string) + valid_until (Option<u32>) ----
@@ -99,15 +90,6 @@ const POLICY_INSTALL_PARAM_FIELDS = [
99
90
  'install_nonce',
100
91
  'predicate',
101
92
  'predicate_hash',
102
- 'oracle_max_staleness_seconds',
103
- 'oracle_max_deviation_bps',
104
- // Cross-feed divergence bound. A field added to the contract's
105
- // `PolicyInstallParams` changes the ABI: the host unpacks the map by field
106
- // count, so omitting one fails the entire install with
107
- // `Error(Object, UnexpectedSize)` and no indication of which field is
108
- // missing. The Rust tests build that struct in Rust and never cross this
109
- // boundary, so only a real install against a deployed contract catches it.
110
- 'oracle_max_xfeed_dev_bps',
111
93
  ];
112
94
  function encodeContextRuleType(rule) {
113
95
  switch (rule.kind) {
@@ -149,75 +131,10 @@ function encodePoliciesMap(args) {
149
131
  val: encodePolicyInstallParams(args),
150
132
  }));
151
133
  }
152
- else if (ref.kind === 'oz_builtin') {
153
- entries.push(new stellar_sdk_1.xdr.ScMapEntry({
154
- key: stellar_sdk_1.Address.fromString(ref.instanceAddress).toScVal(),
155
- val: encodeOzPrimitiveParams(ref.primitive),
156
- }));
157
- }
158
134
  }
159
135
  entries.sort(sortByScValSymbolString);
160
136
  return stellar_sdk_1.xdr.ScVal.scvMap(entries);
161
137
  }
162
- /** Encode the install params for one OZ built-in policy.
163
- *
164
- * Field names and types are read from the deployed contracts' own spec:
165
- * SpendingLimitAccountParams { period_ledgers: u32, spending_limit: i128 }
166
- * SimpleThresholdAccountParams { threshold: u32 }
167
- * WeightedThresholdAccountParams { signer_weights: map, threshold: u32 }
168
- * Entries are symbol-string ordered for the same reason the interpreter's
169
- * are: the host orders by symbol, not by XDR bytes.
170
- */
171
- function encodeOzPrimitiveParams(primitive) {
172
- const entries = [];
173
- const push = (name, val) => entries.push(new stellar_sdk_1.xdr.ScMapEntry({ key: stellar_sdk_1.xdr.ScVal.scvSymbol(name), val }));
174
- const p = primitive.params;
175
- switch (primitive.primitive) {
176
- case 'spending_limit': {
177
- const limit = p.spending_limit;
178
- const period = p.period_ledgers;
179
- if (typeof limit !== 'string' || typeof period !== 'number') {
180
- throw limitError('INSTALL_BUILD_FAILED', 'spending_limit needs { spending_limit: string; period_ledgers: number }');
181
- }
182
- push('period_ledgers', stellar_sdk_1.xdr.ScVal.scvU32(period));
183
- push('spending_limit', encodeI128(limit));
184
- break;
185
- }
186
- case 'simple_threshold': {
187
- const threshold = p.threshold;
188
- if (typeof threshold !== 'number') {
189
- throw limitError('INSTALL_BUILD_FAILED', 'simple_threshold needs { threshold: number }');
190
- }
191
- push('threshold', stellar_sdk_1.xdr.ScVal.scvU32(threshold));
192
- break;
193
- }
194
- case 'weighted_threshold': {
195
- const threshold = p.threshold;
196
- const weights = p.weights;
197
- if (typeof threshold !== 'number' || !weights) {
198
- throw limitError('INSTALL_BUILD_FAILED', 'weighted_threshold needs { threshold: number; weights: Record<address, number> }');
199
- }
200
- const weightEntries = Object.entries(weights)
201
- .map(([addr, w]) => new stellar_sdk_1.xdr.ScMapEntry({
202
- key: stellar_sdk_1.Address.fromString(addr).toScVal(),
203
- val: stellar_sdk_1.xdr.ScVal.scvU32(w),
204
- }))
205
- .sort((a, b) => (a.key().toXDR('base64') < b.key().toXDR('base64') ? -1 : 1));
206
- push('signer_weights', stellar_sdk_1.xdr.ScVal.scvMap(weightEntries));
207
- push('threshold', stellar_sdk_1.xdr.ScVal.scvU32(threshold));
208
- break;
209
- }
210
- }
211
- entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
212
- return stellar_sdk_1.xdr.ScVal.scvMap(entries);
213
- }
214
- function encodeI128(value) {
215
- const v = BigInt(value);
216
- return stellar_sdk_1.xdr.ScVal.scvI128(new stellar_sdk_1.xdr.Int128Parts({
217
- hi: new stellar_sdk_1.xdr.Int64(BigInt.asIntN(64, v >> 64n)),
218
- lo: new stellar_sdk_1.xdr.Uint64(BigInt.asUintN(64, v)),
219
- }));
220
- }
221
138
  function encodePolicyInstallParams(args) {
222
139
  const predicate = Buffer.from(args.encodedPredicate, 'base64');
223
140
  const computedHash = (0, node_crypto_1.createHash)('sha256').update(predicate).digest('hex');
@@ -227,15 +144,11 @@ function encodePolicyInstallParams(args) {
227
144
  // Per-field value encoders. Each entry returns the ScVal to drop into the
228
145
  // map; the key symbol comes from the surrounding loop. Adding a field is
229
146
  // one row here plus the symbol in POLICY_INSTALL_PARAM_FIELDS.
230
- const oracleParams = args.oracleParams;
231
147
  const valueFor = {
232
148
  grammar_version: () => stellar_sdk_1.xdr.ScVal.scvU32(args.grammarVersion ?? exports.DEFAULT_GRAMMAR_VERSION),
233
149
  install_nonce: () => stellar_sdk_1.xdr.ScVal.scvU32(args.installNonce),
234
150
  predicate: () => stellar_sdk_1.xdr.ScVal.scvBytes(predicate),
235
151
  predicate_hash: () => stellar_sdk_1.xdr.ScVal.scvBytes(Buffer.from(args.predicateHash, 'hex')),
236
- oracle_max_staleness_seconds: () => encodeOptionU32(oracleParams?.maxStalenessSeconds),
237
- oracle_max_deviation_bps: () => encodeOptionU32(oracleParams?.maxDeviationBps),
238
- oracle_max_xfeed_dev_bps: () => encodeOptionU32(oracleParams?.maxCrossFeedDeviationBps),
239
152
  };
240
153
  const entries = POLICY_INSTALL_PARAM_FIELDS.map((k) => new stellar_sdk_1.xdr.ScMapEntry({ key: stellar_sdk_1.xdr.ScVal.scvSymbol(k), val: valueFor[k]() }));
241
154
  // The host orders map entries by the SYMBOL STRING, not by XDR bytes. A
@@ -245,14 +158,6 @@ function encodePolicyInstallParams(args) {
245
158
  entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
246
159
  return stellar_sdk_1.xdr.ScVal.scvMap(entries);
247
160
  }
248
- function encodeOptionU32(v) {
249
- if (v === undefined)
250
- return stellar_sdk_1.xdr.ScVal.scvVoid();
251
- if (!Number.isFinite(v) || v < 0 || v > 0xffffffff) {
252
- throw limitError('INSTALL_BUILD_FAILED', `oracle params value ${v} is outside u32 range`);
253
- }
254
- return stellar_sdk_1.xdr.ScVal.scvU32(v);
255
- }
256
161
  /** Sort host-map keys by their symbol-string form. The host orders map
257
162
  * entries by the SYMBOL STRING, not by the key's XDR bytes (a length
258
163
  * prefix in the encoding would otherwise put `amount` before `address`).
@@ -1,5 +1,5 @@
1
- import { Contract, rpc, type Transaction } from '@stellar/stellar-sdk';
2
- import { DEFAULT_GRAMMAR_VERSION } from './build-add-context-rule.ts';
1
+ import { rpc, type Transaction } from '@stellar/stellar-sdk';
2
+ import type { ContextRuleDraft } from '../types.ts';
3
3
  /** Minimal Soroban RPC surface the install pipeline needs. Test seams
4
4
  * inject a stub so the builder stays deterministic; production builds
5
5
  * the real one via `createRpcServer` from `../record/rpc.ts`. */
@@ -31,20 +31,14 @@ export interface BuildInstallPolicyArgs {
31
31
  sourceAccount: string;
32
32
  /** Network passphrase - pins the hash the auth digest binds. */
33
33
  networkPassphrase: string;
34
- /** The new rule to install. Mirrors the core `ContextRuleDraft`. */
35
- rule: BuildInstallPolicyRuleDraft;
34
+ /** The new rule to install. */
35
+ rule: ContextRuleDraft;
36
36
  /** Per-rule install nonce; 1 for a fresh install. */
37
37
  installNonce: number;
38
38
  /** Already-encoded (base64) canonical ScVal of the predicate. */
39
39
  encodedPredicate: string;
40
40
  /** Hex sha256 of the canonical predicate XDR bytes. */
41
41
  predicateHash: string;
42
- /** Per-policy oracle overrides. */
43
- oracleParams?: {
44
- maxStalenessSeconds?: number;
45
- maxDeviationBps?: number;
46
- maxCrossFeedDeviationBps?: number;
47
- };
48
42
  /** Grammar version override; defaults to 1. */
49
43
  grammarVersion?: number;
50
44
  /** Base fee in stroops; defaults to BASE_FEE (100). */
@@ -54,41 +48,6 @@ export interface BuildInstallPolicyArgs {
54
48
  /** Ledger window (in ledgers) for the auth entry's `validUntil`. */
55
49
  authValidUntilLedgers?: number;
56
50
  }
57
- export type BuildInstallPolicyRuleDraft = {
58
- contextRuleType: {
59
- kind: 'default';
60
- } | {
61
- kind: 'call_contract';
62
- contract: string;
63
- } | {
64
- kind: 'create_contract';
65
- wasmHash: string;
66
- };
67
- name: string;
68
- validUntilLedger: number | null;
69
- signers: BuildInstallPolicySignerDraft[];
70
- policies: BuildInstallPolicyPolicyRef[];
71
- };
72
- export type BuildInstallPolicySignerDraft = {
73
- kind: 'delegated';
74
- address: string;
75
- } | {
76
- kind: 'external';
77
- verifier: string;
78
- keyBytes: string;
79
- };
80
- export type BuildInstallPolicyPolicyRef = {
81
- kind: 'interpreter';
82
- interpreterAddress: string;
83
- predicateBlobBase64: string;
84
- } | {
85
- kind: 'oz_builtin';
86
- instanceAddress: string;
87
- primitive: {
88
- primitive: 'spending_limit' | 'simple_threshold' | 'weighted_threshold';
89
- params: Record<string, unknown>;
90
- };
91
- };
92
51
  /** Human-readable description of the install call, decoded FROM the built
93
52
  * XDR (not from the input args). The XDR is the source of truth: a
94
53
  * human approving a review card needs the description to mirror the bytes
@@ -134,10 +93,6 @@ export interface InstallCallDescribes {
134
93
  installNonce: number;
135
94
  predicateHash: string;
136
95
  predicateSha256OfEmbeddedBytes: string;
137
- } | {
138
- kind: 'oz_builtin';
139
- address: string;
140
- primitive: 'spending_limit' | 'simple_threshold' | 'weighted_threshold';
141
96
  }>;
142
97
  /** The install nonce, decoded from the interpreter policy's
143
98
  * `install_nonce` field. Echoed at the top level for reviewer convenience;
@@ -217,7 +172,3 @@ export interface BuildRevokePolicyResult {
217
172
  authValidUntilLedger: number;
218
173
  rootInvocationXdr: string;
219
174
  }
220
- /** Re-export so the run-layer does not need to import from
221
- * build-add-context-rule.ts (keeps the install/ -> install/ dependency
222
- * direction intact). */
223
- export { Contract, DEFAULT_GRAMMAR_VERSION };
@@ -18,15 +18,12 @@
18
18
  // forwards each install_param to that policy, so the interpreter stores the
19
19
  // predicate document as part of this same transaction.
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.DEFAULT_GRAMMAR_VERSION = exports.Contract = void 0;
22
21
  exports.rpcClientFromServer = rpcClientFromServer;
23
22
  exports.buildInstallPolicyXdr = buildInstallPolicyXdr;
24
23
  exports.buildRevokePolicyXdr = buildRevokePolicyXdr;
25
24
  const node_crypto_1 = require("node:crypto");
26
25
  const stellar_sdk_1 = require("@stellar/stellar-sdk");
27
- Object.defineProperty(exports, "Contract", { enumerable: true, get: function () { return stellar_sdk_1.Contract; } });
28
26
  const build_add_context_rule_ts_1 = require("./build-add-context-rule.js");
29
- Object.defineProperty(exports, "DEFAULT_GRAMMAR_VERSION", { enumerable: true, get: function () { return build_add_context_rule_ts_1.DEFAULT_GRAMMAR_VERSION; } });
30
27
  const oz_auth_ts_1 = require("./oz-auth.js");
31
28
  /** Convert a real rpc.Server into the InstallRpcClient surface. The
32
29
  * `getContractVersion` lookup uses `simulateTransaction` against
@@ -47,7 +44,7 @@ function rpcClientFromServer(server, networkPassphrase) {
47
44
  // random key does NOT exist on chain - asking the network for it returns
48
45
  // 404 and the version probe fails for a reason that has nothing to do
49
46
  // with the contract being probed.
50
- const account = new stellar_sdk_2.Account(stellar_sdk_1.Keypair.random().publicKey(), '0');
47
+ const account = new stellar_sdk_1.Account(stellar_sdk_1.Keypair.random().publicKey(), '0');
51
48
  const tx = new stellar_sdk_1.TransactionBuilder(account, {
52
49
  fee: stellar_sdk_1.BASE_FEE,
53
50
  networkPassphrase,
@@ -80,73 +77,21 @@ async function buildInstallPolicyXdr(args) {
80
77
  name: args.rule.name,
81
78
  validUntilLedger: args.rule.validUntilLedger,
82
79
  signers: args.rule.signers,
83
- policies: args.rule.policies.map(adaptPolicyRef),
80
+ policies: args.rule.policies,
84
81
  }, {
85
82
  signers: args.rule.signers,
86
- policies: args.rule.policies.map(adaptPolicyRef),
83
+ policies: args.rule.policies,
87
84
  installNonce: args.installNonce,
88
85
  encodedPredicate: args.encodedPredicate,
89
86
  predicateHash: args.predicateHash,
90
- ...(args.oracleParams ? { oracleParams: args.oracleParams } : {}),
91
87
  ...(args.grammarVersion !== undefined ? { grammarVersion: args.grammarVersion } : {}),
92
88
  });
93
- // 2. Fetch the source sequence, then build the recording transaction with a
94
- // bare host call. The recording pass assigns the smart-account auth nonce
95
- // and root invocation needed to construct OZ's AuthPayload.
96
- const source = await args.rpc.getAccount(args.sourceAccount);
97
- const hostFunction = stellar_sdk_1.xdr.HostFunction.hostFunctionTypeInvokeContract(new stellar_sdk_1.xdr.InvokeContractArgs({
98
- contractAddress: new stellar_sdk_1.Address(args.smartAccount).toScAddress(),
99
- functionName: 'add_context_rule',
100
- args: [...callArgs],
101
- }));
102
- const makeOperation = (auth = []) => stellar_sdk_1.Operation.invokeHostFunction({ func: hostFunction, auth });
103
- const baseFee = args.baseFee !== undefined ? String(args.baseFee) : stellar_sdk_1.BASE_FEE;
104
- const buildTx = (op) => buildUnsignedTx({
105
- sourceAccount: args.sourceAccount,
106
- sequence: source.sequenceNumber(),
107
- fee: baseFee,
108
- networkPassphrase: args.networkPassphrase,
109
- op,
110
- });
111
- const recordingTx = buildTx(makeOperation());
112
- // 3. Recording simulation: capture the smart account's nonce and invocation
113
- // tree. Nothing is signed here.
114
- const recorded = await args.rpc.simulateTransaction(recordingTx);
115
- if (stellar_sdk_1.rpc.Api.isSimulationError(recorded)) {
116
- // Short, stable reason. The full `simulateTransaction` error (which
117
- // carries host + URL detail) stays in the SDK's own logs - never
118
- // reflected back into a user-facing message where it would
119
- // reconnoitre the RPC.
120
- throw new Error('install_policy: simulateTransaction failed');
121
- }
122
- const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
123
- stellar_sdk_1.Address.fromScAddress(entry.credentials().address().address()).toString() ===
124
- args.smartAccount);
125
- if (!original) {
126
- throw new Error(`install_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
127
- }
128
- // 4. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
89
+ // 2. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
129
90
  // The delegated signer uses source-account credentials, so its signature
130
91
  // bytes stay empty and the ordinary transaction-envelope signature covers
131
92
  // the call when the consumer signs it.
132
- const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
133
- (args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
134
- const contextRuleIds = [0];
135
- const digest = (0, oz_auth_ts_1.authDigest)((0, oz_auth_ts_1.signaturePayload)(args.networkPassphrase, original.credentials().address().nonce(), validUntilLedger, original.rootInvocation()), contextRuleIds);
136
- const authEntries = [
137
- (0, oz_auth_ts_1.accountEntry)(original, validUntilLedger, (0, oz_auth_ts_1.authPayload)([args.sourceAccount], contextRuleIds, () => Buffer.alloc(0))),
138
- ...contextRuleIds.map(() => (0, oz_auth_ts_1.delegatedSignerEntry)(args.smartAccount, digest)),
139
- ];
140
- // 5. Simulate again with the OZ entries already attached. The SDK preserves
141
- // existing auth during assembly and adds the simulated Soroban footprint +
142
- // resource fee, yielding a complete unsigned envelope.
143
- const txWithAuth = buildTx(makeOperation(authEntries));
144
- const enforcing = await args.rpc.simulateTransaction(txWithAuth);
145
- if (stellar_sdk_1.rpc.Api.isSimulationError(enforcing)) {
146
- throw new Error('install_policy: auth simulateTransaction failed');
147
- }
148
- const finalTx = stellar_sdk_1.rpc.assembleTransaction(txWithAuth, enforcing).build();
149
- // 6. Decode the structured description FROM the final assembled transaction.
93
+ const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'add_context_rule', [...callArgs], 'install_policy');
94
+ // 3. Decode the structured description FROM the final assembled transaction.
150
95
  // The human approval binds to the exact bytes the wallet will sign.
151
96
  const describes = decodeInstallCallDescribes(finalTx, args.installNonce);
152
97
  return {
@@ -172,11 +117,39 @@ async function buildInstallPolicyXdr(args) {
172
117
  * deployer can revoke. This builder does not pre-check the signer: it would
173
118
  * be guessing at a contract it cannot read, and the chain is the authority. */
174
119
  async function buildRevokePolicyXdr(args) {
120
+ // Removal is master-only, so the deploy-time admin rule authorises it. The
121
+ // recorded rootInvocation still includes remove_context_rule(ruleId), binding
122
+ // the auth payload to the exact rule being removed. As with install,
123
+ // source-account credentials carry the delegated signer entry and the
124
+ // consumer supplies only the ordinary envelope signature.
125
+ const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'remove_context_rule', [stellar_sdk_1.xdr.ScVal.scvU32(args.ruleId)], 'revoke_policy');
126
+ return {
127
+ unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
128
+ smartAccount: args.smartAccount,
129
+ sourceAccount: args.sourceAccount,
130
+ call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
131
+ authNonce: original.credentials().address().nonce().toString(),
132
+ authValidUntilLedger: validUntilLedger,
133
+ rootInvocationXdr: original.rootInvocation().toXDR().toString('base64'),
134
+ };
135
+ }
136
+ /** ~25 minutes at 5s/ledger. */
137
+ const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
138
+ // ---- internals ----
139
+ /** Record a bare call to the smart account, attach the deploy-time admin rule's
140
+ * auth entries, and re-simulate to assemble the footprint.
141
+ *
142
+ * Install and revoke differ only in the call they wrap, so they share this
143
+ * spine: the recording pass supplies the auth nonce and root invocation OZ's
144
+ * AuthPayload binds to, and the second simulation adds the Soroban footprint +
145
+ * resource fee. Nothing here is signed. `errorPrefix` names the calling tool in
146
+ * the fail-closed messages so a caller can still tell which call failed. */
147
+ async function buildAuthorisedSmartAccountTx(args, functionName, callArgs, errorPrefix) {
175
148
  const source = await args.rpc.getAccount(args.sourceAccount);
176
149
  const hostFunction = stellar_sdk_1.xdr.HostFunction.hostFunctionTypeInvokeContract(new stellar_sdk_1.xdr.InvokeContractArgs({
177
150
  contractAddress: new stellar_sdk_1.Address(args.smartAccount).toScAddress(),
178
- functionName: 'remove_context_rule',
179
- args: [stellar_sdk_1.xdr.ScVal.scvU32(args.ruleId)],
151
+ functionName,
152
+ args: callArgs,
180
153
  }));
181
154
  const makeOperation = (auth = []) => stellar_sdk_1.Operation.invokeHostFunction({ func: hostFunction, auth });
182
155
  const baseFee = args.baseFee !== undefined ? String(args.baseFee) : stellar_sdk_1.BASE_FEE;
@@ -193,19 +166,14 @@ async function buildRevokePolicyXdr(args) {
193
166
  // carries host + URL detail) stays in the SDK's own logs - never
194
167
  // reflected back into a user-facing message where it would
195
168
  // reconnoitre the RPC.
196
- throw new Error('revoke_policy: simulateTransaction failed');
169
+ throw new Error(`${errorPrefix}: simulateTransaction failed`);
197
170
  }
198
171
  const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
199
172
  stellar_sdk_1.Address.fromScAddress(entry.credentials().address().address()).toString() ===
200
173
  args.smartAccount);
201
174
  if (!original) {
202
- throw new Error(`revoke_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
175
+ throw new Error(`${errorPrefix}: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
203
176
  }
204
- // Removal is master-only, so the deploy-time admin rule authorises it. The
205
- // recorded rootInvocation still includes remove_context_rule(ruleId), binding
206
- // the auth payload to the exact rule being removed. As with install,
207
- // source-account credentials carry the delegated signer entry and the
208
- // consumer supplies only the ordinary envelope signature.
209
177
  const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
210
178
  (args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
211
179
  const contextRuleIds = [0];
@@ -217,38 +185,12 @@ async function buildRevokePolicyXdr(args) {
217
185
  const txWithAuth = buildTx(makeOperation(authEntries));
218
186
  const enforcing = await args.rpc.simulateTransaction(txWithAuth);
219
187
  if (stellar_sdk_1.rpc.Api.isSimulationError(enforcing)) {
220
- throw new Error('revoke_policy: auth simulateTransaction failed');
221
- }
222
- const finalTx = stellar_sdk_1.rpc.assembleTransaction(txWithAuth, enforcing).build();
223
- return {
224
- unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
225
- smartAccount: args.smartAccount,
226
- sourceAccount: args.sourceAccount,
227
- call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
228
- authNonce: original.credentials().address().nonce().toString(),
229
- authValidUntilLedger: validUntilLedger,
230
- rootInvocationXdr: original.rootInvocation().toXDR().toString('base64'),
231
- };
232
- }
233
- /** ~25 minutes at 5s/ledger. */
234
- const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
235
- // ---- internals ----
236
- /** Adapter: turn the install-policy wire `PolicyRef` shape into the core
237
- * `PolicyRef` shape `buildAddContextRuleArgs` expects. Keeps the wire
238
- * schema hand-rolled + flat (the strict union would need a recursive
239
- * schema) while delegating to the proven encoder for the actual bytes. */
240
- function adaptPolicyRef(p) {
241
- if (p.kind === 'interpreter') {
242
- return {
243
- kind: 'interpreter',
244
- interpreterAddress: p.interpreterAddress,
245
- predicateBlobBase64: p.predicateBlobBase64,
246
- };
188
+ throw new Error(`${errorPrefix}: auth simulateTransaction failed`);
247
189
  }
248
190
  return {
249
- kind: 'oz_builtin',
250
- instanceAddress: p.instanceAddress,
251
- primitive: p.primitive,
191
+ finalTx: stellar_sdk_1.rpc.assembleTransaction(txWithAuth, enforcing).build(),
192
+ original,
193
+ validUntilLedger,
252
194
  };
253
195
  }
254
196
  /** Build an unsigned Soroban transaction envelope. The `sequence` is
@@ -256,7 +198,7 @@ function adaptPolicyRef(p) {
256
198
  * the SDK accepts). No signing. The returned Transaction is what
257
199
  * `simulateTransaction` accepts. */
258
200
  function buildUnsignedTx(args) {
259
- const account = new stellar_sdk_2.Account(args.sourceAccount, args.sequence);
201
+ const account = new stellar_sdk_1.Account(args.sourceAccount, args.sequence);
260
202
  const tx = new stellar_sdk_1.TransactionBuilder(account, {
261
203
  fee: args.fee,
262
204
  networkPassphrase: args.networkPassphrase,
@@ -302,14 +244,13 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
302
244
  if (scvArgs.length !== 5) {
303
245
  throw new Error(`install_policy: built op has ${scvArgs.length} args, expected 5 (context_type, name, valid_until, signers, policies)`);
304
246
  }
305
- const contextType = scvArgs[0];
306
247
  const nameScv = scvArgs[1];
307
248
  const validUntilScv = scvArgs[2];
308
249
  const signersScv = scvArgs[3];
309
250
  const policiesScv = scvArgs[4];
310
251
  // The length check above pins these as defined; the local references
311
252
  // satisfy noUncheckedIndexedAccess on the accessors below.
312
- if (!nameScv || !validUntilScv || !signersScv || !policiesScv || !contextType) {
253
+ if (!nameScv || !validUntilScv || !signersScv || !policiesScv) {
313
254
  throw new Error('install_policy: built op args include an undefined slot despite length check');
314
255
  }
315
256
  // name
@@ -390,7 +331,6 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
390
331
  fields.set(fk.sym().toString(), inner.val());
391
332
  }
392
333
  // Interpreter policy fields carry grammar_version/install_nonce/predicate.
393
- // OZ primitives carry spending_limit/period_ledgers/threshold/signers.
394
334
  if (fields.has('predicate') || fields.has('grammar_version') || fields.has('install_nonce')) {
395
335
  const installNonceScv = fields.get('install_nonce');
396
336
  if (installNonceScv?.switch().name !== 'scvU32') {
@@ -419,21 +359,6 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
419
359
  observedInstallNonce = installNonce;
420
360
  continue;
421
361
  }
422
- // OZ built-in primitive. Distinguish by the parameter shape we
423
- // emitted; matching one of the three primitives exactly pins the
424
- // kind we built.
425
- if (fields.has('spending_limit') && fields.has('period_ledgers')) {
426
- policies.push({ kind: 'oz_builtin', address, primitive: 'spending_limit' });
427
- continue;
428
- }
429
- if (fields.has('threshold') && fields.has('signer_weights')) {
430
- policies.push({ kind: 'oz_builtin', address, primitive: 'weighted_threshold' });
431
- continue;
432
- }
433
- if (fields.has('threshold')) {
434
- policies.push({ kind: 'oz_builtin', address, primitive: 'simple_threshold' });
435
- continue;
436
- }
437
362
  throw new Error(`install_policy: policies[${address}] value has an unknown field set; the encoder may have drifted`);
438
363
  }
439
364
  // `observedInstallNonce` is the nonce baked into whichever interpreter
@@ -462,6 +387,3 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
462
387
  installNonce,
463
388
  };
464
389
  }
465
- // Local re-import to avoid pulling the class from the SDK module path
466
- // at the top of the file (avoids the unused-import lint).
467
- const stellar_sdk_2 = require("@stellar/stellar-sdk");
@@ -1 +1 @@
1
- export type { IRCompare, IRCompOp, IRCondition, IRLogic, IRPolicyRule, IRScalarType, IRSelector, IRVecMode, PolicyIR, } from './types.ts';
1
+ export type { IRCompare, IRCompOp, IRCondition, IRLogic, IRPolicyRule, IRScalarType, IRSelector, PolicyIR, } from './types.ts';