@crediolabs/policy-synth 0.1.13 → 0.1.15
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/dist/install/build-install-policy.d.ts +10 -12
- package/dist/install/build-install-policy.js +87 -60
- package/dist/install/build-install-predicate.d.ts +96 -0
- package/dist/install/build-install-predicate.js +444 -0
- package/dist/install/oz-auth.d.ts +27 -0
- package/dist/install/oz-auth.js +105 -0
- package/dist/run/index.d.ts +3 -3
- package/dist/run/index.js +3 -3
- package/dist-cjs/install/build-install-policy.d.ts +10 -12
- package/dist-cjs/install/build-install-policy.js +87 -60
- package/dist-cjs/install/build-install-predicate.d.ts +96 -0
- package/dist-cjs/install/build-install-predicate.js +479 -0
- package/dist-cjs/install/oz-auth.d.ts +27 -0
- package/dist-cjs/install/oz-auth.js +114 -0
- package/dist-cjs/run/index.d.ts +3 -3
- package/dist-cjs/run/index.js +3 -3
- package/package.json +1 -1
- package/src/install/build-install-policy.ts +155 -96
- package/src/install/oz-auth.ts +140 -0
- package/src/run/index.ts +3 -3
|
@@ -147,22 +147,20 @@ export interface BuildInstallPolicyResult {
|
|
|
147
147
|
smartAccount: string;
|
|
148
148
|
/** Source account (echo) - the address that must sign. */
|
|
149
149
|
sourceAccount: string;
|
|
150
|
-
/** The host-call target + fn name.
|
|
151
|
-
*
|
|
152
|
-
*
|
|
150
|
+
/** The host-call target + fn name. This single call installs the policy
|
|
151
|
+
* outright: `add_context_rule` takes `policies` as a
|
|
152
|
+
* `Map<policy_address, install_param>`, and the account forwards each
|
|
153
|
+
* install_param to that policy. For an interpreter policy the param
|
|
154
|
+
* carries the predicate and its hash, so the interpreter stores the
|
|
155
|
+
* document as part of this transaction. There is no second call.
|
|
156
|
+
*
|
|
157
|
+
* Verified on testnet 2026-08-01: a rule created by this builder alone
|
|
158
|
+
* permits a matching operator call and denies a non-matching one with
|
|
159
|
+
* interpreter code #100 - not #206 MissingState. */
|
|
153
160
|
call: {
|
|
154
161
|
contract: string;
|
|
155
162
|
fn: 'add_context_rule';
|
|
156
163
|
};
|
|
157
|
-
/** The follow-up call the caller MUST issue after this one confirms.
|
|
158
|
-
* The rule id the account assigns in call 1 is required to bind the
|
|
159
|
-
* interpreter's `install` auth context. */
|
|
160
|
-
followUp: {
|
|
161
|
-
contract: 'interpreter';
|
|
162
|
-
fn: 'install';
|
|
163
|
-
requiresRuleIdFromCallOne: true;
|
|
164
|
-
hint: string;
|
|
165
|
-
};
|
|
166
164
|
/** Human-readable description of the install call, decoded FROM the
|
|
167
165
|
* built unsigned XDR (not from the input args). The wallet signature
|
|
168
166
|
* binds to bytes; the review card has to bind to the same bytes, so
|
|
@@ -13,12 +13,16 @@
|
|
|
13
13
|
// (b) key material the server does not have, so we ship the simpler ONE-CALL
|
|
14
14
|
// shape. The wallet signature covers the change.
|
|
15
15
|
//
|
|
16
|
-
// `buildInstallPolicyXdr`
|
|
17
|
-
//
|
|
18
|
-
//
|
|
16
|
+
// `buildInstallPolicyXdr` installs the policy in ONE call. `add_context_rule`
|
|
17
|
+
// takes `policies` as a `Map<policy_address, install_param>` and the account
|
|
18
|
+
// forwards each install_param to that policy, so the interpreter stores the
|
|
19
|
+
// predicate document as part of this same transaction. Earlier revisions
|
|
20
|
+
// documented a second `interpreter.install` call; that was wrong, and issuing
|
|
21
|
+
// it fails - the account re-enters the interpreter while it is mid-install.
|
|
19
22
|
import { createHash } from 'node:crypto';
|
|
20
23
|
import { Address, BASE_FEE, Contract, Keypair, Operation, rpc, scValToBigInt, TransactionBuilder, xdr, } from '@stellar/stellar-sdk';
|
|
21
24
|
import { buildAddContextRuleArgs, DEFAULT_GRAMMAR_VERSION } from "./build-add-context-rule.js";
|
|
25
|
+
import { accountEntry, authDigest, authPayload, delegatedSignerEntry, signaturePayload, } from "./oz-auth.js";
|
|
22
26
|
/** Convert a real rpc.Server into the InstallRpcClient surface. The
|
|
23
27
|
* `getContractVersion` lookup uses `simulateTransaction` against
|
|
24
28
|
* `contract.call('grammar_version')` and decodes the returned u32.
|
|
@@ -62,7 +66,6 @@ export function rpcClientFromServer(server, networkPassphrase) {
|
|
|
62
66
|
},
|
|
63
67
|
};
|
|
64
68
|
}
|
|
65
|
-
const FOLLOWUP_HINT = 'after this tx confirms, read the rule id via account.get_context_rules_count()-1 (or get the receipt events), then call runInstallPolicy a second time with the interpreter as the target and the rule id in context_rule_ids - OR hand-build the install() call directly with the OZ auth pattern.';
|
|
66
69
|
/** Build the unsigned transaction envelope for `account.add_context_rule(...)`.
|
|
67
70
|
* The output XDR is signed by the wallet, not by us. */
|
|
68
71
|
export async function buildInstallPolicyXdr(args) {
|
|
@@ -83,31 +86,28 @@ export async function buildInstallPolicyXdr(args) {
|
|
|
83
86
|
...(args.oracleParams ? { oracleParams: args.oracleParams } : {}),
|
|
84
87
|
...(args.grammarVersion !== undefined ? { grammarVersion: args.grammarVersion } : {}),
|
|
85
88
|
});
|
|
86
|
-
// 2.
|
|
89
|
+
// 2. Fetch the source sequence, then build the recording transaction with a
|
|
90
|
+
// bare host call. The recording pass assigns the smart-account auth nonce
|
|
91
|
+
// and root invocation needed to construct OZ's AuthPayload.
|
|
87
92
|
const source = await args.rpc.getAccount(args.sourceAccount);
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
functionName: 'add_context_rule',
|
|
95
|
-
args: [...callArgs],
|
|
96
|
-
})),
|
|
97
|
-
auth: [],
|
|
98
|
-
});
|
|
93
|
+
const hostFunction = xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
|
|
94
|
+
contractAddress: new Address(args.smartAccount).toScAddress(),
|
|
95
|
+
functionName: 'add_context_rule',
|
|
96
|
+
args: [...callArgs],
|
|
97
|
+
}));
|
|
98
|
+
const makeOperation = (auth = []) => Operation.invokeHostFunction({ func: hostFunction, auth });
|
|
99
99
|
const baseFee = args.baseFee !== undefined ? String(args.baseFee) : BASE_FEE;
|
|
100
|
-
const
|
|
100
|
+
const buildTx = (op) => buildUnsignedTx({
|
|
101
101
|
sourceAccount: args.sourceAccount,
|
|
102
102
|
sequence: source.sequenceNumber(),
|
|
103
103
|
fee: baseFee,
|
|
104
104
|
networkPassphrase: args.networkPassphrase,
|
|
105
105
|
op,
|
|
106
106
|
});
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
const recorded = await args.rpc.simulateTransaction(
|
|
107
|
+
const recordingTx = buildTx(makeOperation());
|
|
108
|
+
// 3. Recording simulation: capture the smart account's nonce and invocation
|
|
109
|
+
// tree. Nothing is signed here.
|
|
110
|
+
const recorded = await args.rpc.simulateTransaction(recordingTx);
|
|
111
111
|
if (rpc.Api.isSimulationError(recorded)) {
|
|
112
112
|
// Short, stable reason. The full `simulateTransaction` error (which
|
|
113
113
|
// carries host + URL detail) stays in the SDK's own logs - never
|
|
@@ -121,23 +121,35 @@ export async function buildInstallPolicyXdr(args) {
|
|
|
121
121
|
if (!original) {
|
|
122
122
|
throw new Error(`install_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
|
|
123
123
|
}
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
// 4. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
|
|
125
|
+
// The delegated signer uses source-account credentials, so its signature
|
|
126
|
+
// bytes stay empty and the ordinary transaction-envelope signature covers
|
|
127
|
+
// the call when the consumer signs it.
|
|
128
|
+
const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
|
|
129
|
+
(args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
|
|
130
|
+
const contextRuleIds = [0];
|
|
131
|
+
const digest = authDigest(signaturePayload(args.networkPassphrase, original.credentials().address().nonce(), validUntilLedger, original.rootInvocation()), contextRuleIds);
|
|
132
|
+
const authEntries = [
|
|
133
|
+
accountEntry(original, validUntilLedger, authPayload([args.sourceAccount], contextRuleIds, () => Buffer.alloc(0))),
|
|
134
|
+
...contextRuleIds.map(() => delegatedSignerEntry(args.smartAccount, digest)),
|
|
135
|
+
];
|
|
136
|
+
// 5. Simulate again with the OZ entries already attached. The SDK preserves
|
|
137
|
+
// existing auth during assembly and adds the simulated Soroban footprint +
|
|
138
|
+
// resource fee, yielding a complete unsigned envelope.
|
|
139
|
+
const txWithAuth = buildTx(makeOperation(authEntries));
|
|
140
|
+
const enforcing = await args.rpc.simulateTransaction(txWithAuth);
|
|
141
|
+
if (rpc.Api.isSimulationError(enforcing)) {
|
|
142
|
+
throw new Error('install_policy: auth simulateTransaction failed');
|
|
143
|
+
}
|
|
144
|
+
const finalTx = rpc.assembleTransaction(txWithAuth, enforcing).build();
|
|
145
|
+
// 6. Decode the structured description FROM the final assembled transaction.
|
|
146
|
+
// The human approval binds to the exact bytes the wallet will sign.
|
|
147
|
+
const describes = decodeInstallCallDescribes(finalTx, args.installNonce);
|
|
130
148
|
return {
|
|
131
|
-
unsignedXdr:
|
|
149
|
+
unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
|
|
132
150
|
smartAccount: args.smartAccount,
|
|
133
151
|
sourceAccount: args.sourceAccount,
|
|
134
152
|
call: { contract: args.smartAccount, fn: 'add_context_rule' },
|
|
135
|
-
followUp: {
|
|
136
|
-
contract: 'interpreter',
|
|
137
|
-
fn: 'install',
|
|
138
|
-
requiresRuleIdFromCallOne: true,
|
|
139
|
-
hint: FOLLOWUP_HINT,
|
|
140
|
-
},
|
|
141
153
|
describes,
|
|
142
154
|
authNonce: original.credentials().address().nonce().toString(),
|
|
143
155
|
authValidUntilLedger: validUntilLedger,
|
|
@@ -157,25 +169,21 @@ export async function buildInstallPolicyXdr(args) {
|
|
|
157
169
|
* be guessing at a contract it cannot read, and the chain is the authority. */
|
|
158
170
|
export async function buildRevokePolicyXdr(args) {
|
|
159
171
|
const source = await args.rpc.getAccount(args.sourceAccount);
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
args: [xdr.ScVal.scvU32(args.ruleId)],
|
|
167
|
-
})),
|
|
168
|
-
auth: [],
|
|
169
|
-
});
|
|
172
|
+
const hostFunction = xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
|
|
173
|
+
contractAddress: new Address(args.smartAccount).toScAddress(),
|
|
174
|
+
functionName: 'remove_context_rule',
|
|
175
|
+
args: [xdr.ScVal.scvU32(args.ruleId)],
|
|
176
|
+
}));
|
|
177
|
+
const makeOperation = (auth = []) => Operation.invokeHostFunction({ func: hostFunction, auth });
|
|
170
178
|
const baseFee = args.baseFee !== undefined ? String(args.baseFee) : BASE_FEE;
|
|
171
|
-
const
|
|
179
|
+
const buildTx = (op) => buildUnsignedTx({
|
|
172
180
|
sourceAccount: args.sourceAccount,
|
|
173
181
|
sequence: source.sequenceNumber(),
|
|
174
182
|
fee: baseFee,
|
|
175
183
|
networkPassphrase: args.networkPassphrase,
|
|
176
184
|
op,
|
|
177
185
|
});
|
|
178
|
-
const recorded = await args.rpc.simulateTransaction(
|
|
186
|
+
const recorded = await args.rpc.simulateTransaction(buildTx(makeOperation()));
|
|
179
187
|
if (rpc.Api.isSimulationError(recorded)) {
|
|
180
188
|
// Short, stable reason. The full `simulateTransaction` error (which
|
|
181
189
|
// carries host + URL detail) stays in the SDK's own logs - never
|
|
@@ -189,8 +197,27 @@ export async function buildRevokePolicyXdr(args) {
|
|
|
189
197
|
if (!original) {
|
|
190
198
|
throw new Error(`revoke_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
|
|
191
199
|
}
|
|
200
|
+
// Removal is master-only, so the deploy-time admin rule authorises it. The
|
|
201
|
+
// recorded rootInvocation still includes remove_context_rule(ruleId), binding
|
|
202
|
+
// the auth payload to the exact rule being removed. As with install,
|
|
203
|
+
// source-account credentials carry the delegated signer entry and the
|
|
204
|
+
// consumer supplies only the ordinary envelope signature.
|
|
205
|
+
const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
|
|
206
|
+
(args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
|
|
207
|
+
const contextRuleIds = [0];
|
|
208
|
+
const digest = authDigest(signaturePayload(args.networkPassphrase, original.credentials().address().nonce(), validUntilLedger, original.rootInvocation()), contextRuleIds);
|
|
209
|
+
const authEntries = [
|
|
210
|
+
accountEntry(original, validUntilLedger, authPayload([args.sourceAccount], contextRuleIds, () => Buffer.alloc(0))),
|
|
211
|
+
...contextRuleIds.map(() => delegatedSignerEntry(args.smartAccount, digest)),
|
|
212
|
+
];
|
|
213
|
+
const txWithAuth = buildTx(makeOperation(authEntries));
|
|
214
|
+
const enforcing = await args.rpc.simulateTransaction(txWithAuth);
|
|
215
|
+
if (rpc.Api.isSimulationError(enforcing)) {
|
|
216
|
+
throw new Error('revoke_policy: auth simulateTransaction failed');
|
|
217
|
+
}
|
|
218
|
+
const finalTx = rpc.assembleTransaction(txWithAuth, enforcing).build();
|
|
192
219
|
return {
|
|
193
|
-
unsignedXdr:
|
|
220
|
+
unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
|
|
194
221
|
smartAccount: args.smartAccount,
|
|
195
222
|
sourceAccount: args.sourceAccount,
|
|
196
223
|
call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
|
|
@@ -200,7 +227,7 @@ export async function buildRevokePolicyXdr(args) {
|
|
|
200
227
|
};
|
|
201
228
|
}
|
|
202
229
|
/** ~25 minutes at 5s/ledger. */
|
|
203
|
-
const
|
|
230
|
+
const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
|
|
204
231
|
// ---- internals ----
|
|
205
232
|
/** Adapter: turn the install-policy wire `PolicyRef` shape into the core
|
|
206
233
|
* `PolicyRef` shape `buildAddContextRuleArgs` expects. Keeps the wire
|
|
@@ -238,20 +265,24 @@ function buildUnsignedTx(args) {
|
|
|
238
265
|
// its signature, and broadcasts. We do NOT sign here.
|
|
239
266
|
return tx;
|
|
240
267
|
}
|
|
241
|
-
/** Decode the install call's structured fields directly out of the
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* will
|
|
245
|
-
*
|
|
246
|
-
* a ToolError, since that would mean the XDR was tampered with (or
|
|
268
|
+
/** Decode the install call's structured fields directly out of the final
|
|
269
|
+
* assembled transaction. The bytes are the source of truth: a human reviewing
|
|
270
|
+
* the install wants to see what the wallet will actually sign, not what we
|
|
271
|
+
* think it will. The decode is deliberately strict - any shape we did not
|
|
272
|
+
* build ourselves throws, since that would mean the XDR was tampered with (or
|
|
247
273
|
* the encoder changed and this descriptor lags).
|
|
248
274
|
*
|
|
249
275
|
* `expectedInstallNonce` is a fallback for the rare case where the
|
|
250
276
|
* install has no interpreter policy (no `install_nonce` to read); the
|
|
251
277
|
* caller already knows it. */
|
|
252
|
-
function decodeInstallCallDescribes(tx,
|
|
278
|
+
function decodeInstallCallDescribes(tx, expectedInstallNonce) {
|
|
279
|
+
const operations = tx.toEnvelope().v1().tx().operations();
|
|
280
|
+
if (operations.length !== 1 || !operations[0]) {
|
|
281
|
+
throw new Error(`install_policy: final transaction has ${operations.length} operations, expected 1`);
|
|
282
|
+
}
|
|
283
|
+
const op = operations[0];
|
|
253
284
|
const hostFn = op.body().invokeHostFunctionOp()?.hostFunction();
|
|
254
|
-
if (
|
|
285
|
+
if (hostFn?.switch().name !== 'hostFunctionTypeInvokeContract') {
|
|
255
286
|
throw new Error('install_policy: built op is not an invokeHostFunction(invokeContract(...)) call');
|
|
256
287
|
}
|
|
257
288
|
const invokeArgs = hostFn.invokeContract();
|
|
@@ -404,10 +435,6 @@ function decodeInstallCallDescribes(tx, op, expectedInstallNonce) {
|
|
|
404
435
|
// `observedInstallNonce` is the nonce baked into whichever interpreter
|
|
405
436
|
// policy is present; when none, fall back to the caller-supplied value.
|
|
406
437
|
const installNonce = observedInstallNonce ?? expectedInstallNonce;
|
|
407
|
-
// Touch `tx` so the linter does not flag it as unused - the parameter
|
|
408
|
-
// documents that the caller built this Transaction; we re-parse the
|
|
409
|
-
// operation off it as a sanity check.
|
|
410
|
-
void tx;
|
|
411
438
|
return {
|
|
412
439
|
targetContract,
|
|
413
440
|
fnName: 'add_context_rule',
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Contract } from '@stellar/stellar-sdk';
|
|
2
|
+
import type { InstallRpcClient } from './build-install-policy.ts';
|
|
3
|
+
/** Inputs for the install-predicate build. */
|
|
4
|
+
export interface BuildInstallPredicateArgs {
|
|
5
|
+
/** The smart account contract address (C...). The interpreter hashes
|
|
6
|
+
* this rule's `signers` at install; we fetch it via `get_context_rule`
|
|
7
|
+
* on this address, not reconstruct it. */
|
|
8
|
+
smartAccount: string;
|
|
9
|
+
/** The signer that authorises the install (G... wallet). */
|
|
10
|
+
sourceAccount: string;
|
|
11
|
+
/** The rule id the account assigned in call 1. */
|
|
12
|
+
ruleId: number;
|
|
13
|
+
/** The interpreter contract address (C...). */
|
|
14
|
+
interpreterAddress: string;
|
|
15
|
+
/** Network passphrase - pins the hash the auth digest binds. */
|
|
16
|
+
networkPassphrase: string;
|
|
17
|
+
/** Already-encoded (base64) canonical ScVal of the predicate. */
|
|
18
|
+
encodedPredicate: string;
|
|
19
|
+
/** Hex sha256 of the canonical predicate XDR bytes. */
|
|
20
|
+
predicateHash: string;
|
|
21
|
+
/** Grammar version override; defaults to 1. */
|
|
22
|
+
grammarVersion?: number;
|
|
23
|
+
/** Base fee in stroops; defaults to BASE_FEE (100). */
|
|
24
|
+
baseFee?: number;
|
|
25
|
+
/** RPC client to use for the simulation pass; injected for tests. */
|
|
26
|
+
rpc: InstallRpcClient;
|
|
27
|
+
/** Ledger window (in ledgers) for the auth entry's `validUntil`. */
|
|
28
|
+
authValidUntilLedgers?: number;
|
|
29
|
+
}
|
|
30
|
+
/** Human-readable description of the install-predicate call, decoded FROM
|
|
31
|
+
* the built XDR (not from the input args). The wallet signature binds
|
|
32
|
+
* to bytes; the review card has to bind to the same bytes, so this is
|
|
33
|
+
* the only safe source.
|
|
34
|
+
*
|
|
35
|
+
* `ruleId` is NOT decoded from the XDR - it lives inside
|
|
36
|
+
* `raw_context_rule`, which is passed through verbatim. Decoding it
|
|
37
|
+
* here would re-introduce the client-side reconstruction the file
|
|
38
|
+
* header warns against. The top-level `BuildInstallPredicateResult`
|
|
39
|
+
* echoes the caller-supplied rule id instead. */
|
|
40
|
+
export interface InstallPredicateCallDescribes {
|
|
41
|
+
/** The interpreter that will hold the predicate. */
|
|
42
|
+
targetContract: string;
|
|
43
|
+
/** The fn name on the target (always `install` today). */
|
|
44
|
+
fnName: 'install';
|
|
45
|
+
/** Grammar version the interpreter enforces; read off the wire. */
|
|
46
|
+
grammarVersion: number;
|
|
47
|
+
/** Per-rule install nonce; read off the wire. */
|
|
48
|
+
installNonce: number;
|
|
49
|
+
/** Hex sha256 of the encoded predicate blob; read off the wire. */
|
|
50
|
+
predicateHash: string;
|
|
51
|
+
/** Hex sha256 of the predicate bytes embedded in the params map. The
|
|
52
|
+
* two values MUST match; a difference is a wire tampering signal. */
|
|
53
|
+
predicateSha256OfEmbeddedBytes: string;
|
|
54
|
+
/** The smart account address encoded in args[2], read off the wire. */
|
|
55
|
+
smartAccountOnWire: string;
|
|
56
|
+
}
|
|
57
|
+
/** Output of the install-predicate build. The unsigned XDR is the
|
|
58
|
+
* wallet's input; the wallet signs it (single envelope signature) and
|
|
59
|
+
* submits. The auth tree matches install_policy: account entry
|
|
60
|
+
* carrying OZ's AuthPayload + a source-account delegated signer entry.
|
|
61
|
+
* Both are covered by the envelope signature. */
|
|
62
|
+
export interface BuildInstallPredicateResult {
|
|
63
|
+
/** Unsigned Soroban transaction envelope, base64 XDR. */
|
|
64
|
+
unsignedXdr: string;
|
|
65
|
+
/** Smart account contract address (echo). */
|
|
66
|
+
smartAccount: string;
|
|
67
|
+
/** Source account (echo) - the address that signs the envelope. */
|
|
68
|
+
sourceAccount: string;
|
|
69
|
+
/** The interpreter contract address (echo). */
|
|
70
|
+
interpreterAddress: string;
|
|
71
|
+
/** The rule id the account assigned in call 1 (echo). */
|
|
72
|
+
ruleId: number;
|
|
73
|
+
/** The host-call target + fn name. */
|
|
74
|
+
call: {
|
|
75
|
+
contract: string;
|
|
76
|
+
fn: 'install';
|
|
77
|
+
};
|
|
78
|
+
/** The smart-account auth nonce (snapshot). */
|
|
79
|
+
authNonce: string;
|
|
80
|
+
/** The ledger sequence + window the auth entry expires at. */
|
|
81
|
+
authValidUntilLedger: number;
|
|
82
|
+
/** The captured rootInvocation for the smart-account entry. */
|
|
83
|
+
rootInvocationXdr: string;
|
|
84
|
+
/** Human-readable description of the install call, decoded FROM the
|
|
85
|
+
* built unsigned XDR (not from the input args). The wallet signature
|
|
86
|
+
* binds to bytes; the review card has to bind to the same bytes, so
|
|
87
|
+
* this is the only safe source. */
|
|
88
|
+
describes: InstallPredicateCallDescribes;
|
|
89
|
+
}
|
|
90
|
+
/** Build the unsigned transaction envelope for
|
|
91
|
+
* `interpreter.install(params, raw_context_rule, smart_account)`. The
|
|
92
|
+
* output XDR is signed by the wallet, not by us. */
|
|
93
|
+
export declare function buildInstallPredicateXdr(args: BuildInstallPredicateArgs): Promise<BuildInstallPredicateResult>;
|
|
94
|
+
/** Re-export `Contract` so the run-layer does not need to import the
|
|
95
|
+
* SDK directly. Mirrors the build-install-policy.ts convention. */
|
|
96
|
+
export { Contract };
|