@crediolabs/policy-synth 0.2.0 → 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.
- package/README.md +4 -4
- package/dist/adapters/interpreter/adapter.d.ts +19 -25
- package/dist/adapters/interpreter/adapter.js +54 -487
- package/dist/adapters/interpreter/index.d.ts +1 -1
- package/dist/adapters/interpreter/index.js +1 -1
- package/dist/adapters/oz/adapter.js +1 -15
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1 -4
- package/dist/install/build-add-context-rule.d.ts +3 -19
- package/dist/install/build-add-context-rule.js +3 -98
- package/dist/install/build-install-policy.d.ts +4 -53
- package/dist/install/build-install-policy.js +44 -123
- package/dist/install/index.d.ts +0 -2
- package/dist/install/index.js +0 -7
- package/dist/ir/index.d.ts +1 -1
- package/dist/ir/types.d.ts +7 -76
- package/dist/ir/types.js +0 -2
- package/dist/predicate/decode.d.ts +1 -1
- package/dist/predicate/decode.js +2 -70
- package/dist/predicate/encode.js +45 -229
- package/dist/predicate/from-json.js +1 -42
- package/dist/record/decode.js +3 -8
- package/dist/review-card/builder.d.ts +4 -3
- package/dist/review-card/builder.js +18 -162
- package/dist/review-card/cross-check.js +2 -105
- package/dist/review-card/render-leaf.d.ts +4 -0
- package/dist/review-card/render-leaf.js +47 -0
- package/dist/run/index.d.ts +36 -139
- package/dist/run/index.js +125 -437
- package/dist/run/schemas.d.ts +168 -1929
- package/dist/run/schemas.js +40 -269
- package/dist/seams/types.d.ts +0 -2
- package/dist/simulate/deny-cases.d.ts +26 -0
- package/dist/simulate/deny-cases.js +282 -0
- package/dist/simulate/evaluate.d.ts +18 -0
- package/dist/simulate/evaluate.js +271 -0
- package/dist/simulate/index.d.ts +4 -0
- package/dist/simulate/index.js +8 -0
- package/dist/synth/compose-from-recording.d.ts +24 -51
- package/dist/synth/compose-from-recording.js +120 -282
- package/dist/synth/deny-cases.d.ts +5 -7
- package/dist/synth/deny-cases.js +23 -373
- package/dist/synth/evaluate.d.ts +0 -21
- package/dist/synth/evaluate.js +56 -336
- package/dist/synth/index.d.ts +0 -5
- package/dist/synth/index.js +0 -5
- package/dist/synth/permit-context.d.ts +2 -9
- package/dist/synth/permit-context.js +1 -82
- package/dist/synth/synthesize-from-recording.d.ts +1 -29
- package/dist/synth/synthesize-from-recording.js +41 -356
- package/dist/types.d.ts +8 -60
- package/dist/types.js +5 -2
- package/dist/verify/simulate.d.ts +1 -14
- package/dist/verify/simulate.js +2 -88
- package/dist/verify/verify.d.ts +1 -7
- package/dist/verify/verify.js +0 -8
- package/dist-cjs/adapters/interpreter/adapter.d.ts +19 -25
- package/dist-cjs/adapters/interpreter/adapter.js +56 -489
- package/dist-cjs/adapters/interpreter/index.d.ts +1 -1
- package/dist-cjs/adapters/interpreter/index.js +1 -2
- package/dist-cjs/adapters/oz/adapter.js +1 -15
- package/dist-cjs/errors.d.ts +1 -1
- package/dist-cjs/index.d.ts +1 -4
- package/dist-cjs/index.js +1 -4
- package/dist-cjs/install/build-add-context-rule.d.ts +3 -19
- package/dist-cjs/install/build-add-context-rule.js +1 -97
- package/dist-cjs/install/build-install-policy.d.ts +4 -53
- package/dist-cjs/install/build-install-policy.js +44 -122
- package/dist-cjs/install/index.d.ts +0 -2
- package/dist-cjs/install/index.js +2 -23
- package/dist-cjs/ir/index.d.ts +1 -1
- package/dist-cjs/ir/types.d.ts +7 -76
- package/dist-cjs/ir/types.js +0 -2
- package/dist-cjs/predicate/decode.d.ts +1 -1
- package/dist-cjs/predicate/decode.js +2 -70
- package/dist-cjs/predicate/encode.js +45 -229
- package/dist-cjs/predicate/from-json.js +1 -42
- package/dist-cjs/record/decode.js +3 -8
- package/dist-cjs/review-card/builder.d.ts +4 -3
- package/dist-cjs/review-card/builder.js +23 -167
- package/dist-cjs/review-card/cross-check.js +7 -110
- package/dist-cjs/review-card/render-leaf.d.ts +4 -0
- package/dist-cjs/review-card/render-leaf.js +52 -0
- package/dist-cjs/run/index.d.ts +36 -139
- package/dist-cjs/run/index.js +125 -444
- package/dist-cjs/run/schemas.d.ts +168 -1929
- package/dist-cjs/run/schemas.js +41 -270
- package/dist-cjs/seams/types.d.ts +0 -2
- package/dist-cjs/simulate/deny-cases.d.ts +26 -0
- package/dist-cjs/simulate/deny-cases.js +286 -0
- package/dist-cjs/simulate/evaluate.d.ts +18 -0
- package/dist-cjs/simulate/evaluate.js +274 -0
- package/dist-cjs/simulate/index.d.ts +4 -0
- package/dist-cjs/simulate/index.js +13 -0
- package/dist-cjs/synth/compose-from-recording.d.ts +24 -51
- package/dist-cjs/synth/compose-from-recording.js +120 -282
- package/dist-cjs/synth/deny-cases.d.ts +5 -7
- package/dist-cjs/synth/deny-cases.js +23 -374
- package/dist-cjs/synth/evaluate.d.ts +0 -21
- package/dist-cjs/synth/evaluate.js +57 -337
- package/dist-cjs/synth/index.d.ts +0 -5
- package/dist-cjs/synth/index.js +1 -11
- package/dist-cjs/synth/permit-context.d.ts +2 -9
- package/dist-cjs/synth/permit-context.js +1 -82
- package/dist-cjs/synth/synthesize-from-recording.d.ts +1 -29
- package/dist-cjs/synth/synthesize-from-recording.js +39 -354
- package/dist-cjs/types.d.ts +8 -60
- package/dist-cjs/types.js +6 -3
- package/dist-cjs/verify/simulate.d.ts +1 -14
- package/dist-cjs/verify/simulate.js +2 -88
- package/dist-cjs/verify/verify.d.ts +1 -7
- package/dist-cjs/verify/verify.js +0 -8
- package/package.json +4 -4
- package/src/adapters/interpreter/adapter.ts +76 -572
- package/src/errors.ts +0 -19
- package/src/index.ts +1 -4
- package/src/install/build-add-context-rule.ts +5 -139
- package/src/install/build-install-policy.ts +93 -214
- package/src/install/index.ts +0 -34
- package/src/predicate/decode.ts +2 -70
- package/src/predicate/encode.ts +49 -261
- package/src/predicate/from-json.ts +1 -43
- package/src/record/decode.ts +3 -8
- package/src/review-card/builder.ts +19 -168
- package/src/review-card/cross-check.ts +3 -105
- package/src/review-card/render-leaf.ts +48 -0
- package/src/run/index.ts +144 -572
- package/src/run/schemas.ts +42 -291
- package/src/simulate/deny-cases.ts +334 -0
- package/src/simulate/evaluate.ts +284 -0
- package/src/simulate/index.ts +11 -0
- package/src/synth/compose-from-recording.ts +148 -347
- package/src/synth/index.ts +0 -13
- package/src/synth/synthesize-from-recording.ts +43 -456
- package/src/types.ts +13 -49
- package/dist/install/authority-overlap.d.ts +0 -134
- package/dist/install/authority-overlap.js +0 -0
- package/dist/install/build-install-predicate.d.ts +0 -96
- package/dist/install/build-install-predicate.js +0 -444
- package/dist/install/build-merge-policy.d.ts +0 -70
- package/dist/install/build-merge-policy.js +0 -130
- package/dist/install/plan-merge-policy.d.ts +0 -49
- package/dist/install/plan-merge-policy.js +0 -86
- package/dist/install/read-account-rules.d.ts +0 -100
- package/dist/install/read-account-rules.js +0 -283
- package/dist-cjs/install/authority-overlap.d.ts +0 -134
- package/dist-cjs/install/authority-overlap.js +0 -0
- package/dist-cjs/install/build-install-predicate.d.ts +0 -96
- package/dist-cjs/install/build-install-predicate.js +0 -479
- package/dist-cjs/install/build-merge-policy.d.ts +0 -70
- package/dist-cjs/install/build-merge-policy.js +0 -134
- package/dist-cjs/install/plan-merge-policy.d.ts +0 -49
- package/dist-cjs/install/plan-merge-policy.js +0 -90
- package/dist-cjs/install/read-account-rules.d.ts +0 -100
- package/dist-cjs/install/read-account-rules.js +0 -296
- package/src/adapters/interpreter/index.ts +0 -8
- package/src/adapters/oz/adapter.ts +0 -376
- package/src/adapters/oz/index.ts +0 -9
- package/src/codegen/compile-gate.ts +0 -167
- package/src/codegen/index.ts +0 -17
- package/src/codegen/template.ts +0 -165
- package/src/install/authority-overlap.ts +0 -0
- package/src/install/build-merge-policy.ts +0 -219
- package/src/install/plan-merge-policy.ts +0 -133
- package/src/install/read-account-rules.ts +0 -376
- package/src/ir/index.ts +0 -13
- package/src/ir/types.ts +0 -132
- package/src/mandate/index.ts +0 -4
- package/src/mandate/to-ir.ts +0 -71
- package/src/mandate/types.ts +0 -21
- package/src/seams/index.ts +0 -11
- package/src/seams/types.ts +0 -81
- package/src/synth/deny-cases.ts +0 -663
- package/src/synth/evaluate.ts +0 -613
- package/src/synth/harness.ts +0 -68
- package/src/synth/minimize.ts +0 -48
- package/src/synth/permit-context.ts +0 -136
- package/src/synth/predicate-literals.ts +0 -27
- package/src/synth/synthesize-from-mandate.ts +0 -82
- package/src/verify/envelope.ts +0 -28
- package/src/verify/index.ts +0 -5
- package/src/verify/simulate.ts +0 -311
- package/src/verify/verify.ts +0 -243
|
@@ -1,145 +1,51 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// src/synth/evaluate.ts -
|
|
2
|
+
// src/synth/evaluate.ts - TypeScript reference evaluator for grammar version 3.
|
|
3
3
|
//
|
|
4
4
|
// Pure function. Determinism: same `(predicate, ctx)` -> byte-identical result,
|
|
5
5
|
// no clock, no randomness. Deny order (deny on FIRST violation, stable reason):
|
|
6
|
-
// 1.
|
|
7
|
-
// 2.
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// 5. `in` membership; empty haystack ALWAYS denies -> 'NOT_IN_ALLOWLIST'
|
|
12
|
-
// 6. amount / window_spent via BigInt -> 'AMOUNT_BOUND'
|
|
13
|
-
// 7. invocation_count_in_window -> 'FREQUENCY'
|
|
14
|
-
// 8. oracle_price: fatal -> throw OracleError, deny with
|
|
15
|
-
// underlying ORACLE_* reason -> 'ORACLE_*'
|
|
16
|
-
// 9. boolean nodes (and/or/not)
|
|
17
|
-
// 10. signer threshold gate -> 'THRESHOLD_NOT_MET'
|
|
18
|
-
// 11. otherwise permit.
|
|
6
|
+
// 1. contract mismatch -> 'CONTRACT_SCOPE'
|
|
7
|
+
// 2. per-ScVal equality on fn/args; EXACT ordered vector
|
|
8
|
+
// equality; fail-closed on opaque args -> 'ARG_MISMATCH'
|
|
9
|
+
// 3. `in` membership; empty haystack ALWAYS denies -> 'NOT_IN_ALLOWLIST'
|
|
10
|
+
// 4. otherwise permit.
|
|
19
11
|
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
12
|
+
// Grammar version 3 nodes: and, eq, lte
|
|
13
|
+
// Grammar version 3 leaves: call_contract, call_fn, call_arg(i),
|
|
14
|
+
// call_arg_len(i), call_arg_field(i, element, field),
|
|
15
|
+
// literal_address, literal_i128, literal_symbol, literal_u32, literal_vec
|
|
16
|
+
// Grammar version 3 deny reasons: ARG_MISMATCH, CONTRACT_SCOPE,
|
|
17
|
+
// UNSUPPORTED_NODE, NOT_IN_ALLOWLIST
|
|
22
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
19
|
exports.evaluate = evaluate;
|
|
24
|
-
const predicate_literals_ts_1 = require("./predicate-literals.js");
|
|
25
|
-
/** Oracle prices normalise to this many decimals; mirrors NORMALISED_DECIMALS
|
|
26
|
-
* in oracle.rs. A threshold on any other basis must say so. */
|
|
27
|
-
const NORMALISED_DECIMALS = 9;
|
|
28
|
-
/** Mirrors MAX_ORACLE_THRESHOLD_DECIMALS in dsl.rs. */
|
|
29
|
-
const MAX_ORACLE_THRESHOLD_DECIMALS = 18;
|
|
30
|
-
/** Internal fatal thrown by the oracle path; caught at the top of `evaluate`
|
|
31
|
-
* and converted to the matching `ORACLE_*` deny reason. NOT a boolean-false
|
|
32
|
-
* that `not` / `or` could mask. */
|
|
33
|
-
class OracleError extends Error {
|
|
34
|
-
code;
|
|
35
|
-
constructor(code) {
|
|
36
|
-
super(`oracle fatal: ${code}`);
|
|
37
|
-
this.code = code;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const ORACLE_ERROR_CODES = {
|
|
41
|
-
stale: 'ORACLE_STALE',
|
|
42
|
-
missing: 'ORACLE_MISSING',
|
|
43
|
-
deviation: 'ORACLE_DEVIATION_EXCEEDED',
|
|
44
|
-
paused: 'ORACLE_PAUSED',
|
|
45
|
-
decimals: 'ORACLE_DECIMALS_MISMATCH',
|
|
46
|
-
fingerprint: 'ORACLE_FINGERPRINT_DRIFT',
|
|
47
|
-
};
|
|
48
20
|
/** Evaluate a `PredicateNode` against the candidate call described by `ctx`.
|
|
49
21
|
* Pure function. Returns `{ permit: true }` or `{ permit: false; reason }`. */
|
|
50
22
|
function evaluate(predicate, ctx) {
|
|
51
|
-
|
|
52
|
-
// --- step 1: ledger-time expiry ---
|
|
53
|
-
if (ctx.validUntilLedger !== undefined && ctx.atLedger > ctx.validUntilLedger) {
|
|
54
|
-
return { permit: false, reason: 'EXPIRED' };
|
|
55
|
-
}
|
|
56
|
-
// --- step 2..9: predicate tree ---
|
|
57
|
-
const decision = walk(predicate, ctx);
|
|
58
|
-
// --- step 10: signer threshold gate (only when the predicate permitted) ---
|
|
59
|
-
if (decision.permit && ctx.signerWeights !== undefined) {
|
|
60
|
-
let totalWeight = 0n;
|
|
61
|
-
for (const w of Object.values(ctx.signerWeights)) {
|
|
62
|
-
// weights are non-negative integers; BigInt keeps the gate bounded
|
|
63
|
-
totalWeight += BigInt(w);
|
|
64
|
-
}
|
|
65
|
-
if (totalWeight === 0n)
|
|
66
|
-
return { permit: false, reason: 'THRESHOLD_NOT_MET' };
|
|
67
|
-
}
|
|
68
|
-
return decision;
|
|
69
|
-
}
|
|
70
|
-
catch (e) {
|
|
71
|
-
if (e instanceof OracleError) {
|
|
72
|
-
return { permit: false, reason: e.code };
|
|
73
|
-
}
|
|
74
|
-
throw e;
|
|
75
|
-
}
|
|
23
|
+
return walk(predicate, ctx);
|
|
76
24
|
}
|
|
77
25
|
/** Walk the predicate tree. Returns the FIRST deny reason encountered on
|
|
78
|
-
* the active branch (so `and` fails-fast
|
|
26
|
+
* the active branch (so `and` fails-fast). */
|
|
79
27
|
function walk(node, ctx) {
|
|
80
28
|
switch (node.op) {
|
|
81
29
|
case 'and': {
|
|
82
30
|
let lastDeny = null;
|
|
83
31
|
for (const child of node.children) {
|
|
84
32
|
const r = walk(child, ctx);
|
|
85
|
-
if (!r.permit)
|
|
86
|
-
// deny-on-first: short-circuit on the failing child.
|
|
33
|
+
if (!r.permit)
|
|
87
34
|
return r;
|
|
88
|
-
}
|
|
89
35
|
lastDeny = r;
|
|
90
36
|
}
|
|
91
37
|
return lastDeny ?? { permit: true };
|
|
92
38
|
}
|
|
93
|
-
case 'or': {
|
|
94
|
-
let lastDeny = null;
|
|
95
|
-
for (const child of node.children) {
|
|
96
|
-
const r = walk(child, ctx);
|
|
97
|
-
if (r.permit)
|
|
98
|
-
return r;
|
|
99
|
-
lastDeny = r;
|
|
100
|
-
}
|
|
101
|
-
return lastDeny ?? { permit: false, reason: 'NOT_IN_ALLOWLIST' };
|
|
102
|
-
}
|
|
103
|
-
case 'not': {
|
|
104
|
-
// `not` structurally inverts the child unless the child contains an
|
|
105
|
-
// oracle leaf (compile-time rule: no oracle leaf under not/or). A
|
|
106
|
-
// child `OracleError` is re-thrown to the catch at the top of `evaluate`.
|
|
107
|
-
const r = walk(node.child, ctx);
|
|
108
|
-
if (r.permit)
|
|
109
|
-
return { permit: false, reason: 'FN_MISMATCH' };
|
|
110
|
-
return { permit: true };
|
|
111
|
-
}
|
|
112
39
|
case 'eq':
|
|
113
|
-
case 'lt':
|
|
114
40
|
case 'lte':
|
|
115
|
-
case 'gt':
|
|
116
|
-
case 'gte':
|
|
117
41
|
return evalCompare(node.op, node.left, node.right, ctx);
|
|
118
42
|
case 'in':
|
|
119
43
|
return evalIn(node.needle, node.haystack, ctx);
|
|
120
44
|
}
|
|
121
45
|
}
|
|
122
|
-
/**
|
|
46
|
+
/** Comparison leaf evaluation. */
|
|
123
47
|
function evalCompare(op, left, right, ctx) {
|
|
124
|
-
//
|
|
125
|
-
if (left.kind === 'now' && right.kind === 'valid_until') {
|
|
126
|
-
const expired = op === 'gt' || op === 'gte' ? ctx.nowSeconds >= 0 : ctx.nowSeconds < 0;
|
|
127
|
-
// `valid_until` is modelled as a synthetic future timestamp far past
|
|
128
|
-
// `nowSeconds` so the only true-positive expired path is the `gt`/`gte`
|
|
129
|
-
// shapes callers actually write.
|
|
130
|
-
if (op === 'gt' || op === 'gte') {
|
|
131
|
-
if (ctx.nowSeconds > 0)
|
|
132
|
-
return { permit: false, reason: 'EXPIRED' };
|
|
133
|
-
}
|
|
134
|
-
else if (op === 'lt' || op === 'lte') {
|
|
135
|
-
return { permit: true };
|
|
136
|
-
}
|
|
137
|
-
return expired ? { permit: false, reason: 'EXPIRED' } : { permit: true };
|
|
138
|
-
}
|
|
139
|
-
if (right.kind === 'now' && left.kind === 'valid_until') {
|
|
140
|
-
return evalCompare(op, right, left, ctx);
|
|
141
|
-
}
|
|
142
|
-
// --- step 3: CONTRACT_SCOPE on call_contract eq ---
|
|
48
|
+
// CONTRACT_SCOPE on call_contract eq
|
|
143
49
|
if (left.kind === 'call_contract' && op === 'eq') {
|
|
144
50
|
if (right.kind !== 'literal_address')
|
|
145
51
|
return { permit: false, reason: 'CONTRACT_SCOPE' };
|
|
@@ -147,32 +53,20 @@ function evalCompare(op, left, right, ctx) {
|
|
|
147
53
|
? { permit: true }
|
|
148
54
|
: { permit: false, reason: 'CONTRACT_SCOPE' };
|
|
149
55
|
}
|
|
150
|
-
//
|
|
56
|
+
// call_fn equality
|
|
151
57
|
if (left.kind === 'call_fn' && op === 'eq') {
|
|
152
58
|
if (right.kind !== 'literal_symbol')
|
|
153
|
-
return { permit: false, reason: '
|
|
154
|
-
return right.value === ctx.fn ? { permit: true } : { permit: false, reason: '
|
|
59
|
+
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
60
|
+
return right.value === ctx.fn ? { permit: true } : { permit: false, reason: 'ARG_MISMATCH' };
|
|
155
61
|
}
|
|
156
|
-
//
|
|
62
|
+
// call_arg comparison (eq / exact-vec, or lte ordered numeric bound)
|
|
157
63
|
if (left.kind === 'call_arg') {
|
|
158
|
-
// The swap's canonical form is `call_arg[out] >= call_arg_scaled(in, num, den)`.
|
|
159
|
-
// Dispatched here so the floor's dedicated reason codes (ARITHMETIC_OVERFLOW
|
|
160
|
-
// -> SLIPPAGE_FLOOR) reach the user; routing the scaled RHS through the
|
|
161
|
-
// generic `evalArgOrderedCompare` would mask overflow as ARG_MISMATCH.
|
|
162
|
-
if (right.kind === 'call_arg_scaled') {
|
|
163
|
-
return evalScaledArgCompare(op, left, right, ctx);
|
|
164
|
-
}
|
|
165
64
|
const actual = ctx.args[left.index];
|
|
166
65
|
if (op !== 'eq')
|
|
167
66
|
return evalArgOrderedCompare(op, actual, right);
|
|
168
67
|
return evalArgEq(op, actual, right, ctx);
|
|
169
68
|
}
|
|
170
|
-
//
|
|
171
|
-
// Symmetric form so a policy that phrases the floor either way works.
|
|
172
|
-
if (left.kind === 'call_arg_scaled') {
|
|
173
|
-
return evalScaledArgCompare(op, right, left, ctx);
|
|
174
|
-
}
|
|
175
|
-
// --- step 4c: call_arg_len: length of a vec-typed argument as u32.
|
|
69
|
+
// call_arg_len: length of a vec-typed argument as u32.
|
|
176
70
|
// Fails closed on a non-vec / absent arg or a non-u32 literal.
|
|
177
71
|
if (left.kind === 'call_arg_len') {
|
|
178
72
|
const actual = ctx.args[left.index];
|
|
@@ -184,7 +78,7 @@ function evalCompare(op, left, right, ctx) {
|
|
|
184
78
|
? { permit: true }
|
|
185
79
|
: { permit: false, reason: 'ARG_MISMATCH' };
|
|
186
80
|
}
|
|
187
|
-
//
|
|
81
|
+
// call_arg_field: value of a field in the map at element i of
|
|
188
82
|
// the vec at argument index. Fails closed on shape / type / range issues.
|
|
189
83
|
if (left.kind === 'call_arg_field') {
|
|
190
84
|
const actual = ctx.args[left.index];
|
|
@@ -202,34 +96,18 @@ function evalCompare(op, left, right, ctx) {
|
|
|
202
96
|
return evalArgEq(op, entry.val, right, ctx);
|
|
203
97
|
return evalArgOrderedCompare(op, entry.val, right);
|
|
204
98
|
}
|
|
205
|
-
// --- step 6: AMOUNT_BOUND ---
|
|
206
|
-
if (left.kind === 'amount' && op !== 'eq') {
|
|
207
|
-
return evalAmountCompare(op, left.token, right, ctx, 'amountByToken');
|
|
208
|
-
}
|
|
209
|
-
if (left.kind === 'window_spent' && op !== 'eq') {
|
|
210
|
-
return evalWindowSpentCompare(op, left.token, right, ctx);
|
|
211
|
-
}
|
|
212
|
-
// `eq` on amount / window_spent not defined as a bound - fall through.
|
|
213
|
-
// --- step 7: FREQUENCY ---
|
|
214
|
-
if (left.kind === 'invocation_count_in_window') {
|
|
215
|
-
return evalFrequencyCompare(op, left.windowSecs, right, ctx);
|
|
216
|
-
}
|
|
217
|
-
// --- step 8: oracle_price (FATAL via throw) ---
|
|
218
|
-
if (left.kind === 'oracle_price') {
|
|
219
|
-
return evalOracleCompare(op, left.asset, right, ctx);
|
|
220
|
-
}
|
|
221
99
|
// Unknown leaf/op combination - structural fail-closed.
|
|
222
|
-
return { permit: false, reason: '
|
|
100
|
+
return { permit: false, reason: 'UNSUPPORTED_NODE' };
|
|
223
101
|
}
|
|
224
|
-
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
function evalArgEq(op, actual, right,
|
|
102
|
+
/** Per-ScVal equality. Handles literal_vec as an EXACT ordered sequence:
|
|
103
|
+
* compare element-by-element in order; deny if length or any element differs.
|
|
104
|
+
* Opaque args (`type: 'other'`) fail closed. */
|
|
105
|
+
function evalArgEq(op, actual, right, _ctx) {
|
|
228
106
|
// eq(call_arg[i], literal_vec) -> EXACT ordered vector equality.
|
|
229
107
|
if (op === 'eq' && right.kind === 'literal_vec') {
|
|
230
108
|
if (actual?.type !== 'vec')
|
|
231
109
|
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
232
|
-
return compareVecExact(actual.value, right.elements
|
|
110
|
+
return compareVecExact(actual.value, right.elements)
|
|
233
111
|
? { permit: true }
|
|
234
112
|
: { permit: false, reason: 'ARG_MISMATCH' };
|
|
235
113
|
}
|
|
@@ -263,112 +141,18 @@ function evalArgEq(op, actual, right, ctx) {
|
|
|
263
141
|
? { permit: true }
|
|
264
142
|
: { permit: false, reason: 'ARG_MISMATCH' };
|
|
265
143
|
}
|
|
266
|
-
if (op === 'eq' && right.kind === 'literal_u64') {
|
|
267
|
-
if (!actual)
|
|
268
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
269
|
-
return actual.type === 'u64' && actual.value === right.value
|
|
270
|
-
? { permit: true }
|
|
271
|
-
: { permit: false, reason: 'ARG_MISMATCH' };
|
|
272
|
-
}
|
|
273
|
-
if (op === 'eq' && right.kind === 'literal_bytes') {
|
|
274
|
-
if (!actual)
|
|
275
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
276
|
-
return actual.type === 'bytes' && actual.value === right.value
|
|
277
|
-
? { permit: true }
|
|
278
|
-
: { permit: false, reason: 'ARG_MISMATCH' };
|
|
279
|
-
}
|
|
280
144
|
// Anything else: fail closed on opacity (cannot decode the arg reliably).
|
|
281
145
|
if (!actual || actual.type === 'other')
|
|
282
146
|
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
283
147
|
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
284
148
|
}
|
|
285
|
-
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* `ARG_MISMATCH`. A scaled-on-scaled compare denies `ARG_MISMATCH`
|
|
290
|
-
* (no definable semantics). The non-scaled operand must be numeric
|
|
291
|
-
* (`call_arg` carrying a number, or a numeric literal); else `ARG_MISMATCH`. */
|
|
292
|
-
function evalScaledArgCompare(op, left, right, ctx) {
|
|
293
|
-
let scaled;
|
|
294
|
-
let other;
|
|
295
|
-
let scaledOnRight;
|
|
296
|
-
if (left.kind === 'call_arg_scaled') {
|
|
297
|
-
scaled = left;
|
|
298
|
-
other = right;
|
|
299
|
-
scaledOnRight = false;
|
|
300
|
-
}
|
|
301
|
-
else if (right.kind === 'call_arg_scaled') {
|
|
302
|
-
scaled = right;
|
|
303
|
-
other = left;
|
|
304
|
-
scaledOnRight = true;
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
// Programming error in the dispatcher; fail closed.
|
|
308
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
309
|
-
}
|
|
310
|
-
// Out-of-bounds or non-numeric arg fails closed as ARG_MISMATCH (not
|
|
311
|
-
// SLIPPAGE_FLOOR) - a violated floor is the wrong code when the operand
|
|
312
|
-
// itself could not be read.
|
|
313
|
-
if (scaled.index >= ctx.args.length) {
|
|
314
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
315
|
-
}
|
|
316
|
-
const input = argNumericBigInt(ctx.args[scaled.index]);
|
|
317
|
-
if (input === null)
|
|
318
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
319
|
-
let num;
|
|
320
|
-
let den;
|
|
321
|
-
try {
|
|
322
|
-
num = BigInt(scaled.num);
|
|
323
|
-
den = BigInt(scaled.den);
|
|
324
|
-
}
|
|
325
|
-
catch {
|
|
326
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
327
|
-
}
|
|
328
|
-
// Install refuses `den == 0` and `num <= 0` / `den <= 0`. The runtime
|
|
329
|
-
// check is defensive belt-and-braces so a validator regression cannot
|
|
330
|
-
// panic the frame on a divide-by-zero.
|
|
331
|
-
if (den === 0n)
|
|
332
|
-
return { permit: false, reason: 'ARITHMETIC_OVERFLOW' };
|
|
333
|
-
const product = input * num;
|
|
334
|
-
let scaledValue;
|
|
335
|
-
try {
|
|
336
|
-
// BigInt division truncates toward zero (matches Rust `i128::checked_div`).
|
|
337
|
-
scaledValue = product / den;
|
|
338
|
-
}
|
|
339
|
-
catch {
|
|
340
|
-
return { permit: false, reason: 'ARITHMETIC_OVERFLOW' };
|
|
341
|
-
}
|
|
342
|
-
// i128 range check: the contract would have wrapped on i128 arithmetic;
|
|
343
|
-
// surface the same deny.
|
|
344
|
-
const I128_MAX = (1n << 127n) - 1n;
|
|
345
|
-
const I128_MIN = -(1n << 127n);
|
|
346
|
-
if (scaledValue > I128_MAX || scaledValue < I128_MIN) {
|
|
347
|
-
return { permit: false, reason: 'ARITHMETIC_OVERFLOW' };
|
|
348
|
-
}
|
|
349
|
-
let otherVal;
|
|
350
|
-
if (other.kind === 'call_arg') {
|
|
351
|
-
otherVal = argNumericBigInt(ctx.args[other.index]);
|
|
352
|
-
}
|
|
353
|
-
else {
|
|
354
|
-
otherVal = (0, predicate_literals_ts_1.literalNumericBigInt)(other);
|
|
355
|
-
}
|
|
356
|
-
if (otherVal === null)
|
|
357
|
-
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
358
|
-
const pass = scaledOnRight
|
|
359
|
-
? bigintCmp(op, otherVal.toString(), scaledValue.toString())
|
|
360
|
-
: bigintCmp(op, scaledValue.toString(), otherVal.toString());
|
|
361
|
-
return pass ? { permit: true } : { permit: false, reason: 'SLIPPAGE_FLOOR' };
|
|
362
|
-
}
|
|
363
|
-
/** Ordered numeric comparison (lt/lte/gt/gte) on a `call_arg`. The interpreter
|
|
364
|
-
* reads the arg as an integer (i128 / u64 / u32 on the recorder's ScVal
|
|
365
|
-
* surface) and compares it to a numeric literal via BigInt. A non-numeric arg
|
|
366
|
-
* or a non-numeric literal fails closed (ARG_MISMATCH) rather than permitting
|
|
367
|
-
* an undecidable bound. Backs the SoroSwap input-amount cap
|
|
368
|
-
* (`call_arg[0] <= limit`). */
|
|
149
|
+
/** Ordered numeric comparison (lte) on a `call_arg`. The interpreter reads the
|
|
150
|
+
* arg as an integer (i128 on the recorder's ScVal surface) and compares it
|
|
151
|
+
* to a numeric literal via BigInt. A non-numeric arg or a non-numeric literal
|
|
152
|
+
* fails closed (ARG_MISMATCH) rather than permitting an undecidable bound. */
|
|
369
153
|
function evalArgOrderedCompare(op, actual, right) {
|
|
370
154
|
const actualInt = argNumericBigInt(actual);
|
|
371
|
-
const literalInt =
|
|
155
|
+
const literalInt = literalNumericBigInt(right);
|
|
372
156
|
if (actualInt === null || literalInt === null) {
|
|
373
157
|
return { permit: false, reason: 'ARG_MISMATCH' };
|
|
374
158
|
}
|
|
@@ -376,12 +160,12 @@ function evalArgOrderedCompare(op, actual, right) {
|
|
|
376
160
|
? { permit: true }
|
|
377
161
|
: { permit: false, reason: 'ARG_MISMATCH' };
|
|
378
162
|
}
|
|
379
|
-
/** BigInt value of a numeric-integer ScVal arg (i128 /
|
|
163
|
+
/** BigInt value of a numeric-integer ScVal arg (i128 / u32), or null when
|
|
380
164
|
* the arg is absent, opaque, or a non-numeric type. */
|
|
381
165
|
function argNumericBigInt(actual) {
|
|
382
166
|
if (!actual)
|
|
383
167
|
return null;
|
|
384
|
-
if (actual.type === 'i128' || actual.type === '
|
|
168
|
+
if (actual.type === 'i128' || actual.type === 'u32') {
|
|
385
169
|
try {
|
|
386
170
|
return BigInt(actual.value);
|
|
387
171
|
}
|
|
@@ -391,10 +175,27 @@ function argNumericBigInt(actual) {
|
|
|
391
175
|
}
|
|
392
176
|
return null;
|
|
393
177
|
}
|
|
178
|
+
/** BigInt value of a numeric-integer literal leaf (`literal_i128` / `literal_u32`),
|
|
179
|
+
* or null for a non-numeric literal. Callers fail closed on null. */
|
|
180
|
+
function literalNumericBigInt(leaf) {
|
|
181
|
+
switch (leaf.kind) {
|
|
182
|
+
case 'literal_i128':
|
|
183
|
+
try {
|
|
184
|
+
return BigInt(leaf.value);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
case 'literal_u32':
|
|
190
|
+
return BigInt(leaf.value);
|
|
191
|
+
default:
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
394
195
|
/** Element-by-element ordered comparison of an `ScVal[]` against a
|
|
395
196
|
* `PredicateLeaf[]`. Equal-length and equal at every index => permit.
|
|
396
197
|
* Length mismatch OR any element mismatch => deny ARG_MISMATCH. */
|
|
397
|
-
function compareVecExact(actual, expected
|
|
198
|
+
function compareVecExact(actual, expected) {
|
|
398
199
|
if (actual.length !== expected.length)
|
|
399
200
|
return false;
|
|
400
201
|
for (let i = 0; i < expected.length; i++) {
|
|
@@ -402,14 +203,13 @@ function compareVecExact(actual, expected, ctx) {
|
|
|
402
203
|
const a = actual[i];
|
|
403
204
|
if (!e || !a)
|
|
404
205
|
return false;
|
|
405
|
-
const r = evalArgEq('eq', a, e,
|
|
206
|
+
const r = evalArgEq('eq', a, e, {});
|
|
406
207
|
if (!r.permit)
|
|
407
208
|
return false;
|
|
408
209
|
}
|
|
409
210
|
return true;
|
|
410
211
|
}
|
|
411
|
-
/**
|
|
412
|
-
* fails closed. */
|
|
212
|
+
/** `in` membership. Empty haystack ALWAYS denies. Opaque needle fails closed. */
|
|
413
213
|
function evalIn(needle, haystack, ctx) {
|
|
414
214
|
if (haystack.length === 0)
|
|
415
215
|
return { permit: false, reason: 'NOT_IN_ALLOWLIST' };
|
|
@@ -449,14 +249,6 @@ function resolveLeaf(leaf, ctx) {
|
|
|
449
249
|
const entry = element.value.find((e) => e.key === leaf.field);
|
|
450
250
|
return entry ? entry.val : undefined;
|
|
451
251
|
}
|
|
452
|
-
case 'amount':
|
|
453
|
-
case 'window_spent':
|
|
454
|
-
case 'oracle_price':
|
|
455
|
-
case 'invocation_count_in_window':
|
|
456
|
-
case 'now':
|
|
457
|
-
case 'valid_until':
|
|
458
|
-
case 'call_arg_scaled':
|
|
459
|
-
return undefined; // selector leaves with no ScVal projection
|
|
460
252
|
case 'literal_address':
|
|
461
253
|
return { type: 'address', value: leaf.value };
|
|
462
254
|
case 'literal_i128':
|
|
@@ -465,90 +257,18 @@ function resolveLeaf(leaf, ctx) {
|
|
|
465
257
|
return { type: 'symbol', value: leaf.value };
|
|
466
258
|
case 'literal_u32':
|
|
467
259
|
return { type: 'u32', value: String(leaf.value) };
|
|
468
|
-
case 'literal_u64':
|
|
469
|
-
return { type: 'u64', value: leaf.value };
|
|
470
|
-
case 'literal_bytes':
|
|
471
|
-
return { type: 'bytes', value: leaf.value };
|
|
472
260
|
case 'literal_vec':
|
|
473
261
|
return undefined;
|
|
474
262
|
}
|
|
475
263
|
}
|
|
476
|
-
/**
|
|
477
|
-
* per-token BigInt record (current vs. rolling) to an i128 literal; the
|
|
478
|
-
* compare + denial reason are identical, so a single helper handles both. */
|
|
479
|
-
function evalAmountCompare(op, token, right, ctx, record) {
|
|
480
|
-
const literal = right.kind === 'literal_i128' ? right.value : null;
|
|
481
|
-
if (literal === null)
|
|
482
|
-
return { permit: false, reason: 'AMOUNT_BOUND' };
|
|
483
|
-
const actual = ctx[record][token] ?? '0';
|
|
484
|
-
return bigintCmp(op, actual, literal)
|
|
485
|
-
? { permit: true }
|
|
486
|
-
: { permit: false, reason: 'AMOUNT_BOUND' };
|
|
487
|
-
}
|
|
488
|
-
/** Step 6: window_spent compare on BigInt. */
|
|
489
|
-
function evalWindowSpentCompare(op, token, right, ctx) {
|
|
490
|
-
return evalAmountCompare(op, token, right, ctx, 'windowSpentByToken');
|
|
491
|
-
}
|
|
492
|
-
/** Step 7: invocation_count_in_window compare. */
|
|
493
|
-
function evalFrequencyCompare(op, windowSecs, right, ctx) {
|
|
494
|
-
const literal = right.kind === 'literal_u32' ? String(right.value) : null;
|
|
495
|
-
if (literal === null)
|
|
496
|
-
return { permit: false, reason: 'FREQUENCY' };
|
|
497
|
-
const actual = String(ctx.invocationCountByWindow[windowSecs] ?? 0);
|
|
498
|
-
return bigintCmp(op, actual, literal) ? { permit: true } : { permit: false, reason: 'FREQUENCY' };
|
|
499
|
-
}
|
|
500
|
-
/** Step 8: oracle_price compare. Reads `ctx.oraclePriceByAsset[asset]`. Any
|
|
501
|
-
* error entry OR a missing key throws `OracleError` (FATAL). A satisfied
|
|
502
|
-
* compare permits. */
|
|
503
|
-
function evalOracleCompare(op, asset, right, ctx) {
|
|
504
|
-
const entry = ctx.oraclePriceByAsset[asset];
|
|
505
|
-
if (!entry)
|
|
506
|
-
throw new OracleError('ORACLE_STALE');
|
|
507
|
-
if ('error' in entry) {
|
|
508
|
-
const mapped = ORACLE_ERROR_CODES[entry.error];
|
|
509
|
-
if (!mapped)
|
|
510
|
-
throw new OracleError('ORACLE_STALE');
|
|
511
|
-
throw new OracleError(mapped);
|
|
512
|
-
}
|
|
513
|
-
// Mirrors eval_oracle_compare in dsl.rs. The threshold MUST declare its
|
|
514
|
-
// decimal basis: prices are on the normalised 9-dp basis, and a bare literal
|
|
515
|
-
// is refused (not assumed) because a raw 14-dp threshold that assumed the
|
|
516
|
-
// 9-dp basis would permit everything.
|
|
517
|
-
if (right.kind !== 'oracle_threshold')
|
|
518
|
-
throw new OracleError('ORACLE_DECIMALS_MISMATCH');
|
|
519
|
-
if (right.decimals > MAX_ORACLE_THRESHOLD_DECIMALS) {
|
|
520
|
-
throw new OracleError('ORACLE_THRESHOLD_DECIMALS_OUT_OF_RANGE');
|
|
521
|
-
}
|
|
522
|
-
// Scale BOTH sides up to the wider basis; dividing the threshold down
|
|
523
|
-
// truncates and moves the permit boundary.
|
|
524
|
-
const decimals = BigInt(right.decimals);
|
|
525
|
-
const normalised = BigInt(NORMALISED_DECIMALS);
|
|
526
|
-
const common = decimals > normalised ? decimals : normalised;
|
|
527
|
-
const priceScaled = BigInt(entry.price) * 10n ** (common - normalised);
|
|
528
|
-
const literalScaled = BigInt(right.value) * 10n ** (common - decimals);
|
|
529
|
-
// A violated oracle threshold is a stateful bound (Rust dsl.rs:276 returns
|
|
530
|
-
// `DenyReason::StatefulBound`, deny code #104). The TS evaluator must mirror
|
|
531
|
-
// the same reason so a future TS/Rust reason divergence fails CI; the
|
|
532
|
-
// cross-layer harness in this file now asserts reason codes match.
|
|
533
|
-
return bigintCmp(op, String(priceScaled), String(literalScaled))
|
|
534
|
-
? { permit: true }
|
|
535
|
-
: { permit: false, reason: 'STATEFUL_BOUND' };
|
|
536
|
-
}
|
|
537
|
-
/** BigInt compare helper. `eq` is also supported by callers (selector-vs-literal
|
|
538
|
-
* equal checks), but the dedicated arg path uses it via `BigInt(actual) === BigInt(right)`. */
|
|
264
|
+
/** BigInt compare helper. */
|
|
539
265
|
function bigintCmp(op, aStr, bStr) {
|
|
540
266
|
const a = BigInt(aStr);
|
|
541
267
|
const b = BigInt(bStr);
|
|
542
268
|
switch (op) {
|
|
543
269
|
case 'eq':
|
|
544
270
|
return a === b;
|
|
545
|
-
case 'lt':
|
|
546
|
-
return a < b;
|
|
547
271
|
case 'lte':
|
|
548
272
|
return a <= b;
|
|
549
|
-
case 'gt':
|
|
550
|
-
return a > b;
|
|
551
|
-
case 'gte':
|
|
552
|
-
return a >= b;
|
|
553
273
|
}
|
|
554
274
|
}
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
export { isStellarAddress } from './address.ts';
|
|
2
2
|
export { type ComposeOptions, type ComposeResult, composeFromRecording, } from './compose-from-recording.ts';
|
|
3
|
-
export { type DenyCase, type GeneratedCases, generateCases, } from './deny-cases.ts';
|
|
4
|
-
export { type EvalContext, type EvalResult, evaluate } from './evaluate.ts';
|
|
5
|
-
export { type HarnessFailure, type HarnessResult, runHarness, } from './harness.ts';
|
|
6
3
|
export { type IntentFacts, lower } from './lower.ts';
|
|
7
|
-
export { minimize } from './minimize.ts';
|
|
8
4
|
export { type DecideScopeOptions, decideScope, type ScopeDecision, scopeToContextRuleType, } from './scope.ts';
|
|
9
|
-
export { synthesizeFromMandate } from './synthesize-from-mandate.ts';
|
|
10
5
|
export { type __TestInterpreterAdapterOptions, type SynthesizeFromRecordingOptions, synthesizeFromRecording, } from './synthesize-from-recording.ts';
|
package/dist-cjs/synth/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// src/synth/index.ts - re-export the synthesizer front-ends.
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.synthesizeFromRecording = exports.
|
|
4
|
+
exports.synthesizeFromRecording = exports.scopeToContextRuleType = exports.decideScope = exports.lower = exports.composeFromRecording = exports.isStellarAddress = void 0;
|
|
5
5
|
// Exported because `swapRecipientAllowlist` is part of the public synthesis
|
|
6
6
|
// input: a caller assembling one needs the same validator the schema applies,
|
|
7
7
|
// and re-deriving it elsewhere means a second address check that can drift.
|
|
@@ -9,20 +9,10 @@ var address_ts_1 = require("./address.js");
|
|
|
9
9
|
Object.defineProperty(exports, "isStellarAddress", { enumerable: true, get: function () { return address_ts_1.isStellarAddress; } });
|
|
10
10
|
var compose_from_recording_ts_1 = require("./compose-from-recording.js");
|
|
11
11
|
Object.defineProperty(exports, "composeFromRecording", { enumerable: true, get: function () { return compose_from_recording_ts_1.composeFromRecording; } });
|
|
12
|
-
var deny_cases_ts_1 = require("./deny-cases.js");
|
|
13
|
-
Object.defineProperty(exports, "generateCases", { enumerable: true, get: function () { return deny_cases_ts_1.generateCases; } });
|
|
14
|
-
var evaluate_ts_1 = require("./evaluate.js");
|
|
15
|
-
Object.defineProperty(exports, "evaluate", { enumerable: true, get: function () { return evaluate_ts_1.evaluate; } });
|
|
16
|
-
var harness_ts_1 = require("./harness.js");
|
|
17
|
-
Object.defineProperty(exports, "runHarness", { enumerable: true, get: function () { return harness_ts_1.runHarness; } });
|
|
18
12
|
var lower_ts_1 = require("./lower.js");
|
|
19
13
|
Object.defineProperty(exports, "lower", { enumerable: true, get: function () { return lower_ts_1.lower; } });
|
|
20
|
-
var minimize_ts_1 = require("./minimize.js");
|
|
21
|
-
Object.defineProperty(exports, "minimize", { enumerable: true, get: function () { return minimize_ts_1.minimize; } });
|
|
22
14
|
var scope_ts_1 = require("./scope.js");
|
|
23
15
|
Object.defineProperty(exports, "decideScope", { enumerable: true, get: function () { return scope_ts_1.decideScope; } });
|
|
24
16
|
Object.defineProperty(exports, "scopeToContextRuleType", { enumerable: true, get: function () { return scope_ts_1.scopeToContextRuleType; } });
|
|
25
|
-
var synthesize_from_mandate_ts_1 = require("./synthesize-from-mandate.js");
|
|
26
|
-
Object.defineProperty(exports, "synthesizeFromMandate", { enumerable: true, get: function () { return synthesize_from_mandate_ts_1.synthesizeFromMandate; } });
|
|
27
17
|
var synthesize_from_recording_ts_1 = require("./synthesize-from-recording.js");
|
|
28
18
|
Object.defineProperty(exports, "synthesizeFromRecording", { enumerable: true, get: function () { return synthesize_from_recording_ts_1.synthesizeFromRecording; } });
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RecordedTransaction } from '../types.ts';
|
|
2
2
|
import type { EvalContext } from './evaluate.ts';
|
|
3
3
|
export interface PermitContextResponses {
|
|
4
4
|
windowSeconds: number;
|
|
5
|
-
invocationLimit?: number;
|
|
6
5
|
limitAmount?: string;
|
|
7
6
|
validUntilLedger: number;
|
|
8
|
-
oraclePriceBound?: Array<{
|
|
9
|
-
asset: string;
|
|
10
|
-
operator: string;
|
|
11
|
-
value: string;
|
|
12
|
-
decimals: number;
|
|
13
|
-
}>;
|
|
14
7
|
}
|
|
15
|
-
export declare function buildPermitContext(tx: RecordedTransaction, responses: PermitContextResponses
|
|
8
|
+
export declare function buildPermitContext(tx: RecordedTransaction, responses: PermitContextResponses): EvalContext;
|