arc402-cli 1.8.8 → 1.8.9
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/abis.js +1 -1
- package/dist/abis.js.map +1 -1
- package/dist/approval/broker.d.ts +9 -0
- package/dist/approval/broker.d.ts.map +1 -0
- package/dist/approval/broker.js +45 -0
- package/dist/approval/broker.js.map +1 -0
- package/dist/approval/config.d.ts +20 -0
- package/dist/approval/config.d.ts.map +1 -0
- package/dist/approval/config.js +42 -0
- package/dist/approval/config.js.map +1 -0
- package/dist/approval/init.d.ts +4 -0
- package/dist/approval/init.d.ts.map +1 -0
- package/dist/approval/init.js +128 -0
- package/dist/approval/init.js.map +1 -0
- package/dist/approval/passkey-requests.d.ts +22 -0
- package/dist/approval/passkey-requests.d.ts.map +1 -0
- package/dist/approval/passkey-requests.js +85 -0
- package/dist/approval/passkey-requests.js.map +1 -0
- package/dist/approval/transports/local-qr.d.ts +3 -0
- package/dist/approval/transports/local-qr.d.ts.map +1 -0
- package/dist/approval/transports/local-qr.js +42 -0
- package/dist/approval/transports/local-qr.js.map +1 -0
- package/dist/approval/transports/telegram-passkey-link.d.ts +3 -0
- package/dist/approval/transports/telegram-passkey-link.d.ts.map +1 -0
- package/dist/approval/transports/telegram-passkey-link.js +137 -0
- package/dist/approval/transports/telegram-passkey-link.js.map +1 -0
- package/dist/approval/transports/telegram-walletconnect.d.ts +3 -0
- package/dist/approval/transports/telegram-walletconnect.d.ts.map +1 -0
- package/dist/approval/transports/telegram-walletconnect.js +53 -0
- package/dist/approval/transports/telegram-walletconnect.js.map +1 -0
- package/dist/approval/types.d.ts +66 -0
- package/dist/approval/types.d.ts.map +1 -0
- package/dist/approval/types.js +3 -0
- package/dist/approval/types.js.map +1 -0
- package/dist/bundler.d.ts +1 -0
- package/dist/bundler.d.ts.map +1 -1
- package/dist/bundler.js +31 -0
- package/dist/bundler.js.map +1 -1
- package/dist/commands/accept.js +1 -1
- package/dist/commands/accept.js.map +1 -1
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +22 -7
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/approvals.d.ts +3 -0
- package/dist/commands/approvals.d.ts.map +1 -0
- package/dist/commands/approvals.js +78 -0
- package/dist/commands/approvals.js.map +1 -0
- package/dist/commands/arena-handshake.d.ts.map +1 -1
- package/dist/commands/arena-handshake.js +9 -18
- package/dist/commands/arena-handshake.js.map +1 -1
- package/dist/commands/arena-v2.d.ts.map +1 -1
- package/dist/commands/arena-v2.js +23 -38
- package/dist/commands/arena-v2.js.map +1 -1
- package/dist/commands/compute.d.ts.map +1 -1
- package/dist/commands/compute.js +3 -4
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +1 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/deliver.js +1 -1
- package/dist/commands/deliver.js.map +1 -1
- package/dist/commands/hire.d.ts.map +1 -1
- package/dist/commands/hire.js +3 -4
- package/dist/commands/hire.js.map +1 -1
- package/dist/commands/job.d.ts.map +1 -1
- package/dist/commands/job.js +1 -1
- package/dist/commands/job.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +4 -8
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/wallet.d.ts.map +1 -1
- package/dist/commands/wallet.js +580 -204
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/workroom.js +1 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +77 -36
- package/dist/config.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +59 -0
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/passkey-approvals.d.ts +24 -0
- package/dist/daemon/passkey-approvals.d.ts.map +1 -0
- package/dist/daemon/passkey-approvals.js +31 -0
- package/dist/daemon/passkey-approvals.js.map +1 -0
- package/dist/endpoint-notify.d.ts +1 -2
- package/dist/endpoint-notify.d.ts.map +1 -1
- package/dist/endpoint-notify.js +1 -3
- package/dist/endpoint-notify.js.map +1 -1
- package/dist/index.js +5 -11
- package/dist/index.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +2 -0
- package/dist/program.js.map +1 -1
- package/dist/tui-esm/App.js +136 -0
- package/dist/tui-esm/App.js.map +1 -0
- package/dist/tui-esm/Footer.js +13 -0
- package/dist/tui-esm/Footer.js.map +1 -0
- package/dist/tui-esm/Header.js +19 -0
- package/dist/tui-esm/Header.js.map +1 -0
- package/dist/tui-esm/InputLine.js +121 -0
- package/dist/tui-esm/InputLine.js.map +1 -0
- package/dist/tui-esm/Viewport.js +39 -0
- package/dist/tui-esm/Viewport.js.map +1 -0
- package/dist/tui-esm/WalletConnectPairing.js +61 -0
- package/dist/tui-esm/WalletConnectPairing.js.map +1 -0
- package/dist/tui-esm/command-catalog.js +20 -0
- package/dist/tui-esm/command-catalog.js.map +1 -0
- package/dist/tui-esm/command-renderers.js +180 -0
- package/dist/tui-esm/command-renderers.js.map +1 -0
- package/dist/tui-esm/commerce-format.js +19 -0
- package/dist/tui-esm/commerce-format.js.map +1 -0
- package/dist/tui-esm/components/Button.js +21 -0
- package/dist/tui-esm/components/Button.js.map +1 -0
- package/dist/tui-esm/components/CeremonyView.js +10 -0
- package/dist/tui-esm/components/CeremonyView.js.map +1 -0
- package/dist/tui-esm/components/CompletionDropdown.js +23 -0
- package/dist/tui-esm/components/CompletionDropdown.js.map +1 -0
- package/dist/tui-esm/components/ConfirmPrompt.js +10 -0
- package/dist/tui-esm/components/ConfirmPrompt.js.map +1 -0
- package/dist/tui-esm/components/CustomTextInput.js +99 -0
- package/dist/tui-esm/components/CustomTextInput.js.map +1 -0
- package/dist/tui-esm/components/InteractiveTable.js +61 -0
- package/dist/tui-esm/components/InteractiveTable.js.map +1 -0
- package/dist/tui-esm/components/StepSpinner.js +32 -0
- package/dist/tui-esm/components/StepSpinner.js.map +1 -0
- package/dist/tui-esm/components/Toast.js +29 -0
- package/dist/tui-esm/components/Toast.js.map +1 -0
- package/dist/tui-esm/components/commerce/AgreementList.js +25 -0
- package/dist/tui-esm/components/commerce/AgreementList.js.map +1 -0
- package/dist/tui-esm/components/commerce/ComputeCard.js +9 -0
- package/dist/tui-esm/components/commerce/ComputeCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/DiscoverList.js +14 -0
- package/dist/tui-esm/components/commerce/DiscoverList.js.map +1 -0
- package/dist/tui-esm/components/commerce/HireCard.js +11 -0
- package/dist/tui-esm/components/commerce/HireCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/RoundsList.js +9 -0
- package/dist/tui-esm/components/commerce/RoundsList.js.map +1 -0
- package/dist/tui-esm/components/commerce/SquadCard.js +10 -0
- package/dist/tui-esm/components/commerce/SquadCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/StatusCard.js +10 -0
- package/dist/tui-esm/components/commerce/StatusCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/SubscribeCard.js +10 -0
- package/dist/tui-esm/components/commerce/SubscribeCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/WorkroomCard.js +10 -0
- package/dist/tui-esm/components/commerce/WorkroomCard.js.map +1 -0
- package/dist/tui-esm/components/commerce/common.js +71 -0
- package/dist/tui-esm/components/commerce/common.js.map +1 -0
- package/dist/tui-esm/components/commerce/index.js +27 -0
- package/dist/tui-esm/components/commerce/index.js.map +1 -0
- package/dist/tui-esm/index.js +55 -0
- package/dist/tui-esm/index.js.map +1 -0
- package/dist/tui-esm/kernel.js +734 -0
- package/dist/tui-esm/kernel.js.map +1 -0
- package/dist/tui-esm/render-inline.js +32 -0
- package/dist/tui-esm/render-inline.js.map +1 -0
- package/dist/tui-esm/useChat.js +91 -0
- package/dist/tui-esm/useChat.js.map +1 -0
- package/dist/tui-esm/useCommand.js +142 -0
- package/dist/tui-esm/useCommand.js.map +1 -0
- package/dist/tui-esm/useNotifications.js +17 -0
- package/dist/tui-esm/useNotifications.js.map +1 -0
- package/dist/tui-esm/useScroll.js +46 -0
- package/dist/tui-esm/useScroll.js.map +1 -0
- package/dist/tui-esm/useTerminalSize.js +32 -0
- package/dist/tui-esm/useTerminalSize.js.map +1 -0
- package/hermes/plugins/dist/arc402_hermes-1.0.0-py3-none-any.whl +0 -0
- package/hermes/plugins/dist/arc402_hermes-1.0.0.tar.gz +0 -0
- package/package.json +2 -2
package/dist/commands/wallet.js
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
@@ -50,6 +17,8 @@ const format_1 = require("../utils/format");
|
|
|
50
17
|
const abis_1 = require("../abis");
|
|
51
18
|
const config_2 = require("../config");
|
|
52
19
|
const walletconnect_1 = require("../walletconnect");
|
|
20
|
+
const config_3 = require("../approval/config");
|
|
21
|
+
const broker_1 = require("../approval/broker");
|
|
53
22
|
const bundler_1 = require("../bundler");
|
|
54
23
|
const walletconnect_session_1 = require("../walletconnect-session");
|
|
55
24
|
const wallet_router_1 = require("../wallet-router");
|
|
@@ -60,6 +29,89 @@ const spinner_1 = require("../ui/spinner");
|
|
|
60
29
|
const colors_1 = require("../ui/colors");
|
|
61
30
|
const rpc_fallback_1 = require("../ui/rpc-fallback");
|
|
62
31
|
const GUARDIAN_KEY_PATH = path_1.default.join(os_1.default.homedir(), ".arc402", "guardian.key");
|
|
32
|
+
function requireApprovedWalletConnectSession(approval) {
|
|
33
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
34
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
return approval.session;
|
|
38
|
+
}
|
|
39
|
+
async function requestWalletConnectApprovalSession(config, intent) {
|
|
40
|
+
return requireApprovedWalletConnectSession(await (0, broker_1.requestOwnerApproval)(intent, config));
|
|
41
|
+
}
|
|
42
|
+
const PASSKEY_GOVERNANCE_SELECTORS = new Set([
|
|
43
|
+
ethers_1.ethers.id("unfreeze()").slice(0, 10).toLowerCase(),
|
|
44
|
+
ethers_1.ethers.id("setGuardian(address)").slice(0, 10).toLowerCase(),
|
|
45
|
+
ethers_1.ethers.id("proposeRegistryUpdate(address)").slice(0, 10).toLowerCase(),
|
|
46
|
+
ethers_1.ethers.id("executeRegistryUpdate()").slice(0, 10).toLowerCase(),
|
|
47
|
+
ethers_1.ethers.id("cancelRegistryUpdate()").slice(0, 10).toLowerCase(),
|
|
48
|
+
ethers_1.ethers.id("setAuthorizedInterceptor(address)").slice(0, 10).toLowerCase(),
|
|
49
|
+
ethers_1.ethers.id("setVelocityLimit(uint256)").slice(0, 10).toLowerCase(),
|
|
50
|
+
ethers_1.ethers.id("authorizeMachineKey(address)").slice(0, 10).toLowerCase(),
|
|
51
|
+
ethers_1.ethers.id("revokeMachineKey(address)").slice(0, 10).toLowerCase(),
|
|
52
|
+
]);
|
|
53
|
+
function canUsePasskeyForWalletGovernance(config, walletAddress, tx) {
|
|
54
|
+
const approval = (0, config_3.getApprovalConfig)(config);
|
|
55
|
+
const selector = tx.data.slice(0, 10).toLowerCase();
|
|
56
|
+
return approval.defaultTransport === "telegram_passkey_link"
|
|
57
|
+
&& tx.to.toLowerCase() === walletAddress.toLowerCase()
|
|
58
|
+
&& PASSKEY_GOVERNANCE_SELECTORS.has(selector);
|
|
59
|
+
}
|
|
60
|
+
async function requestWalletGovernanceExecution(config, intent) {
|
|
61
|
+
const walletAddress = intent.walletAddress;
|
|
62
|
+
const tx = intent.txs[0];
|
|
63
|
+
if (!walletAddress || !tx || intent.txs.length !== 1) {
|
|
64
|
+
return {
|
|
65
|
+
kind: "walletconnect",
|
|
66
|
+
session: await requestWalletConnectApprovalSession(config, intent),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (!canUsePasskeyForWalletGovernance(config, walletAddress, tx)) {
|
|
70
|
+
return {
|
|
71
|
+
kind: "walletconnect",
|
|
72
|
+
session: await requestWalletConnectApprovalSession(config, intent),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
76
|
+
const nonceReader = new ethers_1.ethers.Contract(bundler_1.DEFAULT_ENTRY_POINT, ["function getNonce(address sender, uint192 key) external view returns (uint256)"], provider);
|
|
77
|
+
const nonce = await nonceReader.getNonce(walletAddress, 0);
|
|
78
|
+
const bundler = new bundler_1.BundlerClient(process.env.BUNDLER_URL ?? bundler_1.DEFAULT_BUNDLER_URL, bundler_1.DEFAULT_ENTRY_POINT, intent.chainId);
|
|
79
|
+
const userOp = await (0, bundler_1.buildUserOp)(tx.data, walletAddress, nonce, config);
|
|
80
|
+
try {
|
|
81
|
+
const estimate = await bundler.estimateUserOperationGas(userOp);
|
|
82
|
+
userOp.callGasLimit = estimate.callGasLimit;
|
|
83
|
+
userOp.verificationGasLimit = estimate.verificationGasLimit;
|
|
84
|
+
userOp.preVerificationGas = estimate.preVerificationGas;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// keep conservative defaults if estimation is unavailable
|
|
88
|
+
}
|
|
89
|
+
const challenge = (0, bundler_1.getUserOperationHash)(userOp, bundler_1.DEFAULT_ENTRY_POINT, intent.chainId);
|
|
90
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
91
|
+
...intent,
|
|
92
|
+
signerMode: "passkey",
|
|
93
|
+
metadata: {
|
|
94
|
+
...intent.metadata,
|
|
95
|
+
passkeyChallenge: challenge,
|
|
96
|
+
},
|
|
97
|
+
}, config);
|
|
98
|
+
if (approval.status !== "approved" || !approval.passkeyApproval?.signature) {
|
|
99
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Passkey approval failed."));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
userOp.signature = approval.passkeyApproval.signature;
|
|
103
|
+
const userOpHash = await bundler.sendUserOperation(userOp);
|
|
104
|
+
const receipt = await bundler.getUserOperationReceipt(userOpHash);
|
|
105
|
+
if (!receipt.success) {
|
|
106
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red("UserOperation failed on-chain."));
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
kind: "passkey",
|
|
111
|
+
userOpHash,
|
|
112
|
+
txHash: String(receipt.receipt.transactionHash),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
63
115
|
function buildFreshConfigFromDefaults(existing, network, privateKey, ownerAddress) {
|
|
64
116
|
const defaults = config_1.NETWORK_DEFAULTS[network];
|
|
65
117
|
if (!defaults)
|
|
@@ -74,6 +126,7 @@ function buildFreshConfigFromDefaults(existing, network, privateKey, ownerAddres
|
|
|
74
126
|
telegramBotToken: existing?.telegramBotToken,
|
|
75
127
|
telegramChatId: existing?.telegramChatId,
|
|
76
128
|
telegramThreadId: existing?.telegramThreadId,
|
|
129
|
+
approval: existing?.approval,
|
|
77
130
|
deviceId: existing?.deviceId,
|
|
78
131
|
chat: existing?.chat,
|
|
79
132
|
policyEngineAddress: defaults.policyEngineAddress,
|
|
@@ -131,9 +184,7 @@ function parseAmount(raw) {
|
|
|
131
184
|
return BigInt(raw);
|
|
132
185
|
}
|
|
133
186
|
function resolvePolicyEngineAddress(config) {
|
|
134
|
-
return (config
|
|
135
|
-
config_1.NETWORK_DEFAULTS[config.network]?.policyEngineAddress ??
|
|
136
|
-
"0x9449B15268bE7042C0b473F3f711a41A29220866");
|
|
187
|
+
return (0, config_1.getCanonicalNetworkAddress)(config, "policyEngineAddress");
|
|
137
188
|
}
|
|
138
189
|
function getWalletAddressFromFactoryLogs(factoryInterface, logs) {
|
|
139
190
|
for (const log of logs) {
|
|
@@ -182,7 +233,6 @@ const ONBOARDING_CATEGORIES = [
|
|
|
182
233
|
*/
|
|
183
234
|
async function runWalletOnboardingCeremony(walletAddress, ownerAddress, config, provider, sendTx) {
|
|
184
235
|
const policyAddress = resolvePolicyEngineAddress(config);
|
|
185
|
-
const executeIface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_EXECUTE_ABI);
|
|
186
236
|
const govIface = new ethers_1.ethers.Interface(abis_1.POLICY_ENGINE_GOVERNANCE_ABI);
|
|
187
237
|
const limitsIface = new ethers_1.ethers.Interface(abis_1.POLICY_ENGINE_LIMITS_ABI);
|
|
188
238
|
const policyGov = new ethers_1.ethers.Contract(policyAddress, abis_1.POLICY_ENGINE_GOVERNANCE_ABI, provider);
|
|
@@ -205,15 +255,8 @@ async function runWalletOnboardingCeremony(walletAddress, ownerAddress, config,
|
|
|
205
255
|
if (!alreadyRegistered) {
|
|
206
256
|
const registerCalldata = govIface.encodeFunctionData("registerWallet", [walletAddress, ownerAddress]);
|
|
207
257
|
await sendTx({
|
|
208
|
-
to:
|
|
209
|
-
data:
|
|
210
|
-
target: policyAddress,
|
|
211
|
-
data: registerCalldata,
|
|
212
|
-
value: 0n,
|
|
213
|
-
minReturnValue: 0n,
|
|
214
|
-
maxApprovalAmount: 0n,
|
|
215
|
-
approvalToken: ethers_1.ethers.ZeroAddress,
|
|
216
|
-
}]),
|
|
258
|
+
to: policyAddress,
|
|
259
|
+
data: registerCalldata,
|
|
217
260
|
value: "0x0",
|
|
218
261
|
}, "registerWallet on PolicyEngine");
|
|
219
262
|
}
|
|
@@ -261,11 +304,8 @@ async function runWalletOnboardingCeremony(walletAddress, ownerAddress, config,
|
|
|
261
304
|
*/
|
|
262
305
|
async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config, provider, sendTx) {
|
|
263
306
|
const policyAddress = resolvePolicyEngineAddress(config);
|
|
264
|
-
const agentRegistryAddress = config
|
|
265
|
-
|
|
266
|
-
const handshakeAddress = config.handshakeAddress ??
|
|
267
|
-
config_1.NETWORK_DEFAULTS[config.network]?.handshakeAddress ??
|
|
268
|
-
"0x4F5A38Bb746d7E5d49d8fd26CA6beD141Ec2DDb3";
|
|
307
|
+
const agentRegistryAddress = (0, config_1.getCanonicalAgentRegistryAddress)(config);
|
|
308
|
+
const handshakeAddress = (0, config_1.getCanonicalNetworkAddress)(config, "handshakeAddress");
|
|
269
309
|
// ── Step 2: Machine Key ────────────────────────────────────────────────────
|
|
270
310
|
console.log("\n" + colors_1.c.dim("── Step 2: Machine Key ────────────────────────────────────────"));
|
|
271
311
|
let machineKeyAddress;
|
|
@@ -493,11 +533,11 @@ async function runCompleteOnboardingCeremony(walletAddress, ownerAddress, config
|
|
|
493
533
|
// Whitelist all contracts an agent will need for the full ARC-402 flow.
|
|
494
534
|
const protocolContracts = [
|
|
495
535
|
{ address: agentRegistryAddress ?? "", name: "AgentRegistry" },
|
|
496
|
-
{ address:
|
|
497
|
-
{ address:
|
|
498
|
-
{ address:
|
|
499
|
-
{ address:
|
|
500
|
-
{ address:
|
|
536
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.serviceAgreementAddress ?? "", name: "ServiceAgreement" },
|
|
537
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.computeAgreementAddress ?? "", name: "ComputeAgreement" },
|
|
538
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.subscriptionAgreementAddress ?? "", name: "SubscriptionAgreement" },
|
|
539
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.handshakeAddress ?? "", name: "Handshake" },
|
|
540
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.sessionChannelsAddress ?? "", name: "SessionChannels" },
|
|
501
541
|
].filter(c => c.address && c.address !== "");
|
|
502
542
|
for (const contract of protocolContracts) {
|
|
503
543
|
const isWhitelisted = await peContract.isContractWhitelisted(walletAddress, contract.address).catch(() => false);
|
|
@@ -1009,7 +1049,7 @@ function registerWalletCommands(program) {
|
|
|
1009
1049
|
console.log(colors_1.c.dim(` ◈ --force: cleared wallet config. Factory reset to ${config.walletFactoryAddress} (V6).`));
|
|
1010
1050
|
}
|
|
1011
1051
|
if (opts.dryRun) {
|
|
1012
|
-
const factoryAddr =
|
|
1052
|
+
const factoryAddr = config_1.NETWORK_DEFAULTS[config.network]?.walletFactoryAddress ?? "(not configured)";
|
|
1013
1053
|
const chainId = config.network === "base-mainnet" ? 8453 : 84532;
|
|
1014
1054
|
console.log();
|
|
1015
1055
|
console.log(" " + colors_1.c.dim("── Dry run: wallet deploy ──────────────────────────────────────"));
|
|
@@ -1145,6 +1185,7 @@ function registerWalletCommands(program) {
|
|
|
1145
1185
|
console.error("Could not find WalletDeployed/WalletCreated event in receipt. Check the transaction on-chain.");
|
|
1146
1186
|
process.exit(1);
|
|
1147
1187
|
}
|
|
1188
|
+
await assertAddressHasCode(provider, walletAddress, "Deployed wallet");
|
|
1148
1189
|
config.walletContractAddress = walletAddress;
|
|
1149
1190
|
config.ownerAddress = account;
|
|
1150
1191
|
(0, config_1.saveConfig)(config);
|
|
@@ -1346,13 +1387,11 @@ function registerWalletCommands(program) {
|
|
|
1346
1387
|
process.exit(1);
|
|
1347
1388
|
}
|
|
1348
1389
|
// Resolve protocol contracts to whitelist
|
|
1349
|
-
const handshakeAddress = config.handshakeAddress ??
|
|
1350
|
-
config_1.NETWORK_DEFAULTS[config.network]?.handshakeAddress ??
|
|
1351
|
-
"0x4F5A38Bb746d7E5d49d8fd26CA6beD141Ec2DDb3";
|
|
1390
|
+
const handshakeAddress = config_1.NETWORK_DEFAULTS[config.network]?.handshakeAddress ?? "";
|
|
1352
1391
|
const protocolContracts = [
|
|
1353
|
-
{ address:
|
|
1354
|
-
{ address:
|
|
1355
|
-
{ address:
|
|
1392
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.serviceAgreementAddress ?? "", name: "ServiceAgreement" },
|
|
1393
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.computeAgreementAddress ?? "", name: "ComputeAgreement" },
|
|
1394
|
+
{ address: config_1.NETWORK_DEFAULTS[config.network]?.subscriptionAgreementAddress ?? "", name: "SubscriptionAgreement" },
|
|
1356
1395
|
{ address: handshakeAddress, name: "Handshake" },
|
|
1357
1396
|
].filter(pc => pc.address && pc.address !== "");
|
|
1358
1397
|
// Pre-check on-chain state to count pending txs and decide what to skip
|
|
@@ -1426,23 +1465,31 @@ function registerWalletCommands(program) {
|
|
|
1426
1465
|
return;
|
|
1427
1466
|
}
|
|
1428
1467
|
console.log(" " + colors_1.c.dim(`◈ ${pendingTxCount} transaction(s) pending — your phone will need to approve each.`));
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1468
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
1469
|
+
actionType: "wallet_onboard",
|
|
1470
|
+
signerMode: "owner_wallet",
|
|
1471
|
+
chainId,
|
|
1472
|
+
walletAddress,
|
|
1473
|
+
txs: Array.from({ length: pendingTxCount }, () => ({ to: walletAddress, data: "0x", value: "0x0" })),
|
|
1474
|
+
ui: {
|
|
1475
|
+
title: "Wallet onboarding",
|
|
1476
|
+
summary: `Approve ${pendingTxCount} wallet onboarding transaction(s)`,
|
|
1477
|
+
risk: "medium",
|
|
1478
|
+
},
|
|
1479
|
+
metadata: {
|
|
1480
|
+
expectedApprovalCount: pendingTxCount,
|
|
1481
|
+
sourceRuntime: "cli",
|
|
1482
|
+
hardware: !!opts.hardware,
|
|
1483
|
+
},
|
|
1484
|
+
}, config);
|
|
1485
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
1486
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
1487
|
+
process.exit(1);
|
|
1488
|
+
}
|
|
1489
|
+
const { client, session, account } = approval.session;
|
|
1435
1490
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
1436
1491
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
1437
1492
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
1438
|
-
if (telegramOpts) {
|
|
1439
|
-
await (0, telegram_notify_1.sendTelegramMessage)({
|
|
1440
|
-
botToken: telegramOpts.botToken,
|
|
1441
|
-
chatId: telegramOpts.chatId,
|
|
1442
|
-
threadId: telegramOpts.threadId,
|
|
1443
|
-
text: `◈ arc402 wallet onboard: ${pendingTxCount} txs pending for ${shortAddr}`,
|
|
1444
|
-
});
|
|
1445
|
-
}
|
|
1446
1493
|
const sendTx = async (call, description) => {
|
|
1447
1494
|
const txSpin = (0, spinner_1.startSpinner)(description);
|
|
1448
1495
|
const hash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, call);
|
|
@@ -1450,24 +1497,22 @@ function registerWalletCommands(program) {
|
|
|
1450
1497
|
txSpin.succeed(description);
|
|
1451
1498
|
return hash;
|
|
1452
1499
|
};
|
|
1453
|
-
const executeIface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_EXECUTE_ABI);
|
|
1454
1500
|
const govIface = new ethers_1.ethers.Interface(abis_1.POLICY_ENGINE_GOVERNANCE_ABI);
|
|
1455
1501
|
const limitsIface = new ethers_1.ethers.Interface(abis_1.POLICY_ENGINE_LIMITS_ABI);
|
|
1456
1502
|
const ownerIface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_OWNER_ABI);
|
|
1503
|
+
const walletOwnerReader = new ethers_1.ethers.Contract(walletAddress, ["function owner() external view returns (address)"], provider);
|
|
1504
|
+
const walletOwner = await walletOwnerReader.owner().catch(() => account);
|
|
1505
|
+
if (walletOwner.toLowerCase() !== account.toLowerCase()) {
|
|
1506
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(`Connected wallet ${account} is not the ARC402Wallet owner ${walletOwner}.`));
|
|
1507
|
+
process.exit(1);
|
|
1508
|
+
}
|
|
1457
1509
|
console.log("\n" + colors_1.c.dim("── Onboarding ceremony ────────────────────────────────────────"));
|
|
1458
1510
|
// 1. registerWallet
|
|
1459
1511
|
if (needsRegister) {
|
|
1460
|
-
const registerCalldata = govIface.encodeFunctionData("registerWallet", [walletAddress,
|
|
1512
|
+
const registerCalldata = govIface.encodeFunctionData("registerWallet", [walletAddress, walletOwner]);
|
|
1461
1513
|
await sendTx({
|
|
1462
|
-
to:
|
|
1463
|
-
data:
|
|
1464
|
-
target: policyAddress,
|
|
1465
|
-
data: registerCalldata,
|
|
1466
|
-
value: 0n,
|
|
1467
|
-
minReturnValue: 0n,
|
|
1468
|
-
maxApprovalAmount: 0n,
|
|
1469
|
-
approvalToken: ethers_1.ethers.ZeroAddress,
|
|
1470
|
-
}]),
|
|
1514
|
+
to: policyAddress,
|
|
1515
|
+
data: registerCalldata,
|
|
1471
1516
|
value: "0x0",
|
|
1472
1517
|
}, "registerWallet on PolicyEngine");
|
|
1473
1518
|
}
|
|
@@ -1592,15 +1637,33 @@ function registerWalletCommands(program) {
|
|
|
1592
1637
|
process.exit(1);
|
|
1593
1638
|
}
|
|
1594
1639
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
1595
|
-
const
|
|
1640
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
1641
|
+
actionType: "spend_limit_set",
|
|
1642
|
+
signerMode: "owner_wallet",
|
|
1643
|
+
chainId,
|
|
1644
|
+
walletAddress: walletAddr,
|
|
1645
|
+
txs: [{
|
|
1646
|
+
to: policyAddress,
|
|
1647
|
+
data: policyInterface.encodeFunctionData("setCategoryLimitFor", [walletAddr, opts.category, amount]),
|
|
1648
|
+
value: "0x0",
|
|
1649
|
+
}],
|
|
1650
|
+
ui: {
|
|
1651
|
+
title: "Set spend limit",
|
|
1652
|
+
summary: `Approve spend limit: ${opts.category} → ${opts.amount} ETH`,
|
|
1653
|
+
risk: "medium",
|
|
1654
|
+
},
|
|
1655
|
+
metadata: { sourceRuntime: "cli" },
|
|
1656
|
+
}, config);
|
|
1657
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
1658
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
1659
|
+
process.exit(1);
|
|
1660
|
+
}
|
|
1661
|
+
const { client, session, account } = approval.session;
|
|
1662
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, {
|
|
1596
1663
|
to: policyAddress,
|
|
1597
1664
|
data: policyInterface.encodeFunctionData("setCategoryLimitFor", [walletAddr, opts.category, amount]),
|
|
1598
1665
|
value: "0x0",
|
|
1599
|
-
})
|
|
1600
|
-
botToken: config.telegramBotToken,
|
|
1601
|
-
chatId: config.telegramChatId,
|
|
1602
|
-
threadId: config.telegramThreadId,
|
|
1603
|
-
} : undefined, config);
|
|
1666
|
+
});
|
|
1604
1667
|
console.log(`\nTransaction submitted: ${txHash}`);
|
|
1605
1668
|
await provider.waitForTransaction(txHash);
|
|
1606
1669
|
console.log(`Spend limit for ${opts.category} set to ${opts.amount} ETH`);
|
|
@@ -1643,15 +1706,33 @@ function registerWalletCommands(program) {
|
|
|
1643
1706
|
const policyInterface = new ethers_1.ethers.Interface(abis_1.POLICY_ENGINE_LIMITS_ABI);
|
|
1644
1707
|
if (config.walletConnectProjectId) {
|
|
1645
1708
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
1646
|
-
const
|
|
1709
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
1710
|
+
actionType: "policy_update",
|
|
1711
|
+
signerMode: "owner_wallet",
|
|
1712
|
+
chainId,
|
|
1713
|
+
walletAddress: walletAddr,
|
|
1714
|
+
txs: [{
|
|
1715
|
+
to: policyAddress,
|
|
1716
|
+
data: policyInterface.encodeFunctionData("setDailyLimitFor", [walletAddr, opts.category, amount]),
|
|
1717
|
+
value: "0x0",
|
|
1718
|
+
}],
|
|
1719
|
+
ui: {
|
|
1720
|
+
title: "Set daily limit",
|
|
1721
|
+
summary: `Approve daily limit: ${opts.category} → ${opts.amount} ETH`,
|
|
1722
|
+
risk: "medium",
|
|
1723
|
+
},
|
|
1724
|
+
metadata: { sourceRuntime: "cli" },
|
|
1725
|
+
}, config);
|
|
1726
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
1727
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
1728
|
+
process.exit(1);
|
|
1729
|
+
}
|
|
1730
|
+
const { client, session, account } = approval.session;
|
|
1731
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, {
|
|
1647
1732
|
to: policyAddress,
|
|
1648
1733
|
data: policyInterface.encodeFunctionData("setDailyLimitFor", [walletAddr, opts.category, amount]),
|
|
1649
1734
|
value: "0x0",
|
|
1650
|
-
})
|
|
1651
|
-
botToken: config.telegramBotToken,
|
|
1652
|
-
chatId: config.telegramChatId,
|
|
1653
|
-
threadId: config.telegramThreadId,
|
|
1654
|
-
} : undefined, config);
|
|
1735
|
+
});
|
|
1655
1736
|
await provider.waitForTransaction(txHash);
|
|
1656
1737
|
console.log(`Daily limit for ${opts.category} set to ${opts.amount} ETH (12/24h rolling window)`);
|
|
1657
1738
|
}
|
|
@@ -1692,24 +1773,30 @@ function registerWalletCommands(program) {
|
|
|
1692
1773
|
];
|
|
1693
1774
|
const policyInterface = new ethers_1.ethers.Interface(abis_1.POLICY_ENGINE_LIMITS_ABI);
|
|
1694
1775
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
1695
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId ? {
|
|
1696
|
-
botToken: config.telegramBotToken,
|
|
1697
|
-
chatId: config.telegramChatId,
|
|
1698
|
-
threadId: config.telegramThreadId,
|
|
1699
|
-
} : undefined;
|
|
1700
1776
|
console.log(colors_1.c.white("\n◈ Spend limit init — 1 connection, 5 approvals\n"));
|
|
1701
1777
|
console.log(colors_1.c.dim(" Connect once — MetaMask will prompt 5 times in sequence."));
|
|
1702
|
-
|
|
1703
|
-
|
|
1778
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
1779
|
+
actionType: "spend_limit_set",
|
|
1780
|
+
signerMode: "owner_wallet",
|
|
1781
|
+
chainId,
|
|
1782
|
+
walletAddress: walletAddr,
|
|
1783
|
+
txs: categories.map(() => ({ to: policyAddress, data: "0x", value: "0x0" })),
|
|
1784
|
+
ui: {
|
|
1785
|
+
title: "Initialize spend limits",
|
|
1786
|
+
summary: "Connect wallet for spend limit setup (5 approvals)",
|
|
1787
|
+
risk: "medium",
|
|
1788
|
+
},
|
|
1789
|
+
metadata: { expectedApprovalCount: categories.length, sourceRuntime: "cli" },
|
|
1790
|
+
}, config);
|
|
1791
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
1792
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
1793
|
+
process.exit(1);
|
|
1794
|
+
}
|
|
1795
|
+
const { client, session, account } = approval.session;
|
|
1704
1796
|
for (const cat of categories) {
|
|
1705
1797
|
const amount = ethers_1.ethers.parseEther(cat.amount);
|
|
1706
1798
|
const data = policyInterface.encodeFunctionData("setCategoryLimitFor", [walletAddr, cat.name, amount]);
|
|
1707
1799
|
console.log(colors_1.c.dim(`\n Setting ${cat.name} → ${cat.amount} ETH...`));
|
|
1708
|
-
// Send Telegram notification for each
|
|
1709
|
-
if (telegramOpts) {
|
|
1710
|
-
const { sendTelegramMessage: sendTg } = await Promise.resolve().then(() => __importStar(require("../telegram-notify.js")));
|
|
1711
|
-
await sendTg({ ...telegramOpts, text: `Approve spend limit: ${cat.name} → ${cat.amount} ETH` });
|
|
1712
|
-
}
|
|
1713
1800
|
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, {
|
|
1714
1801
|
to: policyAddress,
|
|
1715
1802
|
data,
|
|
@@ -1754,14 +1841,33 @@ function registerWalletCommands(program) {
|
|
|
1754
1841
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
1755
1842
|
console.log(`Current policy: ${currentPolicy}`);
|
|
1756
1843
|
console.log(`New policy: ${policyIdHex}`);
|
|
1757
|
-
const
|
|
1758
|
-
|
|
1759
|
-
:
|
|
1760
|
-
|
|
1844
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
1845
|
+
actionType: "policy_update",
|
|
1846
|
+
signerMode: "owner_wallet",
|
|
1847
|
+
chainId,
|
|
1848
|
+
walletAddress: config.walletContractAddress,
|
|
1849
|
+
txs: [{
|
|
1850
|
+
to: config.walletContractAddress,
|
|
1851
|
+
data: ownerInterface.encodeFunctionData("updatePolicy", [policyIdHex]),
|
|
1852
|
+
value: "0x0",
|
|
1853
|
+
}],
|
|
1854
|
+
ui: {
|
|
1855
|
+
title: "Update active policy",
|
|
1856
|
+
summary: `Approve: update policy to ${policyIdHex}`,
|
|
1857
|
+
risk: "medium",
|
|
1858
|
+
},
|
|
1859
|
+
metadata: { sourceRuntime: "cli" },
|
|
1860
|
+
}, config);
|
|
1861
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
1862
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
1863
|
+
process.exit(1);
|
|
1864
|
+
}
|
|
1865
|
+
const { client, session, account } = approval.session;
|
|
1866
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, {
|
|
1761
1867
|
to: config.walletContractAddress,
|
|
1762
1868
|
data: ownerInterface.encodeFunctionData("updatePolicy", [policyIdHex]),
|
|
1763
1869
|
value: "0x0",
|
|
1764
|
-
})
|
|
1870
|
+
});
|
|
1765
1871
|
await provider.waitForTransaction(txHash);
|
|
1766
1872
|
console.log("\n" + colors_1.c.success + colors_1.c.white(" Active policy updated"));
|
|
1767
1873
|
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(txHash));
|
|
@@ -1832,10 +1938,35 @@ function registerWalletCommands(program) {
|
|
|
1832
1938
|
const chainId = config.network === "base-mainnet" ? 8453 : 84532;
|
|
1833
1939
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
1834
1940
|
const walletInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_GUARDIAN_ABI);
|
|
1835
|
-
const
|
|
1836
|
-
|
|
1837
|
-
:
|
|
1838
|
-
|
|
1941
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
1942
|
+
actionType: "custom_tx",
|
|
1943
|
+
signerMode: "owner_wallet",
|
|
1944
|
+
chainId,
|
|
1945
|
+
walletAddress: config.walletContractAddress,
|
|
1946
|
+
txs: [{
|
|
1947
|
+
to: config.walletContractAddress,
|
|
1948
|
+
data: walletInterface.encodeFunctionData("unfreeze", []),
|
|
1949
|
+
value: "0x0",
|
|
1950
|
+
}],
|
|
1951
|
+
ui: {
|
|
1952
|
+
title: "Unfreeze wallet",
|
|
1953
|
+
summary: "Approve: unfreeze ARC402Wallet",
|
|
1954
|
+
risk: "high",
|
|
1955
|
+
},
|
|
1956
|
+
metadata: { sourceRuntime: "cli", hardware: !!opts.hardware },
|
|
1957
|
+
});
|
|
1958
|
+
if (execution.kind === "passkey") {
|
|
1959
|
+
if (opts.json) {
|
|
1960
|
+
console.log(JSON.stringify({ txHash: execution.txHash, walletAddress: config.walletContractAddress, userOpHash: execution.userOpHash }));
|
|
1961
|
+
}
|
|
1962
|
+
else {
|
|
1963
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(` Wallet ${config.walletContractAddress} unfrozen`));
|
|
1964
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
1965
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
1966
|
+
}
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
const { client, session, account } = execution.session;
|
|
1839
1970
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
1840
1971
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
1841
1972
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
@@ -1893,10 +2024,37 @@ function registerWalletCommands(program) {
|
|
|
1893
2024
|
const walletInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_GUARDIAN_ABI);
|
|
1894
2025
|
console.log(`\nGuardian address: ${guardianWallet.address}`);
|
|
1895
2026
|
console.log(`Wallet contract: ${config.walletContractAddress}`);
|
|
1896
|
-
const
|
|
1897
|
-
|
|
1898
|
-
:
|
|
1899
|
-
|
|
2027
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
2028
|
+
actionType: "custom_tx",
|
|
2029
|
+
signerMode: "owner_wallet",
|
|
2030
|
+
chainId,
|
|
2031
|
+
walletAddress: config.walletContractAddress,
|
|
2032
|
+
txs: [{
|
|
2033
|
+
to: config.walletContractAddress,
|
|
2034
|
+
data: walletInterface.encodeFunctionData("setGuardian", [guardianWallet.address]),
|
|
2035
|
+
value: "0x0",
|
|
2036
|
+
}],
|
|
2037
|
+
ui: {
|
|
2038
|
+
title: "Set guardian",
|
|
2039
|
+
summary: `Approve: set guardian to ${guardianWallet.address}`,
|
|
2040
|
+
risk: "high",
|
|
2041
|
+
},
|
|
2042
|
+
metadata: { sourceRuntime: "cli", hardware: !!opts.hardware },
|
|
2043
|
+
});
|
|
2044
|
+
if (execution.kind === "passkey") {
|
|
2045
|
+
saveGuardianKey(guardianWallet.privateKey);
|
|
2046
|
+
if (config.guardianPrivateKey)
|
|
2047
|
+
delete config.guardianPrivateKey;
|
|
2048
|
+
config.guardianAddress = guardianWallet.address;
|
|
2049
|
+
(0, config_1.saveConfig)(config);
|
|
2050
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(` Guardian set to: ${guardianWallet.address}`));
|
|
2051
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
2052
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
2053
|
+
console.log(" " + colors_1.c.dim("Guardian private key saved to ~/.arc402/guardian.key (chmod 400)."));
|
|
2054
|
+
console.log(" " + colors_1.c.warning + " " + colors_1.c.yellow("The guardian key can freeze your wallet. Store it separately from your hot key."));
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
const { client, session, account } = execution.session;
|
|
1900
2058
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
1901
2059
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
1902
2060
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
@@ -1992,10 +2150,36 @@ function registerWalletCommands(program) {
|
|
|
1992
2150
|
console.log(` Value: 0x0`);
|
|
1993
2151
|
return;
|
|
1994
2152
|
}
|
|
1995
|
-
const
|
|
1996
|
-
|
|
1997
|
-
:
|
|
1998
|
-
|
|
2153
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
2154
|
+
actionType: "custom_tx",
|
|
2155
|
+
signerMode: "owner_wallet",
|
|
2156
|
+
chainId,
|
|
2157
|
+
walletAddress: config.walletContractAddress,
|
|
2158
|
+
txs: [{ to: config.walletContractAddress, data: calldata, value: "0x0" }],
|
|
2159
|
+
ui: {
|
|
2160
|
+
title: "Propose registry upgrade",
|
|
2161
|
+
summary: "Approve registry upgrade proposal on ARC402Wallet",
|
|
2162
|
+
risk: "high",
|
|
2163
|
+
},
|
|
2164
|
+
metadata: {
|
|
2165
|
+
sourceRuntime: "cli",
|
|
2166
|
+
hardware: !!opts.hardware,
|
|
2167
|
+
},
|
|
2168
|
+
});
|
|
2169
|
+
if (execution.kind === "passkey") {
|
|
2170
|
+
const unlockAt = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000);
|
|
2171
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(" Registry upgrade proposed"));
|
|
2172
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
2173
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
2174
|
+
console.log(" " + colors_1.c.dim("Unlock at:") + " " + colors_1.c.white(unlockAt.toISOString()) + colors_1.c.dim(" (approximately)"));
|
|
2175
|
+
console.log(`\nNext steps:`);
|
|
2176
|
+
console.log(` Wait 2 days, then run:`);
|
|
2177
|
+
console.log(` arc402 wallet execute-registry-upgrade`);
|
|
2178
|
+
console.log(`\nTo cancel before execution:`);
|
|
2179
|
+
console.log(` arc402 wallet cancel-registry-upgrade`);
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
const { client, session, account } = execution.session;
|
|
1999
2183
|
const networkName = chainId === 8453 ? "Base" : "Base Sepolia";
|
|
2000
2184
|
const shortAddr = `${account.slice(0, 6)}...${account.slice(-5)}`;
|
|
2001
2185
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${shortAddr} on ${networkName}`));
|
|
@@ -2061,15 +2245,39 @@ function registerWalletCommands(program) {
|
|
|
2061
2245
|
}
|
|
2062
2246
|
console.log(`Pending registry: ${pendingRegistry}`);
|
|
2063
2247
|
console.log("Timelock elapsed — proceeding with executeRegistryUpdate()");
|
|
2064
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
2065
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2066
|
-
: undefined;
|
|
2067
2248
|
const walletInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_REGISTRY_ABI);
|
|
2068
|
-
const
|
|
2249
|
+
const txData = {
|
|
2069
2250
|
to: config.walletContractAddress,
|
|
2070
2251
|
data: walletInterface.encodeFunctionData("executeRegistryUpdate", []),
|
|
2071
2252
|
value: "0x0",
|
|
2072
|
-
}
|
|
2253
|
+
};
|
|
2254
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
2255
|
+
actionType: "custom_tx",
|
|
2256
|
+
signerMode: "owner_wallet",
|
|
2257
|
+
chainId,
|
|
2258
|
+
walletAddress: config.walletContractAddress,
|
|
2259
|
+
txs: [txData],
|
|
2260
|
+
ui: {
|
|
2261
|
+
title: "Execute registry upgrade",
|
|
2262
|
+
summary: "Approve registry upgrade execution on ARC402Wallet",
|
|
2263
|
+
risk: "high",
|
|
2264
|
+
},
|
|
2265
|
+
metadata: { sourceRuntime: "cli" },
|
|
2266
|
+
});
|
|
2267
|
+
if (execution.kind === "passkey") {
|
|
2268
|
+
let confirmedRegistry = pendingRegistry;
|
|
2269
|
+
try {
|
|
2270
|
+
confirmedRegistry = await walletContract.registry();
|
|
2271
|
+
}
|
|
2272
|
+
catch { /* use pendingRegistry as fallback */ }
|
|
2273
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(" Registry upgrade executed"));
|
|
2274
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
2275
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
2276
|
+
console.log(" " + colors_1.c.dim("New registry:") + " " + colors_1.c.white(confirmedRegistry));
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
const { client, session, account } = execution.session;
|
|
2280
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2073
2281
|
// Wait for tx to confirm, then read back the active registry (J6-02)
|
|
2074
2282
|
await provider.waitForTransaction(txHash);
|
|
2075
2283
|
let confirmedRegistry = pendingRegistry;
|
|
@@ -2136,18 +2344,33 @@ function registerWalletCommands(program) {
|
|
|
2136
2344
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
2137
2345
|
console.log(`PolicyEngine: ${policyAddress}`);
|
|
2138
2346
|
console.log(`Whitelisting: ${checksumTarget}`);
|
|
2139
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
2140
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2141
|
-
: undefined;
|
|
2142
2347
|
const policyIface = new ethers_1.ethers.Interface(peAbi);
|
|
2143
|
-
const
|
|
2348
|
+
const txData = {
|
|
2144
2349
|
to: policyAddress,
|
|
2145
2350
|
data: policyIface.encodeFunctionData("whitelistContract", [
|
|
2146
2351
|
config.walletContractAddress,
|
|
2147
2352
|
checksumTarget,
|
|
2148
2353
|
]),
|
|
2149
2354
|
value: "0x0",
|
|
2150
|
-
}
|
|
2355
|
+
};
|
|
2356
|
+
const { client, session, account } = await requestWalletConnectApprovalSession(config, {
|
|
2357
|
+
actionType: "policy_update",
|
|
2358
|
+
signerMode: "owner_wallet",
|
|
2359
|
+
chainId,
|
|
2360
|
+
walletAddress: config.walletContractAddress,
|
|
2361
|
+
txs: [txData],
|
|
2362
|
+
ui: {
|
|
2363
|
+
title: "Whitelist contract",
|
|
2364
|
+
summary: `Approve: whitelist ${checksumTarget} on PolicyEngine for your wallet`,
|
|
2365
|
+
risk: "high",
|
|
2366
|
+
},
|
|
2367
|
+
metadata: {
|
|
2368
|
+
category: "policy",
|
|
2369
|
+
sourceRuntime: "cli",
|
|
2370
|
+
hardware: !!opts.hardware,
|
|
2371
|
+
},
|
|
2372
|
+
});
|
|
2373
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2151
2374
|
await provider.waitForTransaction(txHash);
|
|
2152
2375
|
if (opts.json) {
|
|
2153
2376
|
console.log(JSON.stringify({ ok: true, txHash, wallet: config.walletContractAddress, target: checksumTarget }));
|
|
@@ -2194,14 +2417,33 @@ function registerWalletCommands(program) {
|
|
|
2194
2417
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
2195
2418
|
console.log(`Current interceptor: ${currentInterceptor}`);
|
|
2196
2419
|
console.log(`New interceptor: ${checksumAddress}`);
|
|
2197
|
-
const
|
|
2198
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2199
|
-
: undefined;
|
|
2200
|
-
const { txHash } = await (0, walletconnect_1.requestPhoneWalletSignature)(config.walletConnectProjectId, chainId, () => ({
|
|
2420
|
+
const txData = {
|
|
2201
2421
|
to: config.walletContractAddress,
|
|
2202
2422
|
data: ownerInterface.encodeFunctionData("setAuthorizedInterceptor", [checksumAddress]),
|
|
2203
2423
|
value: "0x0",
|
|
2204
|
-
}
|
|
2424
|
+
};
|
|
2425
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
2426
|
+
actionType: "custom_tx",
|
|
2427
|
+
signerMode: "owner_wallet",
|
|
2428
|
+
chainId,
|
|
2429
|
+
walletAddress: config.walletContractAddress,
|
|
2430
|
+
txs: [txData],
|
|
2431
|
+
ui: {
|
|
2432
|
+
title: "Set X402 interceptor",
|
|
2433
|
+
summary: `Approve: set X402 interceptor to ${checksumAddress}`,
|
|
2434
|
+
risk: "high",
|
|
2435
|
+
},
|
|
2436
|
+
metadata: { sourceRuntime: "cli" },
|
|
2437
|
+
});
|
|
2438
|
+
if (execution.kind === "passkey") {
|
|
2439
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(" X402 interceptor updated"));
|
|
2440
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
2441
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
2442
|
+
console.log(" " + colors_1.c.dim("Interceptor:") + " " + colors_1.c.white(checksumAddress));
|
|
2443
|
+
return;
|
|
2444
|
+
}
|
|
2445
|
+
const { client, session, account } = execution.session;
|
|
2446
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2205
2447
|
await provider.waitForTransaction(txHash);
|
|
2206
2448
|
console.log("\n" + colors_1.c.success + colors_1.c.white(" X402 interceptor updated"));
|
|
2207
2449
|
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(txHash));
|
|
@@ -2245,14 +2487,36 @@ function registerWalletCommands(program) {
|
|
|
2245
2487
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
2246
2488
|
console.log(`Current limit: ${currentLimit}`);
|
|
2247
2489
|
console.log(`New limit: ${limitEth} ETH (max ETH per rolling window)`);
|
|
2248
|
-
const
|
|
2249
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2250
|
-
: undefined;
|
|
2251
|
-
const { txHash } = await (0, walletconnect_1.requestPhoneWalletSignature)(config.walletConnectProjectId, chainId, () => ({
|
|
2490
|
+
const txData = {
|
|
2252
2491
|
to: config.walletContractAddress,
|
|
2253
2492
|
data: ownerInterface.encodeFunctionData("setVelocityLimit", [limitWei]),
|
|
2254
2493
|
value: "0x0",
|
|
2255
|
-
}
|
|
2494
|
+
};
|
|
2495
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
2496
|
+
actionType: "policy_update",
|
|
2497
|
+
signerMode: "owner_wallet",
|
|
2498
|
+
chainId,
|
|
2499
|
+
walletAddress: config.walletContractAddress,
|
|
2500
|
+
txs: [txData],
|
|
2501
|
+
ui: {
|
|
2502
|
+
title: "Set velocity limit",
|
|
2503
|
+
summary: `Approve: set velocity limit to ${limitEth} ETH`,
|
|
2504
|
+
risk: "high",
|
|
2505
|
+
},
|
|
2506
|
+
metadata: {
|
|
2507
|
+
category: "policy",
|
|
2508
|
+
sourceRuntime: "cli",
|
|
2509
|
+
},
|
|
2510
|
+
});
|
|
2511
|
+
if (execution.kind === "passkey") {
|
|
2512
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(" Velocity limit updated"));
|
|
2513
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
2514
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
2515
|
+
console.log(" " + colors_1.c.dim("New limit:") + " " + colors_1.c.white(`${limitEth} ETH per rolling window`));
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
const { client, session, account } = execution.session;
|
|
2519
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2256
2520
|
await provider.waitForTransaction(txHash);
|
|
2257
2521
|
console.log("\n" + colors_1.c.success + colors_1.c.white(" Velocity limit updated"));
|
|
2258
2522
|
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(txHash));
|
|
@@ -2260,9 +2524,8 @@ function registerWalletCommands(program) {
|
|
|
2260
2524
|
});
|
|
2261
2525
|
// ─── register-policy ───────────────────────────────────────────────────────
|
|
2262
2526
|
//
|
|
2263
|
-
// Calls registerWallet(walletAddress, ownerAddress) on PolicyEngine
|
|
2264
|
-
//
|
|
2265
|
-
// so this must go through the wallet contract — not called directly by the owner key.
|
|
2527
|
+
// Calls registerWallet(walletAddress, ownerAddress) directly on PolicyEngine
|
|
2528
|
+
// from the owner wallet.
|
|
2266
2529
|
wallet.command("register-policy")
|
|
2267
2530
|
.description("Register this wallet on PolicyEngine (required before spend limits can be set)")
|
|
2268
2531
|
.option("--hardware", "Hardware wallet mode: show raw wc: URI only")
|
|
@@ -2299,33 +2562,45 @@ function registerWalletCommands(program) {
|
|
|
2299
2562
|
}
|
|
2300
2563
|
}
|
|
2301
2564
|
}
|
|
2565
|
+
const resolvedOwnerAddress = ownerAddress;
|
|
2302
2566
|
// Encode registerWallet(wallet, owner) calldata — called on PolicyEngine
|
|
2303
2567
|
const policyInterface = new ethers_1.ethers.Interface([
|
|
2304
2568
|
"function registerWallet(address wallet, address owner) external",
|
|
2305
2569
|
]);
|
|
2306
2570
|
const registerCalldata = policyInterface.encodeFunctionData("registerWallet", [
|
|
2307
2571
|
config.walletContractAddress,
|
|
2308
|
-
|
|
2572
|
+
resolvedOwnerAddress,
|
|
2309
2573
|
]);
|
|
2310
|
-
const executeInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_EXECUTE_ABI);
|
|
2311
2574
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
2312
2575
|
console.log(`PolicyEngine: ${policyAddress}`);
|
|
2313
|
-
console.log(`Owner: ${
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
:
|
|
2317
|
-
const { txHash } = await (0, walletconnect_1.requestPhoneWalletSignature)(config.walletConnectProjectId, chainId, () => ({
|
|
2318
|
-
to: config.walletContractAddress,
|
|
2319
|
-
data: executeInterface.encodeFunctionData("executeContractCall", [{
|
|
2320
|
-
target: policyAddress,
|
|
2321
|
-
data: registerCalldata,
|
|
2322
|
-
value: 0n,
|
|
2323
|
-
minReturnValue: 0n,
|
|
2324
|
-
maxApprovalAmount: 0n,
|
|
2325
|
-
approvalToken: ethers_1.ethers.ZeroAddress,
|
|
2326
|
-
}]),
|
|
2576
|
+
console.log(`Owner: ${resolvedOwnerAddress}`);
|
|
2577
|
+
const txData = {
|
|
2578
|
+
to: policyAddress,
|
|
2579
|
+
data: registerCalldata,
|
|
2327
2580
|
value: "0x0",
|
|
2328
|
-
}
|
|
2581
|
+
};
|
|
2582
|
+
const { client, session, account } = await requestWalletConnectApprovalSession(config, {
|
|
2583
|
+
actionType: "policy_update",
|
|
2584
|
+
signerMode: "owner_wallet",
|
|
2585
|
+
chainId,
|
|
2586
|
+
walletAddress: config.walletContractAddress,
|
|
2587
|
+
txs: [txData],
|
|
2588
|
+
ui: {
|
|
2589
|
+
title: "Register wallet on PolicyEngine",
|
|
2590
|
+
summary: "Approve: register wallet on PolicyEngine",
|
|
2591
|
+
risk: "high",
|
|
2592
|
+
},
|
|
2593
|
+
metadata: {
|
|
2594
|
+
category: "policy",
|
|
2595
|
+
sourceRuntime: "cli",
|
|
2596
|
+
hardware: !!opts.hardware,
|
|
2597
|
+
},
|
|
2598
|
+
});
|
|
2599
|
+
if (account.toLowerCase() !== resolvedOwnerAddress.toLowerCase()) {
|
|
2600
|
+
console.error(`Connected wallet ${account} is not the wallet owner ${resolvedOwnerAddress}.`);
|
|
2601
|
+
process.exit(1);
|
|
2602
|
+
}
|
|
2603
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2329
2604
|
await provider.waitForTransaction(txHash);
|
|
2330
2605
|
console.log("\n" + colors_1.c.success + colors_1.c.white(" Wallet registered on PolicyEngine"));
|
|
2331
2606
|
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(txHash));
|
|
@@ -2374,15 +2649,33 @@ function registerWalletCommands(program) {
|
|
|
2374
2649
|
console.log(` Pending address: ${pendingRegistry}`);
|
|
2375
2650
|
console.log(` Timelock: ${timelockStatus}`);
|
|
2376
2651
|
console.log(`\nCancelling pending registry upgrade to: ${pendingRegistry}`);
|
|
2377
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
2378
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2379
|
-
: undefined;
|
|
2380
2652
|
const walletInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_REGISTRY_ABI);
|
|
2381
|
-
const
|
|
2653
|
+
const txData = {
|
|
2382
2654
|
to: config.walletContractAddress,
|
|
2383
2655
|
data: walletInterface.encodeFunctionData("cancelRegistryUpdate", []),
|
|
2384
2656
|
value: "0x0",
|
|
2385
|
-
}
|
|
2657
|
+
};
|
|
2658
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
2659
|
+
actionType: "custom_tx",
|
|
2660
|
+
signerMode: "owner_wallet",
|
|
2661
|
+
chainId,
|
|
2662
|
+
walletAddress: config.walletContractAddress,
|
|
2663
|
+
txs: [txData],
|
|
2664
|
+
ui: {
|
|
2665
|
+
title: "Cancel registry upgrade",
|
|
2666
|
+
summary: "Approve registry upgrade cancellation on ARC402Wallet",
|
|
2667
|
+
risk: "high",
|
|
2668
|
+
},
|
|
2669
|
+
metadata: { sourceRuntime: "cli" },
|
|
2670
|
+
});
|
|
2671
|
+
if (execution.kind === "passkey") {
|
|
2672
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(" Registry upgrade cancelled"));
|
|
2673
|
+
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(execution.txHash));
|
|
2674
|
+
console.log(" " + colors_1.c.dim("UserOp:") + " " + colors_1.c.white(execution.userOpHash));
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2677
|
+
const { client, session, account } = execution.session;
|
|
2678
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2386
2679
|
console.log("\n" + colors_1.c.success + colors_1.c.white(" Registry upgrade cancelled"));
|
|
2387
2680
|
console.log(" " + colors_1.c.dim("Tx:") + " " + colors_1.c.white(txHash));
|
|
2388
2681
|
});
|
|
@@ -2523,11 +2816,6 @@ function registerWalletCommands(program) {
|
|
|
2523
2816
|
return;
|
|
2524
2817
|
}
|
|
2525
2818
|
// ── Step 6: connect WalletConnect once, send all transactions ─────────
|
|
2526
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
2527
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2528
|
-
: undefined;
|
|
2529
|
-
console.log("\nConnecting wallet...");
|
|
2530
|
-
const { client, session, account } = await (0, walletconnect_1.connectPhoneWallet)(config.walletConnectProjectId, chainId, config, { telegramOpts, prompt: "Approve governance setup transactions on ARC402Wallet" });
|
|
2531
2819
|
const provider = new ethers_1.ethers.JsonRpcProvider(config.rpcUrl);
|
|
2532
2820
|
const ownerInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_OWNER_ABI);
|
|
2533
2821
|
const guardianInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_GUARDIAN_ABI);
|
|
@@ -2549,6 +2837,33 @@ function registerWalletCommands(program) {
|
|
|
2549
2837
|
govAlreadyDefiEnabled = await policyGovContract.defiAccessEnabled(config.walletContractAddress);
|
|
2550
2838
|
}
|
|
2551
2839
|
catch { /* assume not enabled */ }
|
|
2840
|
+
const expectedApprovalCount = (govAlreadyRegistered ? 0 : 1) +
|
|
2841
|
+
(govAlreadyDefiEnabled ? 0 : 1) +
|
|
2842
|
+
1 +
|
|
2843
|
+
(guardianWallet ? 1 : 0) +
|
|
2844
|
+
categories.length;
|
|
2845
|
+
console.log("\nConnecting wallet...");
|
|
2846
|
+
const { client, session, account } = await requestWalletConnectApprovalSession(config, {
|
|
2847
|
+
actionType: "policy_update",
|
|
2848
|
+
signerMode: "owner_wallet",
|
|
2849
|
+
chainId,
|
|
2850
|
+
walletAddress: config.walletContractAddress,
|
|
2851
|
+
txs: Array.from({ length: expectedApprovalCount }, () => ({
|
|
2852
|
+
to: config.walletContractAddress,
|
|
2853
|
+
data: "0x",
|
|
2854
|
+
value: "0x0",
|
|
2855
|
+
})),
|
|
2856
|
+
ui: {
|
|
2857
|
+
title: "Governance setup",
|
|
2858
|
+
summary: "Approve governance setup transactions on ARC402Wallet",
|
|
2859
|
+
risk: "high",
|
|
2860
|
+
},
|
|
2861
|
+
metadata: {
|
|
2862
|
+
category: "policy",
|
|
2863
|
+
expectedApprovalCount,
|
|
2864
|
+
sourceRuntime: "cli",
|
|
2865
|
+
},
|
|
2866
|
+
});
|
|
2552
2867
|
if (!govAlreadyRegistered) {
|
|
2553
2868
|
const registerCalldata = govInterface.encodeFunctionData("registerWallet", [config.walletContractAddress, account]);
|
|
2554
2869
|
calls.push({
|
|
@@ -2683,19 +2998,37 @@ function registerWalletCommands(program) {
|
|
|
2683
2998
|
}
|
|
2684
2999
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
2685
3000
|
console.log(`Machine key: ${checksumKey}`);
|
|
2686
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
2687
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2688
|
-
: undefined;
|
|
2689
3001
|
const walletInterface = new ethers_1.ethers.Interface(machineKeyAbi);
|
|
2690
3002
|
const txData = {
|
|
2691
3003
|
to: config.walletContractAddress,
|
|
2692
3004
|
data: walletInterface.encodeFunctionData("authorizeMachineKey", [checksumKey]),
|
|
2693
3005
|
value: "0x0",
|
|
2694
3006
|
};
|
|
2695
|
-
const
|
|
2696
|
-
|
|
2697
|
-
|
|
3007
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
3008
|
+
actionType: "custom_tx",
|
|
3009
|
+
signerMode: "owner_wallet",
|
|
3010
|
+
chainId,
|
|
3011
|
+
walletAddress: config.walletContractAddress,
|
|
3012
|
+
txs: [txData],
|
|
3013
|
+
ui: {
|
|
3014
|
+
title: "Authorize machine key",
|
|
3015
|
+
summary: `Authorize machine key ${checksumKey} on ARC402Wallet — allows autonomous protocol ops`,
|
|
3016
|
+
risk: "high",
|
|
3017
|
+
},
|
|
3018
|
+
metadata: { sourceRuntime: "cli" },
|
|
2698
3019
|
});
|
|
3020
|
+
if (execution.kind === "passkey") {
|
|
3021
|
+
const confirmed = await walletContract.authorizedMachineKeys(checksumKey);
|
|
3022
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(` Machine key authorized: ${confirmed ? "YES" : "NO"}`));
|
|
3023
|
+
(0, tree_1.renderTree)([
|
|
3024
|
+
{ label: "Wallet", value: config.walletContractAddress ?? "" },
|
|
3025
|
+
{ label: "Machine key", value: checksumKey },
|
|
3026
|
+
{ label: "Tx", value: execution.txHash },
|
|
3027
|
+
{ label: "UserOp", value: execution.userOpHash, last: true },
|
|
3028
|
+
]);
|
|
3029
|
+
return;
|
|
3030
|
+
}
|
|
3031
|
+
const { client, session, account } = execution.session;
|
|
2699
3032
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${account}`));
|
|
2700
3033
|
console.log(colors_1.c.dim("Sending authorizeMachineKey transaction..."));
|
|
2701
3034
|
const hash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
@@ -2756,18 +3089,40 @@ function registerWalletCommands(program) {
|
|
|
2756
3089
|
}
|
|
2757
3090
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
2758
3091
|
console.log(`Revoking: ${checksumKey}`);
|
|
2759
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
2760
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
2761
|
-
: undefined;
|
|
2762
3092
|
const walletInterface = new ethers_1.ethers.Interface(abis_1.ARC402_WALLET_MACHINE_KEY_ABI);
|
|
2763
|
-
const
|
|
2764
|
-
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${account}`));
|
|
2765
|
-
console.log(colors_1.c.dim("Sending revokeMachineKey transaction..."));
|
|
2766
|
-
const hash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, {
|
|
3093
|
+
const txData = {
|
|
2767
3094
|
to: config.walletContractAddress,
|
|
2768
3095
|
data: walletInterface.encodeFunctionData("revokeMachineKey", [checksumKey]),
|
|
2769
3096
|
value: "0x0",
|
|
3097
|
+
};
|
|
3098
|
+
const execution = await requestWalletGovernanceExecution(config, {
|
|
3099
|
+
actionType: "custom_tx",
|
|
3100
|
+
signerMode: "owner_wallet",
|
|
3101
|
+
chainId,
|
|
3102
|
+
walletAddress: config.walletContractAddress,
|
|
3103
|
+
txs: [txData],
|
|
3104
|
+
ui: {
|
|
3105
|
+
title: "Revoke machine key",
|
|
3106
|
+
summary: `Revoke machine key ${checksumKey} on ARC402Wallet`,
|
|
3107
|
+
risk: "high",
|
|
3108
|
+
},
|
|
3109
|
+
metadata: { sourceRuntime: "cli" },
|
|
2770
3110
|
});
|
|
3111
|
+
if (execution.kind === "passkey") {
|
|
3112
|
+
const stillAuthorized = await walletContract.authorizedMachineKeys(checksumKey);
|
|
3113
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(` Machine key revoked: ${stillAuthorized ? "NO (still authorized — check tx)" : "YES"}`));
|
|
3114
|
+
(0, tree_1.renderTree)([
|
|
3115
|
+
{ label: "Wallet", value: config.walletContractAddress ?? "" },
|
|
3116
|
+
{ label: "Machine key", value: checksumKey },
|
|
3117
|
+
{ label: "Tx", value: execution.txHash },
|
|
3118
|
+
{ label: "UserOp", value: execution.userOpHash, last: true },
|
|
3119
|
+
]);
|
|
3120
|
+
return;
|
|
3121
|
+
}
|
|
3122
|
+
const { client, session, account } = execution.session;
|
|
3123
|
+
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${account}`));
|
|
3124
|
+
console.log(colors_1.c.dim("Sending revokeMachineKey transaction..."));
|
|
3125
|
+
const hash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
2771
3126
|
console.log("\n" + colors_1.c.dim("Transaction submitted:") + " " + colors_1.c.white(hash));
|
|
2772
3127
|
console.log(colors_1.c.dim("Waiting for confirmation..."));
|
|
2773
3128
|
const receipt = await provider.waitForTransaction(hash, 1, 60000);
|
|
@@ -3266,7 +3621,7 @@ function registerWalletCommands(program) {
|
|
|
3266
3621
|
console.error("walletConnectProjectId not set. Run `arc402 config set walletConnectProjectId <id>`.");
|
|
3267
3622
|
process.exit(1);
|
|
3268
3623
|
}
|
|
3269
|
-
const migrationRegistryAddress = config
|
|
3624
|
+
const migrationRegistryAddress = (0, config_1.getCanonicalNetworkAddress)(config, "migrationRegistryAddress");
|
|
3270
3625
|
let oldWallet;
|
|
3271
3626
|
let newWallet;
|
|
3272
3627
|
try {
|
|
@@ -3292,10 +3647,20 @@ function registerWalletCommands(program) {
|
|
|
3292
3647
|
"function registerMigration(address oldWallet, address newWallet) external"
|
|
3293
3648
|
]);
|
|
3294
3649
|
const callData = mrIface.encodeFunctionData("registerMigration", [oldWallet, newWallet]);
|
|
3295
|
-
const
|
|
3296
|
-
|
|
3297
|
-
:
|
|
3298
|
-
|
|
3650
|
+
const txData = { to: migrationRegistryAddress, data: callData, value: "0x0" };
|
|
3651
|
+
const { client, session, account } = await requestWalletConnectApprovalSession(config, {
|
|
3652
|
+
actionType: "custom_tx",
|
|
3653
|
+
signerMode: "owner_wallet",
|
|
3654
|
+
chainId,
|
|
3655
|
+
txs: [txData],
|
|
3656
|
+
ui: {
|
|
3657
|
+
title: "Register wallet migration",
|
|
3658
|
+
summary: `Approve: migrate wallet identity ${oldWallet.slice(0, 10)}... → ${newWallet.slice(0, 10)}...`,
|
|
3659
|
+
risk: "high",
|
|
3660
|
+
},
|
|
3661
|
+
metadata: { sourceRuntime: "cli" },
|
|
3662
|
+
});
|
|
3663
|
+
const txHash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|
|
3299
3664
|
await provider.waitForTransaction(txHash);
|
|
3300
3665
|
if (opts.json) {
|
|
3301
3666
|
console.log(JSON.stringify({ ok: true, txHash, from: oldWallet, to: newWallet }));
|
|
@@ -3519,18 +3884,29 @@ function registerWalletCommands(program) {
|
|
|
3519
3884
|
console.log(`\nWallet: ${config.walletContractAddress}`);
|
|
3520
3885
|
console.log(`pubKeyX: ${pubKeyX}`);
|
|
3521
3886
|
console.log(`pubKeyY: ${pubKeyY}`);
|
|
3522
|
-
const telegramOpts = config.telegramBotToken && config.telegramChatId
|
|
3523
|
-
? { botToken: config.telegramBotToken, chatId: config.telegramChatId, threadId: config.telegramThreadId }
|
|
3524
|
-
: undefined;
|
|
3525
3887
|
const txData = {
|
|
3526
3888
|
to: config.walletContractAddress,
|
|
3527
3889
|
data: walletInterface.encodeFunctionData("setPasskey", [pubKeyX, pubKeyY]),
|
|
3528
3890
|
value: "0x0",
|
|
3529
3891
|
};
|
|
3530
|
-
const
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3892
|
+
const approval = await (0, broker_1.requestOwnerApproval)({
|
|
3893
|
+
actionType: "custom_tx",
|
|
3894
|
+
signerMode: "owner_wallet",
|
|
3895
|
+
chainId,
|
|
3896
|
+
walletAddress: config.walletContractAddress,
|
|
3897
|
+
txs: [txData],
|
|
3898
|
+
ui: {
|
|
3899
|
+
title: "Activate passkey",
|
|
3900
|
+
summary: "Activate passkey (Face ID) on ARC402Wallet — enables P256 governance signing",
|
|
3901
|
+
risk: "high",
|
|
3902
|
+
},
|
|
3903
|
+
metadata: { sourceRuntime: "cli" },
|
|
3904
|
+
}, config);
|
|
3905
|
+
if (approval.status !== "approved" || !approval.session || approval.session.kind !== "walletconnect") {
|
|
3906
|
+
console.error(colors_1.c.failure + " " + colors_1.c.red(approval.error ?? "Approval transport failed."));
|
|
3907
|
+
process.exit(1);
|
|
3908
|
+
}
|
|
3909
|
+
const { client, session, account } = approval.session;
|
|
3534
3910
|
console.log("\n" + colors_1.c.success + colors_1.c.white(` Connected: ${account}`));
|
|
3535
3911
|
console.log(colors_1.c.dim("Sending setPasskey transaction..."));
|
|
3536
3912
|
const hash = await (0, walletconnect_1.sendTransactionWithSession)(client, session, account, chainId, txData);
|