@aura-protocol/cli 0.1.2 → 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 +84 -67
- package/bin/aura.js +0 -0
- package/dist/commands/confidential.d.ts +1 -1
- package/dist/commands/confidential.js +276 -597
- package/dist/commands/confidential.js.map +1 -1
- package/dist/commands/config.d.ts +1 -1
- package/dist/commands/config.js +26 -8
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dashboard.d.ts +1 -1
- package/dist/commands/dashboard.js +6 -7
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/dwallet.d.ts +1 -1
- package/dist/commands/dwallet.js +52 -41
- package/dist/commands/dwallet.js.map +1 -1
- package/dist/commands/execution.d.ts +1 -1
- package/dist/commands/execution.js +111 -175
- package/dist/commands/execution.js.map +1 -1
- package/dist/commands/features.d.ts +1 -1
- package/dist/commands/features.js +15 -10
- package/dist/commands/features.js.map +1 -1
- package/dist/commands/generated.d.ts +20 -0
- package/dist/commands/generated.js +61 -0
- package/dist/commands/generated.js.map +1 -0
- package/dist/commands/governance.d.ts +1 -1
- package/dist/commands/governance.js +113 -99
- package/dist/commands/governance.js.map +1 -1
- package/dist/commands/helpers.d.ts +5 -2
- package/dist/commands/helpers.js +79 -16
- package/dist/commands/helpers.js.map +1 -1
- package/dist/commands/instruction-exec.d.ts +27 -0
- package/dist/commands/instruction-exec.js +171 -0
- package/dist/commands/instruction-exec.js.map +1 -0
- package/dist/commands/instruction.d.ts +9 -0
- package/dist/commands/instruction.js +81 -0
- package/dist/commands/instruction.js.map +1 -0
- package/dist/commands/pda.d.ts +1 -1
- package/dist/commands/pda.js +15 -7
- package/dist/commands/pda.js.map +1 -1
- package/dist/commands/treasury.d.ts +1 -1
- package/dist/commands/treasury.js +201 -186
- package/dist/commands/treasury.js.map +1 -1
- package/dist/core/config.d.ts +35 -0
- package/dist/core/config.js +97 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +51 -0
- package/dist/core/context.js +60 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/errors.d.ts +38 -0
- package/dist/core/errors.js +138 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/network.d.ts +18 -0
- package/dist/core/network.js +38 -0
- package/dist/core/network.js.map +1 -0
- package/dist/core/runner.d.ts +45 -0
- package/dist/core/runner.js +219 -0
- package/dist/core/runner.js.map +1 -0
- package/dist/core/security.d.ts +28 -0
- package/dist/core/security.js +83 -0
- package/dist/core/security.js.map +1 -0
- package/dist/core/wallet.d.ts +2 -0
- package/dist/core/wallet.js +21 -0
- package/dist/core/wallet.js.map +1 -0
- package/dist/ika.d.ts +0 -9
- package/dist/ika.js +0 -48
- package/dist/ika.js.map +1 -1
- package/dist/index.js +56 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/domain.d.ts +16 -0
- package/dist/lib/domain.js +88 -0
- package/dist/lib/domain.js.map +1 -0
- package/dist/lib/ika.d.ts +81 -0
- package/dist/lib/ika.js +192 -0
- package/dist/lib/ika.js.map +1 -0
- package/dist/lib/instructions.d.ts +79 -0
- package/dist/lib/instructions.js +421 -0
- package/dist/lib/instructions.js.map +1 -0
- package/dist/lib/protocol.d.ts +99 -0
- package/dist/lib/protocol.js +327 -0
- package/dist/lib/protocol.js.map +1 -0
- package/dist/lib/treasury-view.d.ts +11 -0
- package/dist/lib/treasury-view.js +126 -0
- package/dist/lib/treasury-view.js.map +1 -0
- package/dist/output.js +0 -3
- package/dist/output.js.map +1 -1
- package/dist/program-instructions.d.ts +1 -1
- package/dist/protocol.d.ts +0 -1
- package/dist/protocol.js +0 -7
- package/dist/protocol.js.map +1 -1
- package/dist/treasury-view.js +1 -1
- package/dist/treasury-view.js.map +1 -1
- package/dist/ui/dashboard.d.ts +7 -0
- package/dist/ui/dashboard.js +99 -0
- package/dist/ui/dashboard.js.map +1 -0
- package/dist/ui/format.d.ts +9 -0
- package/dist/ui/format.js +92 -0
- package/dist/ui/format.js.map +1 -0
- package/dist/ui/output.d.ts +58 -0
- package/dist/ui/output.js +208 -0
- package/dist/ui/output.js.map +1 -0
- package/dist/ui/theme.d.ts +52 -0
- package/dist/ui/theme.js +110 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/vendor/encrypt/generated/grpc/encrypt_service.d.ts +1 -1
- package/dist/vendor/encrypt/generated/grpc/encrypt_service.js +36 -13
- package/dist/vendor/encrypt/generated/grpc/encrypt_service.js.map +1 -1
- package/dist/vendor/encrypt/grpc.d.ts +2 -2
- package/dist/vendor/encrypt/grpc.js +1 -3
- package/dist/vendor/encrypt/grpc.js.map +1 -1
- package/dist/vendor/ika/bcs-types.js +107 -50
- package/dist/vendor/ika/bcs-types.js.map +1 -1
- package/dist/vendor/ika/generated/grpc/ika_dwallet.d.ts +1 -1
- package/dist/vendor/ika/generated/grpc/ika_dwallet.js +14 -4
- package/dist/vendor/ika/generated/grpc/ika_dwallet.js.map +1 -1
- package/dist/vendor/ika/grpc.d.ts +1 -1
- package/dist/vendor/ika/grpc.js +49 -24
- package/dist/vendor/ika/grpc.js.map +1 -1
- package/package.json +16 -13
- package/dist/ascii.d.ts +0 -1
- package/dist/ascii.js +0 -2
- package/dist/ascii.js.map +0 -1
|
@@ -1,99 +1,69 @@
|
|
|
1
|
+
import { accounts, instructions } from "@aura-protocol/sdk-ts";
|
|
1
2
|
import { PublicKey, SystemProgram } from "@solana/web3.js";
|
|
2
3
|
import BN from "bn.js";
|
|
3
|
-
import {} from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { encryptU64, encryptU64Batch,
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { buildCliContext } from "../core/context.js";
|
|
5
|
+
import { CliError } from "../core/errors.js";
|
|
6
|
+
import { runInstructions } from "../core/runner.js";
|
|
7
|
+
import { loadKeypair } from "../core/wallet.js";
|
|
8
|
+
import { encryptU64, encryptU64Batch, readU64Ciphertext } from "../lib/ika.js";
|
|
9
|
+
import { buildDryRunKeypair, deriveEncryptAccounts, ensureEncryptDeposit, getActivePendingProposal, markInstructionSigner, resolvePendingPolicyOutput, resolvePendingRequestAccount, resolveScalarGuardrails, waitForCiphertextVerified, waitForDecryptionReady, } from "../lib/protocol.js";
|
|
10
|
+
import { renderTreasurySections } from "../lib/treasury-view.js";
|
|
11
|
+
import { emitJson, printBanner, printInfo, printNote, printSuccess, startSpinner, } from "../ui/output.js";
|
|
12
|
+
import { style } from "../ui/theme.js";
|
|
10
13
|
import { buildProposeConfidentialArgs, promptChain, promptNumber, promptString, promptTransactionType, resolveTreasuryAccount, } from "./helpers.js";
|
|
14
|
+
function requireWallet(ctx) {
|
|
15
|
+
if (!ctx.wallet) {
|
|
16
|
+
throw new CliError("A wallet is required for this command.", {
|
|
17
|
+
code: "WALLET_REQUIRED",
|
|
18
|
+
tip: "Run `aura config init` or pass --wallet <path>.",
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return ctx.wallet;
|
|
22
|
+
}
|
|
11
23
|
function parsePublicKey(value, label) {
|
|
12
24
|
try {
|
|
13
25
|
return new PublicKey(value);
|
|
14
26
|
}
|
|
15
27
|
catch {
|
|
16
|
-
throw
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
function normalizeDigestHex(value, label) {
|
|
20
|
-
if (!value) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
if (!/^[0-9a-fA-F]{64}$/.test(value)) {
|
|
24
|
-
throw new Error(`${label} must be a 32-byte hex digest`);
|
|
28
|
+
throw CliError.invalidInput(label, "base58 public key");
|
|
25
29
|
}
|
|
26
|
-
return value.toLowerCase();
|
|
27
|
-
}
|
|
28
|
-
function normalizePublicKeyHex(value) {
|
|
29
|
-
if (!value) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
if (!/^[0-9a-fA-F]+$/.test(value) || value.length % 2 !== 0) {
|
|
33
|
-
throw new Error("publicKeyHex must contain valid hex bytes");
|
|
34
|
-
}
|
|
35
|
-
return value.toLowerCase();
|
|
36
|
-
}
|
|
37
|
-
const U64_MODULUS = 1n << 64n;
|
|
38
|
-
const U64_VECTOR_LANES = 1024;
|
|
39
|
-
const VECTOR_CIPHERTEXT_TIMEOUT_MS = 600_000;
|
|
40
|
-
function wrappingNegU64(value) {
|
|
41
|
-
const amount = BigInt(value);
|
|
42
|
-
return (U64_MODULUS - (amount % U64_MODULUS)) % U64_MODULUS;
|
|
43
|
-
}
|
|
44
|
-
function vectorFlagIndices() {
|
|
45
|
-
return Array.from({ length: U64_VECTOR_LANES }, (_, index) => {
|
|
46
|
-
if (index === 0)
|
|
47
|
-
return 3n;
|
|
48
|
-
if (index === 1)
|
|
49
|
-
return 4n;
|
|
50
|
-
return BigInt(Math.min(index + 3, U64_VECTOR_LANES - 1));
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
function parseOptionalPubkeyOption(options, name, label) {
|
|
54
|
-
return typeof options[name] === "string"
|
|
55
|
-
? parsePublicKey(options[name], label)
|
|
56
|
-
: null;
|
|
57
30
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (!ctx.wallet) {
|
|
61
|
-
throw new Error("A wallet is required for this command.");
|
|
62
|
-
}
|
|
63
|
-
return await sendInstructionsWithBudget({
|
|
64
|
-
connection: ctx.connection,
|
|
65
|
-
payer: ctx.wallet,
|
|
66
|
-
instructions: [instruction],
|
|
67
|
-
extraSigners,
|
|
68
|
-
});
|
|
31
|
+
function nowBn() {
|
|
32
|
+
return new BN(Math.floor(Date.now() / 1000));
|
|
69
33
|
}
|
|
70
34
|
export function registerConfidentialCommands(program) {
|
|
71
35
|
const confidential = program
|
|
72
36
|
.command("confidential")
|
|
73
|
-
.description("Manage confidential guardrails and policy decryption");
|
|
74
|
-
|
|
37
|
+
.description("Manage confidential guardrails and the policy decryption flow");
|
|
38
|
+
// --- deposit ---------------------------------------------------------
|
|
39
|
+
const deposit = confidential
|
|
40
|
+
.command("deposit")
|
|
41
|
+
.description("Manage Encrypt deposit accounts");
|
|
75
42
|
deposit
|
|
76
43
|
.command("ensure")
|
|
77
44
|
.description("Ensure the configured wallet has an Encrypt deposit account")
|
|
78
45
|
.action(async function confidentialDepositEnsure() {
|
|
79
46
|
const ctx = buildCliContext(this);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
const dryRunAccounts = deriveEncryptAccounts(ctx.wallet.publicKey, {
|
|
47
|
+
const wallet = requireWallet(ctx);
|
|
48
|
+
const derived = deriveEncryptAccounts(wallet.publicKey, {
|
|
84
49
|
auraProgramId: ctx.programId,
|
|
85
50
|
});
|
|
86
51
|
if (ctx.dryRun) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
52
|
+
if (ctx.output.json) {
|
|
53
|
+
emitJson(ctx.output, {
|
|
54
|
+
action: "confidential.deposit.ensure",
|
|
55
|
+
accounts: derived,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
printNote(ctx.output, `Dry run: would ensure Encrypt deposit ${derived.deposit.toBase58()}`);
|
|
60
|
+
}
|
|
91
61
|
return;
|
|
92
62
|
}
|
|
93
63
|
const spinner = startSpinner(ctx.output, "Ensuring Encrypt deposit account...");
|
|
94
64
|
const result = await ensureEncryptDeposit({
|
|
95
65
|
connection: ctx.connection,
|
|
96
|
-
payer:
|
|
66
|
+
payer: wallet,
|
|
97
67
|
auraProgramId: ctx.programId,
|
|
98
68
|
});
|
|
99
69
|
spinner.succeed(result.created ? "Encrypt deposit created" : "Encrypt deposit ready");
|
|
@@ -101,61 +71,62 @@ export function registerConfidentialCommands(program) {
|
|
|
101
71
|
emitJson(ctx.output, result);
|
|
102
72
|
return;
|
|
103
73
|
}
|
|
104
|
-
printSuccess(ctx.output, result.created
|
|
105
|
-
? `Encrypt deposit created: ${result.accounts.deposit.toBase58()}`
|
|
106
|
-
: `Encrypt deposit ready: ${result.accounts.deposit.toBase58()}`);
|
|
74
|
+
printSuccess(ctx.output, `${result.created ? "Encrypt deposit created" : "Encrypt deposit ready"}: ${result.accounts.deposit.toBase58()}`);
|
|
107
75
|
});
|
|
76
|
+
// --- guardrails ------------------------------------------------------
|
|
108
77
|
const guardrails = confidential
|
|
109
78
|
.command("guardrails")
|
|
110
79
|
.description("Configure confidential guardrail ciphertexts");
|
|
111
80
|
guardrails
|
|
112
81
|
.command("scalar")
|
|
113
|
-
.description("Attach scalar guardrail ciphertext accounts")
|
|
82
|
+
.description("Attach scalar guardrail ciphertext accounts (auto-encrypts via Ika Encrypt)")
|
|
114
83
|
.option("--agent-id <id>", "treasury agent ID")
|
|
115
84
|
.option("--treasury <pda>", "treasury PDA")
|
|
116
|
-
.option("--daily-limit <usd>", "daily limit in USD
|
|
117
|
-
.option("--per-tx-limit <usd>", "per-transaction limit in USD
|
|
118
|
-
.option("--spent-today <usd>", "current spent-today counter in USD (default
|
|
119
|
-
.option("--daily-limit-ciphertext <pubkey>", "use a pre-created daily limit ciphertext
|
|
120
|
-
.option("--per-tx-ciphertext <pubkey>", "use a pre-created per-tx limit ciphertext
|
|
121
|
-
.option("--spent-today-ciphertext <pubkey>", "use a pre-created spent-today ciphertext
|
|
85
|
+
.option("--daily-limit <usd>", "daily limit in USD", Number)
|
|
86
|
+
.option("--per-tx-limit <usd>", "per-transaction limit in USD", Number)
|
|
87
|
+
.option("--spent-today <usd>", "current spent-today counter in USD (default 0)", Number)
|
|
88
|
+
.option("--daily-limit-ciphertext <pubkey>", "use a pre-created daily limit ciphertext")
|
|
89
|
+
.option("--per-tx-ciphertext <pubkey>", "use a pre-created per-tx limit ciphertext")
|
|
90
|
+
.option("--spent-today-ciphertext <pubkey>", "use a pre-created spent-today ciphertext")
|
|
122
91
|
.action(async function confidentialGuardrailsScalar() {
|
|
123
92
|
const ctx = buildCliContext(this);
|
|
124
|
-
|
|
125
|
-
throw new Error("A wallet is required to configure guardrails.");
|
|
126
|
-
}
|
|
93
|
+
const wallet = requireWallet(ctx);
|
|
127
94
|
const options = this.opts();
|
|
128
95
|
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
129
|
-
agentId: typeof options
|
|
130
|
-
treasury: typeof options
|
|
96
|
+
agentId: typeof options.agentId === "string" ? options.agentId : undefined,
|
|
97
|
+
treasury: typeof options.treasury === "string" ? options.treasury : undefined,
|
|
131
98
|
});
|
|
132
|
-
const
|
|
99
|
+
const usingPreCreated = typeof options.dailyLimitCiphertext === "string" &&
|
|
100
|
+
typeof options.perTxCiphertext === "string" &&
|
|
101
|
+
typeof options.spentTodayCiphertext === "string";
|
|
133
102
|
let dailyLimitCiphertext;
|
|
134
103
|
let perTxLimitCiphertext;
|
|
135
104
|
let spentTodayCiphertext;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
typeof options["spentTodayCiphertext"] === "string") {
|
|
141
|
-
dailyLimitCiphertext = parsePublicKey(options["dailyLimitCiphertext"], "Daily limit ciphertext");
|
|
142
|
-
perTxLimitCiphertext = parsePublicKey(options["perTxCiphertext"], "Per-tx limit ciphertext");
|
|
143
|
-
spentTodayCiphertext = parsePublicKey(options["spentTodayCiphertext"], "Spent-today ciphertext");
|
|
105
|
+
if (usingPreCreated) {
|
|
106
|
+
dailyLimitCiphertext = parsePublicKey(options.dailyLimitCiphertext, "daily-limit-ciphertext");
|
|
107
|
+
perTxLimitCiphertext = parsePublicKey(options.perTxCiphertext, "per-tx-ciphertext");
|
|
108
|
+
spentTodayCiphertext = parsePublicKey(options.spentTodayCiphertext, "spent-today-ciphertext");
|
|
144
109
|
}
|
|
145
110
|
else {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
111
|
+
const dailyLimit = await promptNumber(typeof options.dailyLimit === "number"
|
|
112
|
+
? options.dailyLimit
|
|
113
|
+
: undefined, "Daily limit (USD)", {
|
|
114
|
+
validate: (v) => {
|
|
115
|
+
if (v <= 0)
|
|
116
|
+
throw new Error("Must be > 0");
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
const perTxLimit = await promptNumber(typeof options.perTxLimit === "number"
|
|
120
|
+
? options.perTxLimit
|
|
121
|
+
: undefined, "Per-transaction limit (USD)", {
|
|
122
|
+
validate: (v) => {
|
|
123
|
+
if (v <= 0)
|
|
124
|
+
throw new Error("Must be > 0");
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
const spentToday = typeof options.spentToday === "number" ? options.spentToday : 0;
|
|
152
128
|
if (ctx.dryRun) {
|
|
153
|
-
|
|
154
|
-
action: "confidential.guardrails.scalar",
|
|
155
|
-
treasury: treasuryState.treasury,
|
|
156
|
-
note: "dry-run: would encrypt dailyLimit, perTxLimit, spentToday via Ika Encrypt gRPC",
|
|
157
|
-
values: { dailyLimit, perTxLimit, spentToday },
|
|
158
|
-
});
|
|
129
|
+
printNote(ctx.output, `Dry run: would encrypt daily=$${dailyLimit}, per-tx=$${perTxLimit}, spent=$${spentToday} via Ika Encrypt, then configure scalar guardrails.`);
|
|
159
130
|
return;
|
|
160
131
|
}
|
|
161
132
|
const spinner = startSpinner(ctx.output, "Encrypting guardrail values via Ika Encrypt...");
|
|
@@ -166,111 +137,33 @@ export function registerConfidentialCommands(program) {
|
|
|
166
137
|
waitForCiphertextVerified(ctx.connection, perTx),
|
|
167
138
|
waitForCiphertextVerified(ctx.connection, spent),
|
|
168
139
|
]);
|
|
140
|
+
spinner.succeed("Ciphertexts verified");
|
|
169
141
|
dailyLimitCiphertext = daily;
|
|
170
142
|
perTxLimitCiphertext = perTx;
|
|
171
143
|
spentTodayCiphertext = spent;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
owner:
|
|
144
|
+
}
|
|
145
|
+
const instruction = await instructions.confidential.configureConfidentialGuardrails(ctx.client, {
|
|
146
|
+
accounts: {
|
|
147
|
+
owner: wallet.publicKey,
|
|
176
148
|
treasury: treasuryState.treasury,
|
|
177
149
|
dailyLimitCiphertext,
|
|
178
150
|
perTxLimitCiphertext,
|
|
179
151
|
spentTodayCiphertext,
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
perTxLimitCiphertext,
|
|
188
|
-
spentTodayCiphertext,
|
|
189
|
-
});
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
printSuccess(ctx.output, `Scalar guardrails configured: ${signature}`);
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
// Pre-created ciphertext path
|
|
196
|
-
const now = Math.floor(Date.now() / 1000);
|
|
197
|
-
if (ctx.dryRun) {
|
|
198
|
-
const instruction = await ctx.client.configureConfidentialGuardrailsInstruction({
|
|
199
|
-
owner: ctx.wallet.publicKey,
|
|
152
|
+
},
|
|
153
|
+
args: { now: nowBn() },
|
|
154
|
+
});
|
|
155
|
+
await runInstructions(ctx, [instruction], {
|
|
156
|
+
action: "Configure scalar guardrails",
|
|
157
|
+
instructionName: "configure_confidential_guardrails",
|
|
158
|
+
result: {
|
|
200
159
|
treasury: treasuryState.treasury,
|
|
201
160
|
dailyLimitCiphertext,
|
|
202
161
|
perTxLimitCiphertext,
|
|
203
162
|
spentTodayCiphertext,
|
|
204
|
-
},
|
|
205
|
-
emitJson(ctx.output, {
|
|
206
|
-
action: "confidential.guardrails.scalar",
|
|
207
|
-
treasury: treasuryState.treasury,
|
|
208
|
-
instruction: serializeInstruction(instruction),
|
|
209
|
-
});
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const spinner = startSpinner(ctx.output, "Configuring scalar guardrails...");
|
|
213
|
-
const signature = await ctx.client.configureConfidentialGuardrails(ctx.wallet, {
|
|
214
|
-
owner: ctx.wallet.publicKey,
|
|
215
|
-
treasury: treasuryState.treasury,
|
|
216
|
-
dailyLimitCiphertext,
|
|
217
|
-
perTxLimitCiphertext,
|
|
218
|
-
spentTodayCiphertext,
|
|
219
|
-
}, now);
|
|
220
|
-
spinner.succeed("Scalar guardrails configured");
|
|
221
|
-
if (ctx.output.json) {
|
|
222
|
-
emitJson(ctx.output, { treasury: treasuryState.treasury, signature });
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
printSuccess(ctx.output, `Scalar guardrails configured: ${signature}`);
|
|
226
|
-
});
|
|
227
|
-
guardrails
|
|
228
|
-
.command("vector")
|
|
229
|
-
.description("Attach a vector guardrail ciphertext account")
|
|
230
|
-
.option("--agent-id <id>", "treasury agent ID")
|
|
231
|
-
.option("--treasury <pda>", "treasury PDA")
|
|
232
|
-
.option("--guardrail-ciphertext <pubkey>", "guardrail vector ciphertext account")
|
|
233
|
-
.action(async function confidentialGuardrailsVector() {
|
|
234
|
-
const ctx = buildCliContext(this);
|
|
235
|
-
if (!ctx.wallet) {
|
|
236
|
-
throw new Error("A wallet is required to configure vector guardrails.");
|
|
237
|
-
}
|
|
238
|
-
const options = this.opts();
|
|
239
|
-
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
240
|
-
agentId: typeof options["agentId"] === "string" ? options["agentId"] : undefined,
|
|
241
|
-
treasury: typeof options["treasury"] === "string" ? options["treasury"] : undefined,
|
|
163
|
+
},
|
|
242
164
|
});
|
|
243
|
-
const existing = treasuryState.account.confidentialGuardrails?.guardrailVectorCiphertext;
|
|
244
|
-
const guardrailVectorCiphertext = parsePublicKey(await promptString(typeof options["guardrailCiphertext"] === "string"
|
|
245
|
-
? options["guardrailCiphertext"]
|
|
246
|
-
: existing?.toBase58(), "Guardrail vector ciphertext"), "Guardrail vector ciphertext");
|
|
247
|
-
const now = Math.floor(Date.now() / 1000);
|
|
248
|
-
if (ctx.dryRun) {
|
|
249
|
-
const instruction = await ctx.client.configureConfidentialVectorGuardrailsInstruction({
|
|
250
|
-
owner: ctx.wallet.publicKey,
|
|
251
|
-
treasury: treasuryState.treasury,
|
|
252
|
-
guardrailVectorCiphertext,
|
|
253
|
-
}, now);
|
|
254
|
-
emitJson(ctx.output, {
|
|
255
|
-
action: "confidential.guardrails.vector",
|
|
256
|
-
treasury: treasuryState.treasury,
|
|
257
|
-
instruction: serializeInstruction(instruction),
|
|
258
|
-
});
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
const spinner = startSpinner(ctx.output, "Configuring vector guardrails...");
|
|
262
|
-
const signature = await ctx.client.configureConfidentialVectorGuardrails(ctx.wallet, {
|
|
263
|
-
owner: ctx.wallet.publicKey,
|
|
264
|
-
treasury: treasuryState.treasury,
|
|
265
|
-
guardrailVectorCiphertext,
|
|
266
|
-
}, now);
|
|
267
|
-
spinner.succeed("Vector guardrails configured");
|
|
268
|
-
if (ctx.output.json) {
|
|
269
|
-
emitJson(ctx.output, { treasury: treasuryState.treasury, signature });
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
printSuccess(ctx.output, `Vector guardrails configured: ${signature}`);
|
|
273
165
|
});
|
|
166
|
+
// --- status ----------------------------------------------------------
|
|
274
167
|
confidential
|
|
275
168
|
.command("status")
|
|
276
169
|
.description("Show confidential guardrails and pending confidential state")
|
|
@@ -280,8 +173,8 @@ export function registerConfidentialCommands(program) {
|
|
|
280
173
|
const ctx = buildCliContext(this);
|
|
281
174
|
const options = this.opts();
|
|
282
175
|
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
283
|
-
agentId: typeof options
|
|
284
|
-
treasury: typeof options
|
|
176
|
+
agentId: typeof options.agentId === "string" ? options.agentId : undefined,
|
|
177
|
+
treasury: typeof options.treasury === "string" ? options.treasury : undefined,
|
|
285
178
|
});
|
|
286
179
|
const sections = renderTreasurySections(treasuryState.treasury, treasuryState.account);
|
|
287
180
|
if (ctx.output.json) {
|
|
@@ -293,17 +186,14 @@ export function registerConfidentialCommands(program) {
|
|
|
293
186
|
return;
|
|
294
187
|
}
|
|
295
188
|
printBanner(ctx.output, `Confidential: ${treasuryState.account.agentId}`);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
console.log("No confidential guardrails configured.");
|
|
301
|
-
}
|
|
189
|
+
console.log(sections.confidential ??
|
|
190
|
+
style.muted("No confidential guardrails configured."));
|
|
302
191
|
if (sections.pending) {
|
|
303
192
|
console.log("");
|
|
304
193
|
console.log(sections.pending);
|
|
305
194
|
}
|
|
306
195
|
});
|
|
196
|
+
// --- propose ---------------------------------------------------------
|
|
307
197
|
confidential
|
|
308
198
|
.command("propose")
|
|
309
199
|
.description("Propose a confidential scalar transaction")
|
|
@@ -318,404 +208,214 @@ export function registerConfidentialCommands(program) {
|
|
|
318
208
|
.option("--actual-output <usd>", "actual output in USD", Number)
|
|
319
209
|
.option("--quote-age <secs>", "quote age in seconds", Number)
|
|
320
210
|
.option("--counterparty-risk <score>", "counterparty risk score", Number)
|
|
321
|
-
.option("--amount-ciphertext <pubkey>", "use a pre-created verified Encrypt ciphertext
|
|
322
|
-
.option("--policy-output-keypair <path>", "
|
|
211
|
+
.option("--amount-ciphertext <pubkey>", "use a pre-created verified Encrypt ciphertext")
|
|
212
|
+
.option("--policy-output-keypair <path>", "keypair path for the output ciphertext account")
|
|
323
213
|
.option("--wait", "wait until the policy output ciphertext is verified")
|
|
324
214
|
.action(async function confidentialPropose() {
|
|
325
215
|
const ctx = buildCliContext(this);
|
|
326
|
-
|
|
327
|
-
throw new Error("A wallet is required to submit a confidential proposal.");
|
|
328
|
-
}
|
|
216
|
+
const wallet = requireWallet(ctx);
|
|
329
217
|
const options = this.opts();
|
|
330
218
|
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
331
|
-
agentId: typeof options
|
|
332
|
-
treasury: typeof options
|
|
219
|
+
agentId: typeof options.agentId === "string" ? options.agentId : undefined,
|
|
220
|
+
treasury: typeof options.treasury === "string" ? options.treasury : undefined,
|
|
333
221
|
});
|
|
334
222
|
const guardrails = resolveScalarGuardrails(treasuryState.account);
|
|
335
|
-
const amountUsd = await promptNumber(typeof options
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
223
|
+
const amountUsd = await promptNumber(typeof options.amount === "number" ? options.amount : undefined, "Amount (USD)", {
|
|
224
|
+
validate: (v) => {
|
|
225
|
+
if (v <= 0)
|
|
226
|
+
throw new Error("Amount must be > 0");
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
const chain = await promptChain(typeof options.chain === "string" || typeof options.chain === "number"
|
|
230
|
+
? options.chain
|
|
339
231
|
: undefined, "Chain");
|
|
340
|
-
const recipient = await promptString(typeof options
|
|
341
|
-
const txType = await promptTransactionType(typeof options
|
|
342
|
-
? options
|
|
232
|
+
const recipient = await promptString(typeof options.recipient === "string" ? options.recipient : undefined, "Recipient");
|
|
233
|
+
const txType = await promptTransactionType(typeof options.txType === "string" || typeof options.txType === "number"
|
|
234
|
+
? options.txType
|
|
343
235
|
: undefined, "Transaction type");
|
|
344
236
|
const args = buildProposeConfidentialArgs({
|
|
345
237
|
amountUsd,
|
|
346
238
|
chain,
|
|
347
239
|
txType,
|
|
348
240
|
recipient,
|
|
349
|
-
protocolId: typeof options
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
241
|
+
protocolId: typeof options.protocolId === "number"
|
|
242
|
+
? options.protocolId
|
|
243
|
+
: undefined,
|
|
244
|
+
expectedOutputUsd: typeof options.expectedOutput === "number"
|
|
245
|
+
? options.expectedOutput
|
|
246
|
+
: undefined,
|
|
247
|
+
actualOutputUsd: typeof options.actualOutput === "number"
|
|
248
|
+
? options.actualOutput
|
|
249
|
+
: undefined,
|
|
250
|
+
quoteAgeSecs: typeof options.quoteAge === "number" ? options.quoteAge : undefined,
|
|
251
|
+
counterpartyRiskScore: typeof options.counterpartyRisk === "number"
|
|
252
|
+
? options.counterpartyRisk
|
|
355
253
|
: undefined,
|
|
356
|
-
});
|
|
357
|
-
const policyOutputSigner = buildDryRunKeypair(typeof options["policyOutputKeypair"] === "string"
|
|
358
|
-
? options["policyOutputKeypair"]
|
|
359
|
-
: undefined, loadKeypair);
|
|
360
|
-
const encryptAccounts = deriveEncryptAccounts(ctx.wallet.publicKey, {
|
|
361
|
-
auraProgramId: ctx.programId,
|
|
362
254
|
});
|
|
363
255
|
if (ctx.dryRun) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
: "would auto-encrypt amount via Ika Encrypt gRPC",
|
|
373
|
-
});
|
|
256
|
+
printNote(ctx.output, "Dry run: would ensure an Encrypt deposit, encrypt the amount via Ika, then submit propose_confidential_transaction.");
|
|
257
|
+
if (ctx.output.json) {
|
|
258
|
+
emitJson(ctx.output, {
|
|
259
|
+
action: "confidential.propose",
|
|
260
|
+
treasury: treasuryState.treasury,
|
|
261
|
+
args,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
374
264
|
return;
|
|
375
265
|
}
|
|
266
|
+
const policyOutputSigner = buildDryRunKeypair(typeof options.policyOutputKeypair === "string"
|
|
267
|
+
? options.policyOutputKeypair
|
|
268
|
+
: undefined, loadKeypair);
|
|
269
|
+
const encryptAccounts = deriveEncryptAccounts(wallet.publicKey, {
|
|
270
|
+
auraProgramId: ctx.programId,
|
|
271
|
+
});
|
|
376
272
|
const spinner = startSpinner(ctx.output, "Ensuring Encrypt deposit account...");
|
|
377
273
|
await ensureEncryptDeposit({
|
|
378
274
|
connection: ctx.connection,
|
|
379
|
-
payer:
|
|
275
|
+
payer: wallet,
|
|
380
276
|
auraProgramId: ctx.programId,
|
|
381
277
|
});
|
|
382
|
-
// Resolve the amount ciphertext — auto-encrypt if not provided
|
|
383
278
|
let amountCiphertext;
|
|
384
|
-
if (typeof options
|
|
385
|
-
amountCiphertext = parsePublicKey(options
|
|
279
|
+
if (typeof options.amountCiphertext === "string") {
|
|
280
|
+
amountCiphertext = parsePublicKey(options.amountCiphertext, "amount-ciphertext");
|
|
386
281
|
}
|
|
387
282
|
else {
|
|
388
|
-
spinner.setText(`Encrypting amount (
|
|
283
|
+
spinner.setText(`Encrypting amount ($${amountUsd}) via Ika Encrypt...`);
|
|
389
284
|
amountCiphertext = await encryptU64(amountUsd, ctx.programId);
|
|
390
285
|
spinner.setText("Waiting for amount ciphertext to be verified on-chain...");
|
|
391
286
|
await waitForCiphertextVerified(ctx.connection, amountCiphertext);
|
|
392
287
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
perTxLimitCiphertext: guardrails.perTxLimitCiphertext,
|
|
398
|
-
spentTodayCiphertext: guardrails.spentTodayCiphertext,
|
|
399
|
-
amountCiphertext,
|
|
400
|
-
policyOutputCiphertext: policyOutputSigner.publicKey,
|
|
401
|
-
encryptProgram: encryptAccounts.encryptProgram,
|
|
402
|
-
config: encryptAccounts.config,
|
|
403
|
-
deposit: encryptAccounts.deposit,
|
|
404
|
-
callerProgram: ctx.programId,
|
|
405
|
-
cpiAuthority: encryptAccounts.cpiAuthority,
|
|
406
|
-
networkEncryptionKey: encryptAccounts.networkEncryptionKey,
|
|
407
|
-
eventAuthority: encryptAccounts.eventAuthority,
|
|
408
|
-
systemProgram: SystemProgram.programId,
|
|
409
|
-
}, args);
|
|
410
|
-
markInstructionSigner(instruction, policyOutputSigner.publicKey);
|
|
411
|
-
spinner.setText("Submitting confidential proposal...");
|
|
412
|
-
const signature = await sendPreparedInstruction({
|
|
413
|
-
ctx,
|
|
414
|
-
instruction,
|
|
415
|
-
extraSigners: [policyOutputSigner],
|
|
416
|
-
});
|
|
417
|
-
if (options["wait"] === true) {
|
|
418
|
-
spinner.setText("Waiting for output ciphertext verification...");
|
|
419
|
-
await waitForCiphertextVerified(ctx.connection, policyOutputSigner.publicKey);
|
|
420
|
-
}
|
|
421
|
-
spinner.succeed("Confidential proposal submitted");
|
|
422
|
-
if (ctx.output.json) {
|
|
423
|
-
emitJson(ctx.output, {
|
|
288
|
+
spinner.succeed("Amount ciphertext ready");
|
|
289
|
+
const instruction = await instructions.confidential.proposeConfidentialTransaction(ctx.client, {
|
|
290
|
+
accounts: {
|
|
291
|
+
aiAuthority: wallet.publicKey,
|
|
424
292
|
treasury: treasuryState.treasury,
|
|
425
|
-
|
|
293
|
+
dailyLimitCiphertext: guardrails.dailyLimitCiphertext,
|
|
294
|
+
perTxLimitCiphertext: guardrails.perTxLimitCiphertext,
|
|
295
|
+
spentTodayCiphertext: guardrails.spentTodayCiphertext,
|
|
426
296
|
amountCiphertext,
|
|
427
297
|
policyOutputCiphertext: policyOutputSigner.publicKey,
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
.option("--protocol-id <id>", "protocol ID", Number)
|
|
443
|
-
.option("--expected-output <usd>", "expected output in USD", Number)
|
|
444
|
-
.option("--actual-output <usd>", "actual output in USD", Number)
|
|
445
|
-
.option("--quote-age <secs>", "quote age in seconds", Number)
|
|
446
|
-
.option("--counterparty-risk <score>", "counterparty risk score", Number)
|
|
447
|
-
.option("--spend-delta-ciphertext <pubkey>", "pre-created vector ciphertext for [-amount mod u64, 0, amount]")
|
|
448
|
-
.option("--comparison-ciphertext <pubkey>", "pre-created vector ciphertext for [amount, amount]")
|
|
449
|
-
.option("--flag-indices-ciphertext <pubkey>", "pre-created vector ciphertext for assign lanes [3,4,5,...]")
|
|
450
|
-
.option("--policy-output-ciphertext <pubkey>", "pre-created zero EUint64Vector output ciphertext")
|
|
451
|
-
.option("--wait", "wait until the vector policy output ciphertext is verified")
|
|
452
|
-
.action(async function confidentialProposeVector() {
|
|
453
|
-
const ctx = buildCliContext(this);
|
|
454
|
-
if (!ctx.wallet) {
|
|
455
|
-
throw new Error("A wallet is required to submit a confidential vector proposal.");
|
|
456
|
-
}
|
|
457
|
-
const options = this.opts();
|
|
458
|
-
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
459
|
-
agentId: typeof options["agentId"] === "string" ? options["agentId"] : undefined,
|
|
460
|
-
treasury: typeof options["treasury"] === "string" ? options["treasury"] : undefined,
|
|
461
|
-
});
|
|
462
|
-
const guardrailVectorCiphertext = resolveVectorGuardrail(treasuryState.account);
|
|
463
|
-
const amountUsd = await promptNumber(typeof options["amount"] === "number" ? options["amount"] : undefined, "Amount (USD)", { validate: (value) => { if (value <= 0)
|
|
464
|
-
throw new Error("Amount must be > 0"); } });
|
|
465
|
-
const chain = await promptChain(typeof options["chain"] === "string" || typeof options["chain"] === "number"
|
|
466
|
-
? options["chain"]
|
|
467
|
-
: undefined, "Chain");
|
|
468
|
-
const recipient = await promptString(typeof options["recipient"] === "string" ? options["recipient"] : undefined, "Recipient");
|
|
469
|
-
const txType = await promptTransactionType(typeof options["txType"] === "string" || typeof options["txType"] === "number"
|
|
470
|
-
? options["txType"]
|
|
471
|
-
: undefined, "Transaction type");
|
|
472
|
-
const args = buildProposeConfidentialArgs({
|
|
473
|
-
amountUsd,
|
|
474
|
-
chain,
|
|
475
|
-
txType,
|
|
476
|
-
recipient,
|
|
477
|
-
protocolId: typeof options["protocolId"] === "number" ? options["protocolId"] : undefined,
|
|
478
|
-
expectedOutputUsd: typeof options["expectedOutput"] === "number" ? options["expectedOutput"] : undefined,
|
|
479
|
-
actualOutputUsd: typeof options["actualOutput"] === "number" ? options["actualOutput"] : undefined,
|
|
480
|
-
quoteAgeSecs: typeof options["quoteAge"] === "number" ? options["quoteAge"] : undefined,
|
|
481
|
-
counterpartyRiskScore: typeof options["counterpartyRisk"] === "number"
|
|
482
|
-
? options["counterpartyRisk"]
|
|
483
|
-
: undefined,
|
|
484
|
-
});
|
|
485
|
-
const suppliedInputs = {
|
|
486
|
-
spendDeltaVectorCiphertext: parseOptionalPubkeyOption(options, "spendDeltaCiphertext", "Spend delta ciphertext"),
|
|
487
|
-
comparisonVectorCiphertext: parseOptionalPubkeyOption(options, "comparisonCiphertext", "Comparison ciphertext"),
|
|
488
|
-
flagIndicesVectorCiphertext: parseOptionalPubkeyOption(options, "flagIndicesCiphertext", "Flag indices ciphertext"),
|
|
489
|
-
policyOutputVectorCiphertext: parseOptionalPubkeyOption(options, "policyOutputCiphertext", "Policy output ciphertext"),
|
|
490
|
-
};
|
|
491
|
-
const suppliedCount = Object.values(suppliedInputs).filter(Boolean).length;
|
|
492
|
-
if (suppliedCount > 0 && suppliedCount < 4) {
|
|
493
|
-
throw new Error("Vector proposal ciphertext overrides must include spend-delta, comparison, flag-indices, and policy-output accounts together.");
|
|
494
|
-
}
|
|
495
|
-
const encryptAccounts = deriveEncryptAccounts(ctx.wallet.publicKey, {
|
|
496
|
-
auraProgramId: ctx.programId,
|
|
298
|
+
encryptProgram: encryptAccounts.encryptProgram,
|
|
299
|
+
config: encryptAccounts.config,
|
|
300
|
+
deposit: encryptAccounts.deposit,
|
|
301
|
+
callerProgram: ctx.programId,
|
|
302
|
+
cpiAuthority: encryptAccounts.cpiAuthority,
|
|
303
|
+
networkEncryptionKey: encryptAccounts.networkEncryptionKey,
|
|
304
|
+
eventAuthority: encryptAccounts.eventAuthority,
|
|
305
|
+
externalLiveness: null,
|
|
306
|
+
weeklyLimitCiphertext: null,
|
|
307
|
+
weeklySpentCiphertext: null,
|
|
308
|
+
confidentialGuardrails: null,
|
|
309
|
+
systemProgram: SystemProgram.programId,
|
|
310
|
+
},
|
|
311
|
+
args,
|
|
497
312
|
});
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
note: "dry-run: would create spend-delta, comparison, flag-indices, and zero output EUint64Vector ciphertexts via Ika Encrypt gRPC",
|
|
512
|
-
});
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
const spinner = startSpinner(ctx.output, "Ensuring Encrypt deposit account...");
|
|
516
|
-
if (!ctx.dryRun) {
|
|
517
|
-
await ensureEncryptDeposit({
|
|
518
|
-
connection: ctx.connection,
|
|
519
|
-
payer: ctx.wallet,
|
|
520
|
-
auraProgramId: ctx.programId,
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
let spendDeltaVectorCiphertext = suppliedInputs.spendDeltaVectorCiphertext;
|
|
524
|
-
let comparisonVectorCiphertext = suppliedInputs.comparisonVectorCiphertext;
|
|
525
|
-
let flagIndicesVectorCiphertext = suppliedInputs.flagIndicesVectorCiphertext;
|
|
526
|
-
let policyOutputVectorCiphertext = suppliedInputs.policyOutputVectorCiphertext;
|
|
527
|
-
if (suppliedCount === 0) {
|
|
528
|
-
spinner.setText("Encrypting vector helper ciphertexts via Ika Encrypt...");
|
|
529
|
-
const amount = BigInt(amountUsd);
|
|
530
|
-
[
|
|
531
|
-
spendDeltaVectorCiphertext,
|
|
532
|
-
comparisonVectorCiphertext,
|
|
533
|
-
flagIndicesVectorCiphertext,
|
|
534
|
-
policyOutputVectorCiphertext,
|
|
535
|
-
] = await Promise.all([
|
|
536
|
-
encryptU64Vector([wrappingNegU64(amount), 0n, amount], ctx.programId),
|
|
537
|
-
encryptU64Vector([amount, amount], ctx.programId),
|
|
538
|
-
encryptU64Vector(vectorFlagIndices(), ctx.programId),
|
|
539
|
-
encryptU64Vector([], ctx.programId),
|
|
540
|
-
]);
|
|
541
|
-
}
|
|
542
|
-
if (!spendDeltaVectorCiphertext ||
|
|
543
|
-
!comparisonVectorCiphertext ||
|
|
544
|
-
!flagIndicesVectorCiphertext ||
|
|
545
|
-
!policyOutputVectorCiphertext) {
|
|
546
|
-
throw new Error("Vector helper ciphertext resolution failed.");
|
|
547
|
-
}
|
|
548
|
-
if (!ctx.dryRun) {
|
|
549
|
-
spinner.setText("Waiting for vector ciphertexts to be verified on-chain...");
|
|
550
|
-
await Promise.all([
|
|
551
|
-
waitForCiphertextVerified(ctx.connection, spendDeltaVectorCiphertext, {
|
|
552
|
-
timeoutMs: VECTOR_CIPHERTEXT_TIMEOUT_MS,
|
|
553
|
-
}),
|
|
554
|
-
waitForCiphertextVerified(ctx.connection, comparisonVectorCiphertext, {
|
|
555
|
-
timeoutMs: VECTOR_CIPHERTEXT_TIMEOUT_MS,
|
|
556
|
-
}),
|
|
557
|
-
waitForCiphertextVerified(ctx.connection, flagIndicesVectorCiphertext, {
|
|
558
|
-
timeoutMs: VECTOR_CIPHERTEXT_TIMEOUT_MS,
|
|
559
|
-
}),
|
|
560
|
-
waitForCiphertextVerified(ctx.connection, policyOutputVectorCiphertext, {
|
|
561
|
-
timeoutMs: VECTOR_CIPHERTEXT_TIMEOUT_MS,
|
|
562
|
-
}),
|
|
563
|
-
]);
|
|
564
|
-
}
|
|
565
|
-
const proposeInstruction = await ctx.client.proposeConfidentialVectorTransactionInstruction({
|
|
566
|
-
aiAuthority: ctx.wallet.publicKey,
|
|
567
|
-
treasury: treasuryState.treasury,
|
|
568
|
-
guardrailVectorCiphertext,
|
|
569
|
-
spendDeltaVectorCiphertext,
|
|
570
|
-
comparisonVectorCiphertext,
|
|
571
|
-
flagIndicesVectorCiphertext,
|
|
572
|
-
policyResultVectorCiphertext: policyOutputVectorCiphertext,
|
|
573
|
-
encryptProgram: encryptAccounts.encryptProgram,
|
|
574
|
-
}, args);
|
|
575
|
-
const executeInstruction = await ctx.client.executePendingVectorFheInstruction({
|
|
576
|
-
aiAuthority: ctx.wallet.publicKey,
|
|
577
|
-
treasury: treasuryState.treasury,
|
|
578
|
-
guardrailVectorCiphertext,
|
|
579
|
-
spendDeltaVectorCiphertext,
|
|
580
|
-
comparisonVectorCiphertext,
|
|
581
|
-
flagIndicesVectorCiphertext,
|
|
582
|
-
policyResultVectorCiphertext: policyOutputVectorCiphertext,
|
|
583
|
-
encryptProgram: encryptAccounts.encryptProgram,
|
|
584
|
-
config: encryptAccounts.config,
|
|
585
|
-
deposit: encryptAccounts.deposit,
|
|
586
|
-
callerProgram: ctx.programId,
|
|
587
|
-
cpiAuthority: encryptAccounts.cpiAuthority,
|
|
588
|
-
networkEncryptionKey: encryptAccounts.networkEncryptionKey,
|
|
589
|
-
eventAuthority: encryptAccounts.eventAuthority,
|
|
590
|
-
systemProgram: SystemProgram.programId,
|
|
591
|
-
}, executeArgs);
|
|
592
|
-
if (ctx.dryRun) {
|
|
593
|
-
emitJson(ctx.output, {
|
|
594
|
-
action: "confidential.propose-vector",
|
|
313
|
+
// The freshly created output ciphertext account must sign its own creation.
|
|
314
|
+
markInstructionSigner(instruction, policyOutputSigner.publicKey);
|
|
315
|
+
const outcome = await runInstructions(ctx, [instruction], {
|
|
316
|
+
action: "Propose confidential transaction",
|
|
317
|
+
instructionName: "propose_confidential_transaction",
|
|
318
|
+
extraSigners: [policyOutputSigner],
|
|
319
|
+
computeUnits: 1_400_000,
|
|
320
|
+
heapFrameBytes: 256 * 1024,
|
|
321
|
+
summary: [
|
|
322
|
+
["amount ct", amountCiphertext.toBase58()],
|
|
323
|
+
["output ct", policyOutputSigner.publicKey.toBase58()],
|
|
324
|
+
],
|
|
325
|
+
result: {
|
|
595
326
|
treasury: treasuryState.treasury,
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
policyOutputVectorCiphertext,
|
|
600
|
-
instructions: {
|
|
601
|
-
propose: serializeInstruction(proposeInstruction),
|
|
602
|
-
executeVectorFhe: serializeInstruction(executeInstruction),
|
|
603
|
-
},
|
|
604
|
-
});
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
spinner.setText("Submitting vector confidential proposal...");
|
|
608
|
-
const signature = await sendPreparedInstruction({
|
|
609
|
-
ctx,
|
|
610
|
-
instruction: proposeInstruction,
|
|
611
|
-
});
|
|
612
|
-
spinner.setText("Executing vector FHE graph...");
|
|
613
|
-
const executeSignature = await sendPreparedInstruction({
|
|
614
|
-
ctx,
|
|
615
|
-
instruction: executeInstruction,
|
|
327
|
+
amountCiphertext,
|
|
328
|
+
policyOutputCiphertext: policyOutputSigner.publicKey,
|
|
329
|
+
},
|
|
616
330
|
});
|
|
617
|
-
if (options
|
|
618
|
-
|
|
619
|
-
await waitForCiphertextVerified(ctx.connection,
|
|
620
|
-
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
spinner.succeed("Vector confidential proposal submitted");
|
|
624
|
-
if (ctx.output.json) {
|
|
625
|
-
emitJson(ctx.output, {
|
|
626
|
-
treasury: treasuryState.treasury,
|
|
627
|
-
signature,
|
|
628
|
-
executeSignature,
|
|
629
|
-
spendDeltaVectorCiphertext,
|
|
630
|
-
comparisonVectorCiphertext,
|
|
631
|
-
flagIndicesVectorCiphertext,
|
|
632
|
-
policyOutputCiphertext: policyOutputVectorCiphertext,
|
|
633
|
-
});
|
|
634
|
-
return;
|
|
331
|
+
if (outcome.signature && options.wait === true) {
|
|
332
|
+
const waitSpinner = startSpinner(ctx.output, "Waiting for output ciphertext verification...");
|
|
333
|
+
await waitForCiphertextVerified(ctx.connection, policyOutputSigner.publicKey);
|
|
334
|
+
waitSpinner.succeed("Output ciphertext verified");
|
|
635
335
|
}
|
|
636
|
-
printSuccess(ctx.output, `Vector confidential proposal submitted:\n propose: ${signature}\n execute FHE: ${executeSignature}\n output ciphertext: ${policyOutputVectorCiphertext.toBase58()}`);
|
|
637
336
|
});
|
|
337
|
+
// --- request-decryption ---------------------------------------------
|
|
638
338
|
confidential
|
|
639
339
|
.command("request-decryption")
|
|
640
340
|
.description("Request Encrypt decryption for the pending policy output")
|
|
641
341
|
.option("--agent-id <id>", "treasury agent ID")
|
|
642
342
|
.option("--treasury <pda>", "treasury PDA")
|
|
643
343
|
.option("--ciphertext <pubkey>", "override the pending policy output ciphertext")
|
|
644
|
-
.option("--request-keypair <path>", "
|
|
344
|
+
.option("--request-keypair <path>", "keypair path for the decryption request account")
|
|
645
345
|
.option("--wait", "wait until the plaintext is ready on-chain")
|
|
646
346
|
.action(async function confidentialRequestDecryption() {
|
|
647
347
|
const ctx = buildCliContext(this);
|
|
648
|
-
|
|
649
|
-
throw new Error("A wallet is required to request policy decryption.");
|
|
650
|
-
}
|
|
348
|
+
const wallet = requireWallet(ctx);
|
|
651
349
|
const options = this.opts();
|
|
652
350
|
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
653
|
-
agentId: typeof options
|
|
654
|
-
treasury: typeof options
|
|
351
|
+
agentId: typeof options.agentId === "string" ? options.agentId : undefined,
|
|
352
|
+
treasury: typeof options.treasury === "string" ? options.treasury : undefined,
|
|
655
353
|
});
|
|
656
|
-
const ciphertext = typeof options
|
|
657
|
-
? parsePublicKey(options
|
|
354
|
+
const ciphertext = typeof options.ciphertext === "string"
|
|
355
|
+
? parsePublicKey(options.ciphertext, "ciphertext")
|
|
658
356
|
: resolvePendingPolicyOutput(treasuryState.account);
|
|
659
|
-
const requestSigner = buildDryRunKeypair(typeof options["requestKeypair"] === "string"
|
|
660
|
-
? options["requestKeypair"]
|
|
661
|
-
: undefined, loadKeypair);
|
|
662
|
-
const encryptAccounts = deriveEncryptAccounts(ctx.wallet.publicKey, {
|
|
663
|
-
auraProgramId: ctx.programId,
|
|
664
|
-
});
|
|
665
|
-
const now = Math.floor(Date.now() / 1000);
|
|
666
|
-
const instruction = await ctx.client.requestPolicyDecryptionInstruction({
|
|
667
|
-
operator: ctx.wallet.publicKey,
|
|
668
|
-
treasury: treasuryState.treasury,
|
|
669
|
-
requestAccount: requestSigner.publicKey,
|
|
670
|
-
ciphertext,
|
|
671
|
-
encryptProgram: encryptAccounts.encryptProgram,
|
|
672
|
-
config: encryptAccounts.config,
|
|
673
|
-
deposit: encryptAccounts.deposit,
|
|
674
|
-
callerProgram: ctx.programId,
|
|
675
|
-
cpiAuthority: encryptAccounts.cpiAuthority,
|
|
676
|
-
networkEncryptionKey: encryptAccounts.networkEncryptionKey,
|
|
677
|
-
eventAuthority: encryptAccounts.eventAuthority,
|
|
678
|
-
systemProgram: SystemProgram.programId,
|
|
679
|
-
}, now);
|
|
680
|
-
markInstructionSigner(instruction, requestSigner.publicKey);
|
|
681
357
|
if (ctx.dryRun) {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
358
|
+
printNote(ctx.output, "Dry run: would ensure an Encrypt deposit and submit request_policy_decryption.");
|
|
359
|
+
if (ctx.output.json) {
|
|
360
|
+
emitJson(ctx.output, {
|
|
361
|
+
action: "confidential.request-decryption",
|
|
362
|
+
treasury: treasuryState.treasury,
|
|
363
|
+
ciphertext,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
689
366
|
return;
|
|
690
367
|
}
|
|
368
|
+
const requestSigner = buildDryRunKeypair(typeof options.requestKeypair === "string"
|
|
369
|
+
? options.requestKeypair
|
|
370
|
+
: undefined, loadKeypair);
|
|
371
|
+
const encryptAccounts = deriveEncryptAccounts(wallet.publicKey, {
|
|
372
|
+
auraProgramId: ctx.programId,
|
|
373
|
+
});
|
|
691
374
|
const spinner = startSpinner(ctx.output, "Ensuring Encrypt deposit account...");
|
|
692
|
-
|
|
375
|
+
await ensureEncryptDeposit({
|
|
693
376
|
connection: ctx.connection,
|
|
694
|
-
payer:
|
|
377
|
+
payer: wallet,
|
|
695
378
|
auraProgramId: ctx.programId,
|
|
696
379
|
});
|
|
697
|
-
spinner.
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
380
|
+
spinner.succeed("Encrypt deposit ready");
|
|
381
|
+
const instruction = await instructions.confidential.requestPolicyDecryption(ctx.client, {
|
|
382
|
+
accounts: {
|
|
383
|
+
operator: wallet.publicKey,
|
|
384
|
+
treasury: treasuryState.treasury,
|
|
385
|
+
requestAccount: requestSigner.publicKey,
|
|
386
|
+
ciphertext,
|
|
387
|
+
encryptProgram: encryptAccounts.encryptProgram,
|
|
388
|
+
config: encryptAccounts.config,
|
|
389
|
+
deposit: encryptAccounts.deposit,
|
|
390
|
+
callerProgram: ctx.programId,
|
|
391
|
+
cpiAuthority: encryptAccounts.cpiAuthority,
|
|
392
|
+
networkEncryptionKey: encryptAccounts.networkEncryptionKey,
|
|
393
|
+
eventAuthority: encryptAccounts.eventAuthority,
|
|
394
|
+
confidentialGuardrails: null,
|
|
395
|
+
systemProgram: SystemProgram.programId,
|
|
396
|
+
},
|
|
397
|
+
args: { now: nowBn(), currentEpochId: new BN(0) },
|
|
702
398
|
});
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
399
|
+
markInstructionSigner(instruction, requestSigner.publicKey);
|
|
400
|
+
const outcome = await runInstructions(ctx, [instruction], {
|
|
401
|
+
action: "Request policy decryption",
|
|
402
|
+
instructionName: "request_policy_decryption",
|
|
403
|
+
extraSigners: [requestSigner],
|
|
404
|
+
computeUnits: 1_400_000,
|
|
405
|
+
heapFrameBytes: 256 * 1024,
|
|
406
|
+
summary: [["request", requestSigner.publicKey.toBase58()]],
|
|
407
|
+
result: {
|
|
710
408
|
treasury: treasuryState.treasury,
|
|
711
|
-
signature,
|
|
712
409
|
requestAccount: requestSigner.publicKey,
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
if (outcome.signature && options.wait === true) {
|
|
413
|
+
const waitSpinner = startSpinner(ctx.output, "Waiting for decrypted plaintext...");
|
|
414
|
+
await waitForDecryptionReady(ctx.connection, requestSigner.publicKey);
|
|
415
|
+
waitSpinner.succeed("Plaintext ready");
|
|
716
416
|
}
|
|
717
|
-
printSuccess(ctx.output, `Policy decryption requested: ${signature} (request ${requestSigner.publicKey.toBase58()})`);
|
|
718
417
|
});
|
|
418
|
+
// --- confirm-decryption ---------------------------------------------
|
|
719
419
|
confidential
|
|
720
420
|
.command("confirm-decryption")
|
|
721
421
|
.description("Confirm a completed policy decryption request on-chain")
|
|
@@ -724,72 +424,51 @@ export function registerConfidentialCommands(program) {
|
|
|
724
424
|
.option("--request-account <pubkey>", "override the pending decryption request account")
|
|
725
425
|
.action(async function confidentialConfirmDecryption() {
|
|
726
426
|
const ctx = buildCliContext(this);
|
|
727
|
-
|
|
728
|
-
throw new Error("A wallet is required to confirm policy decryption.");
|
|
729
|
-
}
|
|
427
|
+
const wallet = requireWallet(ctx);
|
|
730
428
|
const options = this.opts();
|
|
731
429
|
const treasuryState = await resolveTreasuryAccount(ctx, {
|
|
732
|
-
agentId: typeof options
|
|
733
|
-
treasury: typeof options
|
|
430
|
+
agentId: typeof options.agentId === "string" ? options.agentId : undefined,
|
|
431
|
+
treasury: typeof options.treasury === "string" ? options.treasury : undefined,
|
|
734
432
|
});
|
|
735
|
-
const requestAccount = typeof options
|
|
736
|
-
? parsePublicKey(options
|
|
433
|
+
const requestAccount = typeof options.requestAccount === "string"
|
|
434
|
+
? parsePublicKey(options.requestAccount, "request-account")
|
|
737
435
|
: resolvePendingRequestAccount(treasuryState.account);
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
operator: ctx.wallet.publicKey,
|
|
742
|
-
treasury: treasuryState.treasury,
|
|
743
|
-
requestAccount,
|
|
744
|
-
}, now);
|
|
745
|
-
emitJson(ctx.output, {
|
|
746
|
-
action: "confidential.confirm-decryption",
|
|
436
|
+
const instruction = await instructions.confidential.confirmPolicyDecryption(ctx.client, {
|
|
437
|
+
accounts: {
|
|
438
|
+
operator: wallet.publicKey,
|
|
747
439
|
treasury: treasuryState.treasury,
|
|
748
440
|
requestAccount,
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
}
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
requestAccount,
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
441
|
+
confidentialGuardrails: null,
|
|
442
|
+
},
|
|
443
|
+
args: { now: nowBn(), currentEpochId: new BN(0) },
|
|
444
|
+
});
|
|
445
|
+
const outcome = await runInstructions(ctx, [instruction], {
|
|
446
|
+
action: "Confirm policy decryption",
|
|
447
|
+
instructionName: "confirm_policy_decryption",
|
|
448
|
+
summary: [["request", requestAccount.toBase58()]],
|
|
449
|
+
result: { treasury: treasuryState.treasury, requestAccount },
|
|
450
|
+
});
|
|
451
|
+
if (outcome.signature && !ctx.output.json) {
|
|
452
|
+
let violationCode = null;
|
|
453
|
+
try {
|
|
454
|
+
violationCode = await readU64Ciphertext(resolvePendingPolicyOutput(treasuryState.account), wallet.publicKey);
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
// Non-fatal — on-chain state remains the source of truth.
|
|
458
|
+
}
|
|
459
|
+
try {
|
|
460
|
+
const refreshed = await accounts.fetchTreasuryAccount(ctx.client, treasuryState.treasury);
|
|
461
|
+
const decision = getActivePendingProposal(refreshed)?.decision;
|
|
462
|
+
if (decision) {
|
|
463
|
+
printInfo(ctx.output, decision.approved
|
|
464
|
+
? style.success("result: approved")
|
|
465
|
+
: style.danger(`result: denied — violation code ${violationCode ?? decision.violation}`));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
// Non-fatal.
|
|
768
470
|
}
|
|
769
471
|
}
|
|
770
|
-
catch {
|
|
771
|
-
// Non-fatal — the on-chain state is the source of truth
|
|
772
|
-
}
|
|
773
|
-
spinner.succeed("Policy decryption confirmed");
|
|
774
|
-
const refreshed = await ctx.client.getTreasuryAccount(treasuryState.treasury);
|
|
775
|
-
const decision = getActivePendingProposal(refreshed)?.decision;
|
|
776
|
-
if (ctx.output.json) {
|
|
777
|
-
emitJson(ctx.output, {
|
|
778
|
-
treasury: treasuryState.treasury,
|
|
779
|
-
requestAccount,
|
|
780
|
-
signature,
|
|
781
|
-
approved: decision?.approved ?? null,
|
|
782
|
-
violation: decision?.violation ?? null,
|
|
783
|
-
violationCode: violationCode !== null ? violationCode.toString() : null,
|
|
784
|
-
});
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
const resultLine = decision
|
|
788
|
-
? decision.approved
|
|
789
|
-
? "approved ✓"
|
|
790
|
-
: `denied — violation code ${violationCode ?? decision.violation}`
|
|
791
|
-
: "";
|
|
792
|
-
printSuccess(ctx.output, `Policy decryption confirmed: ${signature}${resultLine ? `\n result: ${resultLine}` : ""}`);
|
|
793
472
|
});
|
|
794
473
|
}
|
|
795
474
|
//# sourceMappingURL=confidential.js.map
|