@aomi-labs/client 0.1.6 → 0.1.8
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/cli.js +1087 -97
- package/dist/index.cjs +826 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +270 -1
- package/dist/index.d.ts +270 -1
- package/dist/index.js +803 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/cli.js
CHANGED
|
@@ -67,6 +67,30 @@ ${list}`);
|
|
|
67
67
|
}
|
|
68
68
|
return n;
|
|
69
69
|
}
|
|
70
|
+
function resolveExecutionMode(flags) {
|
|
71
|
+
const flagAA = flags["aa"] === "true";
|
|
72
|
+
const flagEoa = flags["eoa"] === "true";
|
|
73
|
+
if (flagAA && flagEoa) {
|
|
74
|
+
fatal("Choose only one of `--aa` or `--eoa`.");
|
|
75
|
+
}
|
|
76
|
+
if (flagAA) return "aa";
|
|
77
|
+
if (flagEoa) return "eoa";
|
|
78
|
+
return "aa";
|
|
79
|
+
}
|
|
80
|
+
function parseAAProvider(value) {
|
|
81
|
+
if (value === void 0) return void 0;
|
|
82
|
+
if (value === "alchemy" || value === "pimlico") {
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
fatal("Unsupported AA provider. Use `alchemy` or `pimlico`.");
|
|
86
|
+
}
|
|
87
|
+
function parseAAMode(value) {
|
|
88
|
+
if (value === void 0) return void 0;
|
|
89
|
+
if (value === "4337" || value === "7702") {
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
fatal("Unsupported AA mode. Use `4337` or `7702`.");
|
|
93
|
+
}
|
|
70
94
|
function parseArgs(argv) {
|
|
71
95
|
const raw = argv.slice(2);
|
|
72
96
|
const command = raw[0] && !raw[0].startsWith("--") ? raw[0] : void 0;
|
|
@@ -96,16 +120,35 @@ function parseArgs(argv) {
|
|
|
96
120
|
return { command, positional, flags };
|
|
97
121
|
}
|
|
98
122
|
function getConfig(parsed) {
|
|
99
|
-
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
123
|
+
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
124
|
+
const usesSignFlags = parsed.flags["aa"] === "true" || parsed.flags["eoa"] === "true" || parsed.flags["aa-provider"] !== void 0 || parsed.flags["aa-mode"] !== void 0;
|
|
125
|
+
if (usesSignFlags && parsed.command !== "sign") {
|
|
126
|
+
fatal(
|
|
127
|
+
"AA/EOA execution flags are only supported on `aomi sign <tx-id>`."
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
const execution = resolveExecutionMode(parsed.flags);
|
|
131
|
+
const aaProvider = parseAAProvider(
|
|
132
|
+
(_a3 = parsed.flags["aa-provider"]) != null ? _a3 : process.env.AOMI_AA_PROVIDER
|
|
133
|
+
);
|
|
134
|
+
const aaMode = parseAAMode(
|
|
135
|
+
(_b = parsed.flags["aa-mode"]) != null ? _b : process.env.AOMI_AA_MODE
|
|
136
|
+
);
|
|
137
|
+
if (execution === "eoa" && (aaProvider || aaMode)) {
|
|
138
|
+
fatal("`--aa-provider` and `--aa-mode` cannot be used with `--eoa`.");
|
|
139
|
+
}
|
|
100
140
|
return {
|
|
101
|
-
baseUrl: (
|
|
102
|
-
apiKey: (
|
|
103
|
-
app: (
|
|
104
|
-
model: (
|
|
105
|
-
publicKey: (
|
|
106
|
-
privateKey: (
|
|
107
|
-
chainRpcUrl: (
|
|
108
|
-
chain: parseChainId((
|
|
141
|
+
baseUrl: (_d = (_c = parsed.flags["backend-url"]) != null ? _c : process.env.AOMI_BASE_URL) != null ? _d : "https://api.aomi.dev",
|
|
142
|
+
apiKey: (_e = parsed.flags["api-key"]) != null ? _e : process.env.AOMI_API_KEY,
|
|
143
|
+
app: (_g = (_f = parsed.flags["app"]) != null ? _f : process.env.AOMI_APP) != null ? _g : "default",
|
|
144
|
+
model: (_h = parsed.flags["model"]) != null ? _h : process.env.AOMI_MODEL,
|
|
145
|
+
publicKey: (_i = parsed.flags["public-key"]) != null ? _i : process.env.AOMI_PUBLIC_KEY,
|
|
146
|
+
privateKey: (_j = parsed.flags["private-key"]) != null ? _j : process.env.PRIVATE_KEY,
|
|
147
|
+
chainRpcUrl: (_k = parsed.flags["rpc-url"]) != null ? _k : process.env.CHAIN_RPC_URL,
|
|
148
|
+
chain: parseChainId((_l = parsed.flags["chain"]) != null ? _l : process.env.AOMI_CHAIN_ID),
|
|
149
|
+
execution,
|
|
150
|
+
aaProvider,
|
|
151
|
+
aaMode
|
|
109
152
|
};
|
|
110
153
|
}
|
|
111
154
|
function createRuntime(argv) {
|
|
@@ -1623,6 +1666,40 @@ function walletRequestToPendingTx(request) {
|
|
|
1623
1666
|
payload: request.payload
|
|
1624
1667
|
};
|
|
1625
1668
|
}
|
|
1669
|
+
function pendingTxToCallList(tx) {
|
|
1670
|
+
var _a3, _b;
|
|
1671
|
+
if (tx.kind !== "transaction" || !tx.to) {
|
|
1672
|
+
throw new Error("pending_transaction_missing_call_data");
|
|
1673
|
+
}
|
|
1674
|
+
return [
|
|
1675
|
+
{
|
|
1676
|
+
to: tx.to,
|
|
1677
|
+
value: (_a3 = tx.value) != null ? _a3 : "0",
|
|
1678
|
+
data: tx.data,
|
|
1679
|
+
chainId: (_b = tx.chainId) != null ? _b : 1
|
|
1680
|
+
}
|
|
1681
|
+
];
|
|
1682
|
+
}
|
|
1683
|
+
function toSignedTransactionRecord(tx, execution, from, chainId, timestamp, aaProvider, aaMode) {
|
|
1684
|
+
return {
|
|
1685
|
+
id: tx.id,
|
|
1686
|
+
kind: "transaction",
|
|
1687
|
+
txHash: execution.txHash,
|
|
1688
|
+
txHashes: execution.txHashes,
|
|
1689
|
+
executionKind: execution.executionKind,
|
|
1690
|
+
aaProvider,
|
|
1691
|
+
aaMode,
|
|
1692
|
+
batched: execution.batched,
|
|
1693
|
+
sponsored: execution.sponsored,
|
|
1694
|
+
AAAddress: execution.AAAddress,
|
|
1695
|
+
delegationAddress: execution.delegationAddress,
|
|
1696
|
+
from,
|
|
1697
|
+
to: tx.to,
|
|
1698
|
+
value: tx.value,
|
|
1699
|
+
chainId,
|
|
1700
|
+
timestamp
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1626
1703
|
function formatTxLine(tx, prefix) {
|
|
1627
1704
|
var _a3;
|
|
1628
1705
|
const parts = [`${prefix} ${tx.id}`];
|
|
@@ -1638,6 +1715,29 @@ function formatTxLine(tx, prefix) {
|
|
|
1638
1715
|
parts.push(`(${new Date(tx.timestamp).toLocaleTimeString()})`);
|
|
1639
1716
|
return parts.join(" ");
|
|
1640
1717
|
}
|
|
1718
|
+
function formatSignedTxLine(tx, prefix) {
|
|
1719
|
+
var _a3;
|
|
1720
|
+
const parts = [`${prefix} ${tx.id}`];
|
|
1721
|
+
if (tx.kind === "eip712_sign") {
|
|
1722
|
+
parts.push(`sig: ${(_a3 = tx.signature) == null ? void 0 : _a3.slice(0, 20)}...`);
|
|
1723
|
+
if (tx.description) parts.push(tx.description);
|
|
1724
|
+
} else {
|
|
1725
|
+
parts.push(`hash: ${tx.txHash}`);
|
|
1726
|
+
if (tx.executionKind) parts.push(`exec: ${tx.executionKind}`);
|
|
1727
|
+
if (tx.aaProvider) parts.push(`provider: ${tx.aaProvider}`);
|
|
1728
|
+
if (tx.aaMode) parts.push(`mode: ${tx.aaMode}`);
|
|
1729
|
+
if (tx.txHashes && tx.txHashes.length > 1) {
|
|
1730
|
+
parts.push(`txs: ${tx.txHashes.length}`);
|
|
1731
|
+
}
|
|
1732
|
+
if (tx.sponsored) parts.push("sponsored");
|
|
1733
|
+
if (tx.AAAddress) parts.push(`aa: ${tx.AAAddress}`);
|
|
1734
|
+
if (tx.delegationAddress) parts.push(`delegation: ${tx.delegationAddress}`);
|
|
1735
|
+
if (tx.to) parts.push(`to: ${tx.to}`);
|
|
1736
|
+
if (tx.value) parts.push(`value: ${tx.value}`);
|
|
1737
|
+
}
|
|
1738
|
+
parts.push(`(${new Date(tx.timestamp).toLocaleTimeString()})`);
|
|
1739
|
+
return parts.join(" ");
|
|
1740
|
+
}
|
|
1641
1741
|
|
|
1642
1742
|
// src/cli/commands/chat.ts
|
|
1643
1743
|
async function chatCommand(runtime) {
|
|
@@ -1914,17 +2014,25 @@ function toPendingTxMetadata(tx) {
|
|
|
1914
2014
|
};
|
|
1915
2015
|
}
|
|
1916
2016
|
function toSignedTxMetadata(tx) {
|
|
1917
|
-
var _a3, _b, _c, _d, _e, _f, _g;
|
|
2017
|
+
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
|
|
1918
2018
|
return {
|
|
1919
2019
|
id: tx.id,
|
|
1920
2020
|
kind: tx.kind,
|
|
1921
2021
|
txHash: (_a3 = tx.txHash) != null ? _a3 : null,
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2022
|
+
txHashes: (_b = tx.txHashes) != null ? _b : null,
|
|
2023
|
+
executionKind: (_c = tx.executionKind) != null ? _c : null,
|
|
2024
|
+
aaProvider: (_d = tx.aaProvider) != null ? _d : null,
|
|
2025
|
+
aaMode: (_e = tx.aaMode) != null ? _e : null,
|
|
2026
|
+
batched: (_f = tx.batched) != null ? _f : null,
|
|
2027
|
+
sponsored: (_g = tx.sponsored) != null ? _g : null,
|
|
2028
|
+
AAAddress: (_h = tx.AAAddress) != null ? _h : null,
|
|
2029
|
+
delegationAddress: (_i = tx.delegationAddress) != null ? _i : null,
|
|
2030
|
+
signature: (_j = tx.signature) != null ? _j : null,
|
|
2031
|
+
from: (_k = tx.from) != null ? _k : null,
|
|
2032
|
+
to: (_l = tx.to) != null ? _l : null,
|
|
2033
|
+
value: (_m = tx.value) != null ? _m : null,
|
|
2034
|
+
chainId: (_n = tx.chainId) != null ? _n : null,
|
|
2035
|
+
description: (_o = tx.description) != null ? _o : null,
|
|
1928
2036
|
timestamp: new Date(tx.timestamp).toISOString()
|
|
1929
2037
|
};
|
|
1930
2038
|
}
|
|
@@ -2183,10 +2291,704 @@ function sessionCommand(runtime) {
|
|
|
2183
2291
|
|
|
2184
2292
|
// src/cli/commands/wallet.ts
|
|
2185
2293
|
import { createWalletClient, http } from "viem";
|
|
2186
|
-
import {
|
|
2294
|
+
import { createInterface } from "readline/promises";
|
|
2295
|
+
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
2187
2296
|
import * as viemChains from "viem/chains";
|
|
2297
|
+
|
|
2298
|
+
// src/aa/types.ts
|
|
2299
|
+
function getAAChainConfig(config, calls, chainsById) {
|
|
2300
|
+
if (!config.enabled || calls.length === 0) {
|
|
2301
|
+
return null;
|
|
2302
|
+
}
|
|
2303
|
+
const chainIds = Array.from(new Set(calls.map((call) => call.chainId)));
|
|
2304
|
+
if (chainIds.length !== 1) {
|
|
2305
|
+
return null;
|
|
2306
|
+
}
|
|
2307
|
+
const chainId = chainIds[0];
|
|
2308
|
+
if (!chainsById[chainId]) {
|
|
2309
|
+
return null;
|
|
2310
|
+
}
|
|
2311
|
+
const chainConfig = config.chains.find((item) => item.chainId === chainId);
|
|
2312
|
+
if (!(chainConfig == null ? void 0 : chainConfig.enabled)) {
|
|
2313
|
+
return null;
|
|
2314
|
+
}
|
|
2315
|
+
if (calls.length > 1 && !chainConfig.allowBatching) {
|
|
2316
|
+
return null;
|
|
2317
|
+
}
|
|
2318
|
+
return chainConfig;
|
|
2319
|
+
}
|
|
2320
|
+
function buildAAExecutionPlan(config, chainConfig) {
|
|
2321
|
+
const mode = chainConfig.supportedModes.includes(chainConfig.defaultMode) ? chainConfig.defaultMode : chainConfig.supportedModes[0];
|
|
2322
|
+
if (!mode) {
|
|
2323
|
+
throw new Error(`No smart account mode configured for chain ${chainConfig.chainId}`);
|
|
2324
|
+
}
|
|
2325
|
+
return {
|
|
2326
|
+
provider: config.provider,
|
|
2327
|
+
chainId: chainConfig.chainId,
|
|
2328
|
+
mode,
|
|
2329
|
+
batchingEnabled: chainConfig.allowBatching,
|
|
2330
|
+
sponsorship: chainConfig.sponsorship,
|
|
2331
|
+
fallbackToEoa: config.fallbackToEoa
|
|
2332
|
+
};
|
|
2333
|
+
}
|
|
2334
|
+
function mapCall(call) {
|
|
2335
|
+
return {
|
|
2336
|
+
to: call.to,
|
|
2337
|
+
value: BigInt(call.value),
|
|
2338
|
+
data: call.data ? call.data : void 0
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
var DEFAULT_AA_CONFIG = {
|
|
2342
|
+
enabled: true,
|
|
2343
|
+
provider: "alchemy",
|
|
2344
|
+
fallbackToEoa: true,
|
|
2345
|
+
chains: [
|
|
2346
|
+
{
|
|
2347
|
+
chainId: 1,
|
|
2348
|
+
enabled: true,
|
|
2349
|
+
defaultMode: "7702",
|
|
2350
|
+
supportedModes: ["4337", "7702"],
|
|
2351
|
+
allowBatching: true,
|
|
2352
|
+
sponsorship: "optional"
|
|
2353
|
+
},
|
|
2354
|
+
{
|
|
2355
|
+
chainId: 137,
|
|
2356
|
+
enabled: true,
|
|
2357
|
+
defaultMode: "4337",
|
|
2358
|
+
supportedModes: ["4337", "7702"],
|
|
2359
|
+
allowBatching: true,
|
|
2360
|
+
sponsorship: "optional"
|
|
2361
|
+
},
|
|
2362
|
+
{
|
|
2363
|
+
chainId: 42161,
|
|
2364
|
+
enabled: true,
|
|
2365
|
+
defaultMode: "4337",
|
|
2366
|
+
supportedModes: ["4337", "7702"],
|
|
2367
|
+
allowBatching: true,
|
|
2368
|
+
sponsorship: "optional"
|
|
2369
|
+
},
|
|
2370
|
+
{
|
|
2371
|
+
chainId: 10,
|
|
2372
|
+
enabled: true,
|
|
2373
|
+
defaultMode: "4337",
|
|
2374
|
+
supportedModes: ["4337", "7702"],
|
|
2375
|
+
allowBatching: true,
|
|
2376
|
+
sponsorship: "optional"
|
|
2377
|
+
},
|
|
2378
|
+
{
|
|
2379
|
+
chainId: 8453,
|
|
2380
|
+
enabled: true,
|
|
2381
|
+
defaultMode: "4337",
|
|
2382
|
+
supportedModes: ["4337", "7702"],
|
|
2383
|
+
allowBatching: true,
|
|
2384
|
+
sponsorship: "optional"
|
|
2385
|
+
}
|
|
2386
|
+
]
|
|
2387
|
+
};
|
|
2388
|
+
var DISABLED_PROVIDER_STATE = {
|
|
2389
|
+
plan: null,
|
|
2390
|
+
AA: void 0,
|
|
2391
|
+
isPending: false,
|
|
2392
|
+
error: null
|
|
2393
|
+
};
|
|
2394
|
+
async function executeWalletCalls(params) {
|
|
2395
|
+
const {
|
|
2396
|
+
callList,
|
|
2397
|
+
currentChainId,
|
|
2398
|
+
capabilities,
|
|
2399
|
+
localPrivateKey,
|
|
2400
|
+
providerState,
|
|
2401
|
+
sendCallsSyncAsync,
|
|
2402
|
+
sendTransactionAsync,
|
|
2403
|
+
switchChainAsync,
|
|
2404
|
+
chainsById,
|
|
2405
|
+
getPreferredRpcUrl: getPreferredRpcUrl2
|
|
2406
|
+
} = params;
|
|
2407
|
+
if (providerState.plan && providerState.AA) {
|
|
2408
|
+
return executeViaAA(callList, providerState);
|
|
2409
|
+
}
|
|
2410
|
+
if (providerState.plan && providerState.error && !providerState.plan.fallbackToEoa) {
|
|
2411
|
+
throw providerState.error;
|
|
2412
|
+
}
|
|
2413
|
+
return executeViaEoa({
|
|
2414
|
+
callList,
|
|
2415
|
+
currentChainId,
|
|
2416
|
+
capabilities,
|
|
2417
|
+
localPrivateKey,
|
|
2418
|
+
sendCallsSyncAsync,
|
|
2419
|
+
sendTransactionAsync,
|
|
2420
|
+
switchChainAsync,
|
|
2421
|
+
chainsById,
|
|
2422
|
+
getPreferredRpcUrl: getPreferredRpcUrl2
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
async function executeViaAA(callList, providerState) {
|
|
2426
|
+
var _a3;
|
|
2427
|
+
const AA = providerState.AA;
|
|
2428
|
+
const plan = providerState.plan;
|
|
2429
|
+
if (!AA || !plan) {
|
|
2430
|
+
throw (_a3 = providerState.error) != null ? _a3 : new Error("smart_account_unavailable");
|
|
2431
|
+
}
|
|
2432
|
+
const callsPayload = callList.map(mapCall);
|
|
2433
|
+
const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
|
|
2434
|
+
const txHash = receipt.transactionHash;
|
|
2435
|
+
const providerPrefix = AA.provider.toLowerCase();
|
|
2436
|
+
return {
|
|
2437
|
+
txHash,
|
|
2438
|
+
txHashes: [txHash],
|
|
2439
|
+
executionKind: `${providerPrefix}_${AA.mode}`,
|
|
2440
|
+
batched: callList.length > 1,
|
|
2441
|
+
sponsored: plan.sponsorship !== "disabled",
|
|
2442
|
+
AAAddress: AA.AAAddress,
|
|
2443
|
+
delegationAddress: AA.mode === "7702" ? AA.delegationAddress : void 0
|
|
2444
|
+
};
|
|
2445
|
+
}
|
|
2446
|
+
async function executeViaEoa({
|
|
2447
|
+
callList,
|
|
2448
|
+
currentChainId,
|
|
2449
|
+
capabilities,
|
|
2450
|
+
localPrivateKey,
|
|
2451
|
+
sendCallsSyncAsync,
|
|
2452
|
+
sendTransactionAsync,
|
|
2453
|
+
switchChainAsync,
|
|
2454
|
+
chainsById,
|
|
2455
|
+
getPreferredRpcUrl: getPreferredRpcUrl2
|
|
2456
|
+
}) {
|
|
2457
|
+
var _a3, _b;
|
|
2458
|
+
const { createPublicClient, createWalletClient: createWalletClient2, http: http2 } = await import("viem");
|
|
2459
|
+
const { privateKeyToAccount: privateKeyToAccount3 } = await import("viem/accounts");
|
|
2460
|
+
const hashes = [];
|
|
2461
|
+
if (localPrivateKey) {
|
|
2462
|
+
for (const call of callList) {
|
|
2463
|
+
const chain = chainsById[call.chainId];
|
|
2464
|
+
if (!chain) {
|
|
2465
|
+
throw new Error(`Unsupported chain ${call.chainId}`);
|
|
2466
|
+
}
|
|
2467
|
+
const rpcUrl = getPreferredRpcUrl2(chain);
|
|
2468
|
+
if (!rpcUrl) {
|
|
2469
|
+
throw new Error(`No RPC for chain ${call.chainId}`);
|
|
2470
|
+
}
|
|
2471
|
+
const account = privateKeyToAccount3(localPrivateKey);
|
|
2472
|
+
const walletClient = createWalletClient2({
|
|
2473
|
+
account,
|
|
2474
|
+
chain,
|
|
2475
|
+
transport: http2(rpcUrl)
|
|
2476
|
+
});
|
|
2477
|
+
const hash = await walletClient.sendTransaction({
|
|
2478
|
+
account,
|
|
2479
|
+
to: call.to,
|
|
2480
|
+
value: BigInt(call.value),
|
|
2481
|
+
data: call.data ? call.data : void 0
|
|
2482
|
+
});
|
|
2483
|
+
const publicClient = createPublicClient({
|
|
2484
|
+
chain,
|
|
2485
|
+
transport: http2(rpcUrl)
|
|
2486
|
+
});
|
|
2487
|
+
await publicClient.waitForTransactionReceipt({ hash });
|
|
2488
|
+
hashes.push(hash);
|
|
2489
|
+
}
|
|
2490
|
+
return {
|
|
2491
|
+
txHash: hashes[hashes.length - 1],
|
|
2492
|
+
txHashes: hashes,
|
|
2493
|
+
executionKind: "eoa",
|
|
2494
|
+
batched: hashes.length > 1,
|
|
2495
|
+
sponsored: false
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
const chainIds = Array.from(new Set(callList.map((call) => call.chainId)));
|
|
2499
|
+
if (chainIds.length > 1) {
|
|
2500
|
+
throw new Error("mixed_chain_bundle_not_supported");
|
|
2501
|
+
}
|
|
2502
|
+
const chainId = chainIds[0];
|
|
2503
|
+
if (currentChainId !== chainId) {
|
|
2504
|
+
await switchChainAsync({ chainId });
|
|
2505
|
+
}
|
|
2506
|
+
const chainCaps = capabilities == null ? void 0 : capabilities[`eip155:${chainId}`];
|
|
2507
|
+
const atomicStatus = (_a3 = chainCaps == null ? void 0 : chainCaps.atomic) == null ? void 0 : _a3.status;
|
|
2508
|
+
const canUseSendCalls = atomicStatus === "supported" || atomicStatus === "ready";
|
|
2509
|
+
if (canUseSendCalls) {
|
|
2510
|
+
const batchResult = await sendCallsSyncAsync({
|
|
2511
|
+
calls: callList.map(mapCall),
|
|
2512
|
+
capabilities: {
|
|
2513
|
+
atomic: {
|
|
2514
|
+
required: true
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
const receipts = (_b = batchResult.receipts) != null ? _b : [];
|
|
2519
|
+
for (const receipt of receipts) {
|
|
2520
|
+
if (receipt.transactionHash) {
|
|
2521
|
+
hashes.push(receipt.transactionHash);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
} else {
|
|
2525
|
+
for (const call of callList) {
|
|
2526
|
+
const hash = await sendTransactionAsync({
|
|
2527
|
+
chainId: call.chainId,
|
|
2528
|
+
to: call.to,
|
|
2529
|
+
value: BigInt(call.value),
|
|
2530
|
+
data: call.data ? call.data : void 0
|
|
2531
|
+
});
|
|
2532
|
+
hashes.push(hash);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return {
|
|
2536
|
+
txHash: hashes[hashes.length - 1],
|
|
2537
|
+
txHashes: hashes,
|
|
2538
|
+
executionKind: "eoa",
|
|
2539
|
+
batched: hashes.length > 1,
|
|
2540
|
+
sponsored: false
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
// src/aa/env.ts
|
|
2545
|
+
var ALCHEMY_API_KEY_ENVS = [
|
|
2546
|
+
"ALCHEMY_API_KEY",
|
|
2547
|
+
"NEXT_PUBLIC_ALCHEMY_API_KEY"
|
|
2548
|
+
];
|
|
2549
|
+
var ALCHEMY_GAS_POLICY_ENVS = [
|
|
2550
|
+
"ALCHEMY_GAS_POLICY_ID",
|
|
2551
|
+
"NEXT_PUBLIC_ALCHEMY_GAS_POLICY_ID"
|
|
2552
|
+
];
|
|
2553
|
+
var PIMLICO_API_KEY_ENVS = [
|
|
2554
|
+
"PIMLICO_API_KEY",
|
|
2555
|
+
"NEXT_PUBLIC_PIMLICO_API_KEY"
|
|
2556
|
+
];
|
|
2557
|
+
function readEnv(candidates, options = {}) {
|
|
2558
|
+
var _a3;
|
|
2559
|
+
const { publicOnly = false } = options;
|
|
2560
|
+
for (const name of candidates) {
|
|
2561
|
+
if (publicOnly && !name.startsWith("NEXT_PUBLIC_")) {
|
|
2562
|
+
continue;
|
|
2563
|
+
}
|
|
2564
|
+
const value = (_a3 = process.env[name]) == null ? void 0 : _a3.trim();
|
|
2565
|
+
if (value) return value;
|
|
2566
|
+
}
|
|
2567
|
+
return void 0;
|
|
2568
|
+
}
|
|
2569
|
+
function readGasPolicyEnv(chainId, chainSlugById, baseCandidates, options = {}) {
|
|
2570
|
+
const slug = chainSlugById[chainId];
|
|
2571
|
+
if (slug) {
|
|
2572
|
+
const chainSpecific = baseCandidates.map(
|
|
2573
|
+
(base) => `${base}_${slug.toUpperCase()}`
|
|
2574
|
+
);
|
|
2575
|
+
const found = readEnv(chainSpecific, options);
|
|
2576
|
+
if (found) return found;
|
|
2577
|
+
}
|
|
2578
|
+
return readEnv(baseCandidates, options);
|
|
2579
|
+
}
|
|
2580
|
+
function isProviderConfigured(provider, options = {}) {
|
|
2581
|
+
return provider === "alchemy" ? Boolean(readEnv(ALCHEMY_API_KEY_ENVS, options)) : Boolean(readEnv(PIMLICO_API_KEY_ENVS, options));
|
|
2582
|
+
}
|
|
2583
|
+
function resolveDefaultProvider(options = {}) {
|
|
2584
|
+
if (isProviderConfigured("alchemy", options)) return "alchemy";
|
|
2585
|
+
if (isProviderConfigured("pimlico", options)) return "pimlico";
|
|
2586
|
+
throw new Error(
|
|
2587
|
+
"AA requires provider credentials. Set ALCHEMY_API_KEY or PIMLICO_API_KEY, or use --eoa."
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
// src/aa/resolve.ts
|
|
2592
|
+
function resolveAlchemyConfig(options) {
|
|
2593
|
+
const {
|
|
2594
|
+
calls,
|
|
2595
|
+
localPrivateKey,
|
|
2596
|
+
accountAbstractionConfig = DEFAULT_AA_CONFIG,
|
|
2597
|
+
chainsById,
|
|
2598
|
+
chainSlugById = {},
|
|
2599
|
+
getPreferredRpcUrl: getPreferredRpcUrl2 = (chain2) => {
|
|
2600
|
+
var _a3;
|
|
2601
|
+
return (_a3 = chain2.rpcUrls.default.http[0]) != null ? _a3 : "";
|
|
2602
|
+
},
|
|
2603
|
+
modeOverride,
|
|
2604
|
+
publicOnly = false,
|
|
2605
|
+
throwOnMissingConfig = false,
|
|
2606
|
+
apiKey: preResolvedApiKey,
|
|
2607
|
+
gasPolicyId: preResolvedGasPolicyId
|
|
2608
|
+
} = options;
|
|
2609
|
+
if (!calls || localPrivateKey) {
|
|
2610
|
+
return null;
|
|
2611
|
+
}
|
|
2612
|
+
const config = __spreadProps(__spreadValues({}, accountAbstractionConfig), {
|
|
2613
|
+
provider: "alchemy"
|
|
2614
|
+
});
|
|
2615
|
+
const chainConfig = getAAChainConfig(config, calls, chainsById);
|
|
2616
|
+
if (!chainConfig) {
|
|
2617
|
+
if (throwOnMissingConfig) {
|
|
2618
|
+
const chainIds = Array.from(new Set(calls.map((c) => c.chainId)));
|
|
2619
|
+
throw new Error(
|
|
2620
|
+
`AA is not configured for chain ${chainIds[0]}, or batching is disabled for that chain.`
|
|
2621
|
+
);
|
|
2622
|
+
}
|
|
2623
|
+
return null;
|
|
2624
|
+
}
|
|
2625
|
+
const apiKey = preResolvedApiKey != null ? preResolvedApiKey : readEnv(ALCHEMY_API_KEY_ENVS, { publicOnly });
|
|
2626
|
+
if (!apiKey) {
|
|
2627
|
+
if (throwOnMissingConfig) {
|
|
2628
|
+
throw new Error("Alchemy AA requires ALCHEMY_API_KEY.");
|
|
2629
|
+
}
|
|
2630
|
+
return null;
|
|
2631
|
+
}
|
|
2632
|
+
const chain = chainsById[chainConfig.chainId];
|
|
2633
|
+
if (!chain) {
|
|
2634
|
+
return null;
|
|
2635
|
+
}
|
|
2636
|
+
const gasPolicyId = preResolvedGasPolicyId != null ? preResolvedGasPolicyId : readGasPolicyEnv(
|
|
2637
|
+
chainConfig.chainId,
|
|
2638
|
+
chainSlugById,
|
|
2639
|
+
ALCHEMY_GAS_POLICY_ENVS,
|
|
2640
|
+
{ publicOnly }
|
|
2641
|
+
);
|
|
2642
|
+
if (chainConfig.sponsorship === "required" && !gasPolicyId) {
|
|
2643
|
+
if (throwOnMissingConfig) {
|
|
2644
|
+
throw new Error(
|
|
2645
|
+
`Alchemy gas policy required for chain ${chainConfig.chainId} but not configured.`
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
return null;
|
|
2649
|
+
}
|
|
2650
|
+
if (modeOverride && !chainConfig.supportedModes.includes(modeOverride)) {
|
|
2651
|
+
if (throwOnMissingConfig) {
|
|
2652
|
+
throw new Error(
|
|
2653
|
+
`AA mode "${modeOverride}" is not supported on chain ${chainConfig.chainId}.`
|
|
2654
|
+
);
|
|
2655
|
+
}
|
|
2656
|
+
return null;
|
|
2657
|
+
}
|
|
2658
|
+
const resolvedChainConfig = modeOverride ? __spreadProps(__spreadValues({}, chainConfig), { defaultMode: modeOverride }) : chainConfig;
|
|
2659
|
+
const plan = buildAAExecutionPlan(config, resolvedChainConfig);
|
|
2660
|
+
return {
|
|
2661
|
+
chainConfig: resolvedChainConfig,
|
|
2662
|
+
plan,
|
|
2663
|
+
apiKey,
|
|
2664
|
+
chain,
|
|
2665
|
+
rpcUrl: getPreferredRpcUrl2(chain),
|
|
2666
|
+
gasPolicyId,
|
|
2667
|
+
mode: resolvedChainConfig.defaultMode
|
|
2668
|
+
};
|
|
2669
|
+
}
|
|
2670
|
+
function resolvePimlicoConfig(options) {
|
|
2671
|
+
const {
|
|
2672
|
+
calls,
|
|
2673
|
+
localPrivateKey,
|
|
2674
|
+
accountAbstractionConfig = DEFAULT_AA_CONFIG,
|
|
2675
|
+
chainsById,
|
|
2676
|
+
rpcUrl,
|
|
2677
|
+
modeOverride,
|
|
2678
|
+
publicOnly = false,
|
|
2679
|
+
throwOnMissingConfig = false,
|
|
2680
|
+
apiKey: preResolvedApiKey
|
|
2681
|
+
} = options;
|
|
2682
|
+
if (!calls || localPrivateKey) {
|
|
2683
|
+
return null;
|
|
2684
|
+
}
|
|
2685
|
+
const config = __spreadProps(__spreadValues({}, accountAbstractionConfig), {
|
|
2686
|
+
provider: "pimlico"
|
|
2687
|
+
});
|
|
2688
|
+
const chainConfig = getAAChainConfig(config, calls, chainsById);
|
|
2689
|
+
if (!chainConfig) {
|
|
2690
|
+
if (throwOnMissingConfig) {
|
|
2691
|
+
const chainIds = Array.from(new Set(calls.map((c) => c.chainId)));
|
|
2692
|
+
throw new Error(
|
|
2693
|
+
`AA is not configured for chain ${chainIds[0]}, or batching is disabled for that chain.`
|
|
2694
|
+
);
|
|
2695
|
+
}
|
|
2696
|
+
return null;
|
|
2697
|
+
}
|
|
2698
|
+
const apiKey = preResolvedApiKey != null ? preResolvedApiKey : readEnv(PIMLICO_API_KEY_ENVS, { publicOnly });
|
|
2699
|
+
if (!apiKey) {
|
|
2700
|
+
if (throwOnMissingConfig) {
|
|
2701
|
+
throw new Error("Pimlico AA requires PIMLICO_API_KEY.");
|
|
2702
|
+
}
|
|
2703
|
+
return null;
|
|
2704
|
+
}
|
|
2705
|
+
const chain = chainsById[chainConfig.chainId];
|
|
2706
|
+
if (!chain) {
|
|
2707
|
+
return null;
|
|
2708
|
+
}
|
|
2709
|
+
if (modeOverride && !chainConfig.supportedModes.includes(modeOverride)) {
|
|
2710
|
+
if (throwOnMissingConfig) {
|
|
2711
|
+
throw new Error(
|
|
2712
|
+
`AA mode "${modeOverride}" is not supported on chain ${chainConfig.chainId}.`
|
|
2713
|
+
);
|
|
2714
|
+
}
|
|
2715
|
+
return null;
|
|
2716
|
+
}
|
|
2717
|
+
const resolvedChainConfig = modeOverride ? __spreadProps(__spreadValues({}, chainConfig), { defaultMode: modeOverride }) : chainConfig;
|
|
2718
|
+
const plan = buildAAExecutionPlan(config, resolvedChainConfig);
|
|
2719
|
+
return {
|
|
2720
|
+
chainConfig: resolvedChainConfig,
|
|
2721
|
+
plan,
|
|
2722
|
+
apiKey,
|
|
2723
|
+
chain,
|
|
2724
|
+
rpcUrl,
|
|
2725
|
+
mode: resolvedChainConfig.defaultMode
|
|
2726
|
+
};
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
// src/aa/adapt.ts
|
|
2730
|
+
function adaptSmartAccount(account) {
|
|
2731
|
+
return {
|
|
2732
|
+
provider: account.provider,
|
|
2733
|
+
mode: account.mode,
|
|
2734
|
+
AAAddress: account.smartAccountAddress,
|
|
2735
|
+
delegationAddress: account.delegationAddress,
|
|
2736
|
+
sendTransaction: async (call) => {
|
|
2737
|
+
const receipt = await account.sendTransaction(call);
|
|
2738
|
+
return { transactionHash: receipt.transactionHash };
|
|
2739
|
+
},
|
|
2740
|
+
sendBatchTransaction: async (calls) => {
|
|
2741
|
+
const receipt = await account.sendBatchTransaction(calls);
|
|
2742
|
+
return { transactionHash: receipt.transactionHash };
|
|
2743
|
+
}
|
|
2744
|
+
};
|
|
2745
|
+
}
|
|
2746
|
+
function isAlchemySponsorshipLimitError(error) {
|
|
2747
|
+
const message = error instanceof Error ? error.message : String(error != null ? error : "");
|
|
2748
|
+
const normalized = message.toLowerCase();
|
|
2749
|
+
return normalized.includes("gas sponsorship limit") || normalized.includes("put your team over your gas sponsorship limit") || normalized.includes("buy gas credits in your gas manager dashboard");
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
// src/aa/create.ts
|
|
2753
|
+
import { createAlchemySmartAccount } from "@getpara/aa-alchemy";
|
|
2754
|
+
import { createPimlicoSmartAccount } from "@getpara/aa-pimlico";
|
|
2755
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
2756
|
+
async function createAAProviderState(options) {
|
|
2757
|
+
if (options.provider === "alchemy") {
|
|
2758
|
+
return createAlchemyAAState({
|
|
2759
|
+
chain: options.chain,
|
|
2760
|
+
owner: options.owner,
|
|
2761
|
+
rpcUrl: options.rpcUrl,
|
|
2762
|
+
callList: options.callList,
|
|
2763
|
+
mode: options.mode,
|
|
2764
|
+
apiKey: options.apiKey,
|
|
2765
|
+
gasPolicyId: options.gasPolicyId,
|
|
2766
|
+
sponsored: options.sponsored
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
return createPimlicoAAState({
|
|
2770
|
+
chain: options.chain,
|
|
2771
|
+
owner: options.owner,
|
|
2772
|
+
rpcUrl: options.rpcUrl,
|
|
2773
|
+
callList: options.callList,
|
|
2774
|
+
mode: options.mode,
|
|
2775
|
+
apiKey: options.apiKey
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
function getOwnerParams(owner) {
|
|
2779
|
+
if (!owner) {
|
|
2780
|
+
return null;
|
|
2781
|
+
}
|
|
2782
|
+
if ("privateKey" in owner) {
|
|
2783
|
+
return {
|
|
2784
|
+
para: void 0,
|
|
2785
|
+
signer: privateKeyToAccount(owner.privateKey)
|
|
2786
|
+
};
|
|
2787
|
+
}
|
|
2788
|
+
if ("signer" in owner) {
|
|
2789
|
+
return __spreadValues({
|
|
2790
|
+
para: owner.para,
|
|
2791
|
+
signer: owner.signer
|
|
2792
|
+
}, owner.address ? { address: owner.address } : {});
|
|
2793
|
+
}
|
|
2794
|
+
if ("para" in owner) {
|
|
2795
|
+
return __spreadValues({
|
|
2796
|
+
para: owner.para
|
|
2797
|
+
}, owner.address ? { address: owner.address } : {});
|
|
2798
|
+
}
|
|
2799
|
+
return null;
|
|
2800
|
+
}
|
|
2801
|
+
function getMissingOwnerState(plan, provider) {
|
|
2802
|
+
return {
|
|
2803
|
+
plan,
|
|
2804
|
+
AA: null,
|
|
2805
|
+
isPending: false,
|
|
2806
|
+
error: new Error(
|
|
2807
|
+
`${provider} AA account creation requires a signer or Para session.`
|
|
2808
|
+
)
|
|
2809
|
+
};
|
|
2810
|
+
}
|
|
2811
|
+
async function createAlchemyAAState(options) {
|
|
2812
|
+
var _a3, _b;
|
|
2813
|
+
const {
|
|
2814
|
+
chain,
|
|
2815
|
+
owner,
|
|
2816
|
+
rpcUrl,
|
|
2817
|
+
callList,
|
|
2818
|
+
mode,
|
|
2819
|
+
sponsored = true
|
|
2820
|
+
} = options;
|
|
2821
|
+
const resolved = resolveAlchemyConfig({
|
|
2822
|
+
calls: callList,
|
|
2823
|
+
chainsById: { [chain.id]: chain },
|
|
2824
|
+
modeOverride: mode,
|
|
2825
|
+
throwOnMissingConfig: true,
|
|
2826
|
+
getPreferredRpcUrl: () => rpcUrl,
|
|
2827
|
+
apiKey: options.apiKey,
|
|
2828
|
+
gasPolicyId: options.gasPolicyId
|
|
2829
|
+
});
|
|
2830
|
+
if (!resolved) {
|
|
2831
|
+
throw new Error("Alchemy AA config resolution failed.");
|
|
2832
|
+
}
|
|
2833
|
+
const apiKey = (_a3 = options.apiKey) != null ? _a3 : resolved.apiKey;
|
|
2834
|
+
const gasPolicyId = sponsored ? (_b = options.gasPolicyId) != null ? _b : readEnv(ALCHEMY_GAS_POLICY_ENVS) : void 0;
|
|
2835
|
+
const plan = __spreadProps(__spreadValues({}, resolved.plan), {
|
|
2836
|
+
sponsorship: gasPolicyId ? resolved.plan.sponsorship : "disabled",
|
|
2837
|
+
fallbackToEoa: false
|
|
2838
|
+
});
|
|
2839
|
+
const ownerParams = getOwnerParams(owner);
|
|
2840
|
+
if (!ownerParams) {
|
|
2841
|
+
return getMissingOwnerState(plan, "alchemy");
|
|
2842
|
+
}
|
|
2843
|
+
try {
|
|
2844
|
+
const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams), {
|
|
2845
|
+
apiKey,
|
|
2846
|
+
gasPolicyId,
|
|
2847
|
+
chain,
|
|
2848
|
+
rpcUrl,
|
|
2849
|
+
mode: plan.mode
|
|
2850
|
+
}));
|
|
2851
|
+
if (!smartAccount) {
|
|
2852
|
+
return {
|
|
2853
|
+
plan,
|
|
2854
|
+
AA: null,
|
|
2855
|
+
isPending: false,
|
|
2856
|
+
error: new Error("Alchemy AA account could not be initialized.")
|
|
2857
|
+
};
|
|
2858
|
+
}
|
|
2859
|
+
return {
|
|
2860
|
+
plan,
|
|
2861
|
+
AA: adaptSmartAccount(smartAccount),
|
|
2862
|
+
isPending: false,
|
|
2863
|
+
error: null
|
|
2864
|
+
};
|
|
2865
|
+
} catch (error) {
|
|
2866
|
+
return {
|
|
2867
|
+
plan,
|
|
2868
|
+
AA: null,
|
|
2869
|
+
isPending: false,
|
|
2870
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2871
|
+
};
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
async function createPimlicoAAState(options) {
|
|
2875
|
+
var _a3;
|
|
2876
|
+
const {
|
|
2877
|
+
chain,
|
|
2878
|
+
owner,
|
|
2879
|
+
rpcUrl,
|
|
2880
|
+
callList,
|
|
2881
|
+
mode
|
|
2882
|
+
} = options;
|
|
2883
|
+
const resolved = resolvePimlicoConfig({
|
|
2884
|
+
calls: callList,
|
|
2885
|
+
chainsById: { [chain.id]: chain },
|
|
2886
|
+
rpcUrl,
|
|
2887
|
+
modeOverride: mode,
|
|
2888
|
+
throwOnMissingConfig: true,
|
|
2889
|
+
apiKey: options.apiKey
|
|
2890
|
+
});
|
|
2891
|
+
if (!resolved) {
|
|
2892
|
+
throw new Error("Pimlico AA config resolution failed.");
|
|
2893
|
+
}
|
|
2894
|
+
const apiKey = (_a3 = options.apiKey) != null ? _a3 : resolved.apiKey;
|
|
2895
|
+
const plan = __spreadProps(__spreadValues({}, resolved.plan), {
|
|
2896
|
+
fallbackToEoa: false
|
|
2897
|
+
});
|
|
2898
|
+
const ownerParams = getOwnerParams(owner);
|
|
2899
|
+
if (!ownerParams) {
|
|
2900
|
+
return getMissingOwnerState(plan, "pimlico");
|
|
2901
|
+
}
|
|
2902
|
+
try {
|
|
2903
|
+
const smartAccount = await createPimlicoSmartAccount(__spreadProps(__spreadValues({}, ownerParams), {
|
|
2904
|
+
apiKey,
|
|
2905
|
+
chain,
|
|
2906
|
+
rpcUrl,
|
|
2907
|
+
mode: plan.mode
|
|
2908
|
+
}));
|
|
2909
|
+
if (!smartAccount) {
|
|
2910
|
+
return {
|
|
2911
|
+
plan,
|
|
2912
|
+
AA: null,
|
|
2913
|
+
isPending: false,
|
|
2914
|
+
error: new Error("Pimlico AA account could not be initialized.")
|
|
2915
|
+
};
|
|
2916
|
+
}
|
|
2917
|
+
return {
|
|
2918
|
+
plan,
|
|
2919
|
+
AA: adaptSmartAccount(smartAccount),
|
|
2920
|
+
isPending: false,
|
|
2921
|
+
error: null
|
|
2922
|
+
};
|
|
2923
|
+
} catch (error) {
|
|
2924
|
+
return {
|
|
2925
|
+
plan,
|
|
2926
|
+
AA: null,
|
|
2927
|
+
isPending: false,
|
|
2928
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2933
|
+
// src/cli/execution.ts
|
|
2934
|
+
function resolveAAProvider(config) {
|
|
2935
|
+
var _a3;
|
|
2936
|
+
const provider = (_a3 = config.aaProvider) != null ? _a3 : resolveDefaultProvider();
|
|
2937
|
+
if (!isProviderConfigured(provider)) {
|
|
2938
|
+
const envName = provider === "alchemy" ? "ALCHEMY_API_KEY" : "PIMLICO_API_KEY";
|
|
2939
|
+
throw new Error(
|
|
2940
|
+
`AA provider "${provider}" is selected but ${envName} is not configured.`
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
return provider;
|
|
2944
|
+
}
|
|
2945
|
+
function resolveCliExecutionDecision(params) {
|
|
2946
|
+
const { config, chain, callList } = params;
|
|
2947
|
+
if (config.execution === "eoa") {
|
|
2948
|
+
return { execution: "eoa" };
|
|
2949
|
+
}
|
|
2950
|
+
const provider = resolveAAProvider(config);
|
|
2951
|
+
const resolveOpts = {
|
|
2952
|
+
calls: callList,
|
|
2953
|
+
chainsById: { [chain.id]: chain },
|
|
2954
|
+
modeOverride: config.aaMode,
|
|
2955
|
+
throwOnMissingConfig: true
|
|
2956
|
+
};
|
|
2957
|
+
const resolved = provider === "alchemy" ? resolveAlchemyConfig(resolveOpts) : resolvePimlicoConfig(resolveOpts);
|
|
2958
|
+
if (!resolved) {
|
|
2959
|
+
throw new Error(`AA config resolution failed for provider "${provider}".`);
|
|
2960
|
+
}
|
|
2961
|
+
return {
|
|
2962
|
+
execution: "aa",
|
|
2963
|
+
provider,
|
|
2964
|
+
aaMode: resolved.plan.mode
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
async function createCliProviderState(params) {
|
|
2968
|
+
const { decision, chain, privateKey, rpcUrl, callList, sponsored } = params;
|
|
2969
|
+
if (decision.execution === "eoa") {
|
|
2970
|
+
return DISABLED_PROVIDER_STATE;
|
|
2971
|
+
}
|
|
2972
|
+
return createAAProviderState({
|
|
2973
|
+
provider: decision.provider,
|
|
2974
|
+
chain,
|
|
2975
|
+
owner: { privateKey },
|
|
2976
|
+
rpcUrl,
|
|
2977
|
+
callList,
|
|
2978
|
+
mode: decision.aaMode,
|
|
2979
|
+
sponsored
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
function describeExecutionDecision(decision) {
|
|
2983
|
+
if (decision.execution === "eoa") {
|
|
2984
|
+
return "eoa";
|
|
2985
|
+
}
|
|
2986
|
+
return `aa (${decision.provider}, ${decision.aaMode})`;
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
// src/cli/commands/wallet.ts
|
|
2188
2990
|
function txCommand() {
|
|
2189
|
-
var _a3, _b
|
|
2991
|
+
var _a3, _b;
|
|
2190
2992
|
const state = readState();
|
|
2191
2993
|
if (!state) {
|
|
2192
2994
|
console.log("No active session");
|
|
@@ -2210,17 +3012,7 @@ function txCommand() {
|
|
|
2210
3012
|
if (pending.length > 0) console.log();
|
|
2211
3013
|
console.log(`Signed (${signed.length}):`);
|
|
2212
3014
|
for (const tx of signed) {
|
|
2213
|
-
|
|
2214
|
-
if (tx.kind === "eip712_sign") {
|
|
2215
|
-
parts.push(`sig: ${(_c = tx.signature) == null ? void 0 : _c.slice(0, 20)}...`);
|
|
2216
|
-
if (tx.description) parts.push(tx.description);
|
|
2217
|
-
} else {
|
|
2218
|
-
parts.push(`hash: ${tx.txHash}`);
|
|
2219
|
-
if (tx.to) parts.push(`to: ${tx.to}`);
|
|
2220
|
-
if (tx.value) parts.push(`value: ${tx.value}`);
|
|
2221
|
-
}
|
|
2222
|
-
parts.push(`(${new Date(tx.timestamp).toLocaleTimeString()})`);
|
|
2223
|
-
console.log(parts.join(" "));
|
|
3015
|
+
console.log(formatSignedTxLine(tx, " \u2705"));
|
|
2224
3016
|
}
|
|
2225
3017
|
}
|
|
2226
3018
|
printDataFileLocation();
|
|
@@ -2236,6 +3028,13 @@ Run \`aomi tx\` to see available IDs.`
|
|
|
2236
3028
|
}
|
|
2237
3029
|
return pendingTx;
|
|
2238
3030
|
}
|
|
3031
|
+
function requirePendingTxs(state, txIds) {
|
|
3032
|
+
const uniqueIds = Array.from(new Set(txIds));
|
|
3033
|
+
if (uniqueIds.length !== txIds.length) {
|
|
3034
|
+
fatal("Duplicate transaction IDs are not allowed in a single `aomi sign` call.");
|
|
3035
|
+
}
|
|
3036
|
+
return uniqueIds.map((txId) => requirePendingTx(state, txId));
|
|
3037
|
+
}
|
|
2239
3038
|
function rewriteSessionState(runtime, state) {
|
|
2240
3039
|
let changed = false;
|
|
2241
3040
|
if (runtime.config.baseUrl !== state.baseUrl) {
|
|
@@ -2279,12 +3078,147 @@ async function persistResolvedSignerState(session, state, address, chainId) {
|
|
|
2279
3078
|
session.resolveWallet(address, chainId);
|
|
2280
3079
|
await session.syncUserState();
|
|
2281
3080
|
}
|
|
3081
|
+
function resolveChain(targetChainId, rpcUrl) {
|
|
3082
|
+
var _a3;
|
|
3083
|
+
return (_a3 = Object.values(viemChains).find(
|
|
3084
|
+
(candidate) => typeof candidate === "object" && candidate !== null && "id" in candidate && candidate.id === targetChainId
|
|
3085
|
+
)) != null ? _a3 : {
|
|
3086
|
+
id: targetChainId,
|
|
3087
|
+
name: `Chain ${targetChainId}`,
|
|
3088
|
+
nativeCurrency: {
|
|
3089
|
+
name: "ETH",
|
|
3090
|
+
symbol: "ETH",
|
|
3091
|
+
decimals: 18
|
|
3092
|
+
},
|
|
3093
|
+
rpcUrls: {
|
|
3094
|
+
default: {
|
|
3095
|
+
http: rpcUrl ? [rpcUrl] : []
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
function getPreferredRpcUrl(chain, override) {
|
|
3101
|
+
var _a3, _b, _c;
|
|
3102
|
+
return (_c = (_b = override != null ? override : chain.rpcUrls.default.http[0]) != null ? _b : (_a3 = chain.rpcUrls.public) == null ? void 0 : _a3.http[0]) != null ? _c : "";
|
|
3103
|
+
}
|
|
3104
|
+
async function promptForEoaFallback() {
|
|
3105
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
3106
|
+
return false;
|
|
3107
|
+
}
|
|
3108
|
+
const rl = createInterface({
|
|
3109
|
+
input: process.stdin,
|
|
3110
|
+
output: process.stdout
|
|
3111
|
+
});
|
|
3112
|
+
try {
|
|
3113
|
+
const answer = await rl.question(
|
|
3114
|
+
"Account abstraction not available, use EOA? [yes/no] "
|
|
3115
|
+
);
|
|
3116
|
+
const normalized = answer.trim().toLowerCase();
|
|
3117
|
+
return normalized === "y" || normalized === "yes";
|
|
3118
|
+
} finally {
|
|
3119
|
+
rl.close();
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
async function executeCliTransaction(params) {
|
|
3123
|
+
const { privateKey, currentChainId, chainsById, rpcUrl, providerState, callList } = params;
|
|
3124
|
+
const unsupportedWalletMethod = async () => {
|
|
3125
|
+
throw new Error("wallet_client_path_unavailable_in_cli_private_key_mode");
|
|
3126
|
+
};
|
|
3127
|
+
return executeWalletCalls({
|
|
3128
|
+
callList,
|
|
3129
|
+
currentChainId,
|
|
3130
|
+
capabilities: void 0,
|
|
3131
|
+
localPrivateKey: privateKey,
|
|
3132
|
+
providerState,
|
|
3133
|
+
sendCallsSyncAsync: unsupportedWalletMethod,
|
|
3134
|
+
sendTransactionAsync: unsupportedWalletMethod,
|
|
3135
|
+
switchChainAsync: async () => void 0,
|
|
3136
|
+
chainsById,
|
|
3137
|
+
getPreferredRpcUrl: (resolvedChain) => getPreferredRpcUrl(resolvedChain, rpcUrl)
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
async function executeTransactionWithFallback(params) {
|
|
3141
|
+
const { decision, privateKey, currentChainId, chainsById, primaryChain, rpcUrl, callList } = params;
|
|
3142
|
+
const runExecution = async (providerState2) => executeCliTransaction({
|
|
3143
|
+
privateKey,
|
|
3144
|
+
currentChainId,
|
|
3145
|
+
chainsById,
|
|
3146
|
+
rpcUrl,
|
|
3147
|
+
providerState: providerState2,
|
|
3148
|
+
callList
|
|
3149
|
+
});
|
|
3150
|
+
if (decision.execution === "eoa") {
|
|
3151
|
+
const providerState2 = await createCliProviderState({
|
|
3152
|
+
decision,
|
|
3153
|
+
chain: primaryChain,
|
|
3154
|
+
privateKey,
|
|
3155
|
+
rpcUrl: rpcUrl != null ? rpcUrl : "",
|
|
3156
|
+
callList
|
|
3157
|
+
});
|
|
3158
|
+
return {
|
|
3159
|
+
execution: await runExecution(providerState2),
|
|
3160
|
+
finalDecision: decision
|
|
3161
|
+
};
|
|
3162
|
+
}
|
|
3163
|
+
let providerState = await createCliProviderState({
|
|
3164
|
+
decision,
|
|
3165
|
+
chain: primaryChain,
|
|
3166
|
+
privateKey,
|
|
3167
|
+
rpcUrl: rpcUrl != null ? rpcUrl : "",
|
|
3168
|
+
callList,
|
|
3169
|
+
sponsored: true
|
|
3170
|
+
});
|
|
3171
|
+
try {
|
|
3172
|
+
return {
|
|
3173
|
+
execution: await runExecution(providerState),
|
|
3174
|
+
finalDecision: decision
|
|
3175
|
+
};
|
|
3176
|
+
} catch (error) {
|
|
3177
|
+
const shouldRetryUnsponsored = decision.provider === "alchemy" && isAlchemySponsorshipLimitError(error);
|
|
3178
|
+
if (shouldRetryUnsponsored) {
|
|
3179
|
+
console.log("AA sponsorship unavailable. Retrying AA with user-funded gas...");
|
|
3180
|
+
providerState = await createCliProviderState({
|
|
3181
|
+
decision,
|
|
3182
|
+
chain: primaryChain,
|
|
3183
|
+
privateKey,
|
|
3184
|
+
rpcUrl: rpcUrl != null ? rpcUrl : "",
|
|
3185
|
+
callList,
|
|
3186
|
+
sponsored: false
|
|
3187
|
+
});
|
|
3188
|
+
try {
|
|
3189
|
+
return {
|
|
3190
|
+
execution: await runExecution(providerState),
|
|
3191
|
+
finalDecision: decision
|
|
3192
|
+
};
|
|
3193
|
+
} catch (retryError) {
|
|
3194
|
+
error = retryError;
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
const useEoa = await promptForEoaFallback();
|
|
3198
|
+
if (!useEoa) {
|
|
3199
|
+
throw error;
|
|
3200
|
+
}
|
|
3201
|
+
const eoaDecision = { execution: "eoa" };
|
|
3202
|
+
console.log("Retrying with EOA execution...");
|
|
3203
|
+
const eoaProviderState = await createCliProviderState({
|
|
3204
|
+
decision: eoaDecision,
|
|
3205
|
+
chain: primaryChain,
|
|
3206
|
+
privateKey,
|
|
3207
|
+
rpcUrl: rpcUrl != null ? rpcUrl : "",
|
|
3208
|
+
callList
|
|
3209
|
+
});
|
|
3210
|
+
return {
|
|
3211
|
+
execution: await runExecution(eoaProviderState),
|
|
3212
|
+
finalDecision: eoaDecision
|
|
3213
|
+
};
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
2282
3216
|
async function signCommand(runtime) {
|
|
2283
|
-
var _a3, _b
|
|
2284
|
-
const
|
|
2285
|
-
if (
|
|
3217
|
+
var _a3, _b;
|
|
3218
|
+
const txIds = runtime.parsed.positional;
|
|
3219
|
+
if (txIds.length === 0) {
|
|
2286
3220
|
fatal(
|
|
2287
|
-
"Usage: aomi sign <tx-id
|
|
3221
|
+
"Usage: aomi sign <tx-id> [<tx-id> ...]\nRun `aomi tx` to see pending transaction IDs."
|
|
2288
3222
|
);
|
|
2289
3223
|
}
|
|
2290
3224
|
const privateKey = runtime.config.privateKey;
|
|
@@ -2303,10 +3237,10 @@ async function signCommand(runtime) {
|
|
|
2303
3237
|
fatal("No active session. Run `aomi chat` first.");
|
|
2304
3238
|
}
|
|
2305
3239
|
rewriteSessionState(runtime, state);
|
|
2306
|
-
const
|
|
3240
|
+
const pendingTxs = requirePendingTxs(state, txIds);
|
|
2307
3241
|
const session = createSessionFromState(state);
|
|
2308
3242
|
try {
|
|
2309
|
-
const account =
|
|
3243
|
+
const account = privateKeyToAccount2(privateKey);
|
|
2310
3244
|
if (state.publicKey && account.address.toLowerCase() !== state.publicKey.toLowerCase()) {
|
|
2311
3245
|
console.log(
|
|
2312
3246
|
`\u26A0\uFE0F Signer ${account.address} differs from session public key ${state.publicKey}`
|
|
@@ -2314,62 +3248,95 @@ async function signCommand(runtime) {
|
|
|
2314
3248
|
console.log(" Updating session to match the signing key...");
|
|
2315
3249
|
}
|
|
2316
3250
|
const rpcUrl = runtime.config.chainRpcUrl;
|
|
2317
|
-
const
|
|
2318
|
-
|
|
2319
|
-
(
|
|
2320
|
-
)) != null ? _c : {
|
|
2321
|
-
id: targetChainId,
|
|
2322
|
-
name: `Chain ${targetChainId}`,
|
|
2323
|
-
nativeCurrency: {
|
|
2324
|
-
name: "ETH",
|
|
2325
|
-
symbol: "ETH",
|
|
2326
|
-
decimals: 18
|
|
2327
|
-
},
|
|
2328
|
-
rpcUrls: {
|
|
2329
|
-
default: {
|
|
2330
|
-
http: [rpcUrl != null ? rpcUrl : ""]
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
2333
|
-
};
|
|
2334
|
-
const walletClient = createWalletClient({
|
|
2335
|
-
account,
|
|
2336
|
-
chain,
|
|
2337
|
-
transport: http(rpcUrl)
|
|
3251
|
+
const resolvedChainIds = pendingTxs.map((tx) => {
|
|
3252
|
+
var _a4, _b2;
|
|
3253
|
+
return (_b2 = (_a4 = tx.chainId) != null ? _a4 : state.chainId) != null ? _b2 : 1;
|
|
2338
3254
|
});
|
|
3255
|
+
const primaryChainId = resolvedChainIds[0];
|
|
3256
|
+
const chain = resolveChain(primaryChainId, rpcUrl);
|
|
3257
|
+
const resolvedRpcUrl = getPreferredRpcUrl(chain, rpcUrl);
|
|
3258
|
+
const chainsById = Object.fromEntries(
|
|
3259
|
+
Array.from(new Set(resolvedChainIds)).map((chainId) => [
|
|
3260
|
+
chainId,
|
|
3261
|
+
resolveChain(chainId, rpcUrl)
|
|
3262
|
+
])
|
|
3263
|
+
);
|
|
2339
3264
|
console.log(`Signer: ${account.address}`);
|
|
2340
|
-
console.log(`
|
|
2341
|
-
|
|
2342
|
-
let
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
3265
|
+
console.log(`IDs: ${pendingTxs.map((tx) => tx.id).join(", ")}`);
|
|
3266
|
+
let signedRecords = [];
|
|
3267
|
+
let backendNotifications = [];
|
|
3268
|
+
if (pendingTxs.every((tx) => tx.kind === "transaction")) {
|
|
3269
|
+
console.log(`Kind: transaction${pendingTxs.length > 1 ? " (batch)" : ""}`);
|
|
3270
|
+
for (const tx of pendingTxs) {
|
|
3271
|
+
console.log(`Tx: ${tx.id} -> ${tx.to}`);
|
|
3272
|
+
if (tx.value) console.log(`Value: ${tx.value}`);
|
|
3273
|
+
if ((_a3 = tx.chainId) != null ? _a3 : state.chainId) console.log(`Chain: ${(_b = tx.chainId) != null ? _b : state.chainId}`);
|
|
3274
|
+
if (tx.data) {
|
|
3275
|
+
console.log(`Data: ${tx.data.slice(0, 40)}...`);
|
|
3276
|
+
}
|
|
2350
3277
|
}
|
|
2351
3278
|
console.log();
|
|
2352
|
-
const
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
3279
|
+
const callList = pendingTxs.flatMap(
|
|
3280
|
+
(tx, index) => pendingTxToCallList(__spreadProps(__spreadValues({}, tx), {
|
|
3281
|
+
chainId: resolvedChainIds[index]
|
|
3282
|
+
}))
|
|
3283
|
+
);
|
|
3284
|
+
if (callList.length > 1 && rpcUrl && new Set(callList.map((call) => call.chainId)).size > 1) {
|
|
3285
|
+
fatal("A single `--rpc-url` override cannot be used for a mixed-chain multi-sign request.");
|
|
3286
|
+
}
|
|
3287
|
+
const decision = resolveCliExecutionDecision({
|
|
3288
|
+
config: runtime.config,
|
|
3289
|
+
chain,
|
|
3290
|
+
callList
|
|
2356
3291
|
});
|
|
2357
|
-
console.log(
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
};
|
|
2368
|
-
|
|
3292
|
+
console.log(`Exec: ${describeExecutionDecision(decision)}`);
|
|
3293
|
+
const { execution, finalDecision } = await executeTransactionWithFallback({
|
|
3294
|
+
decision,
|
|
3295
|
+
privateKey,
|
|
3296
|
+
currentChainId: primaryChainId,
|
|
3297
|
+
chainsById,
|
|
3298
|
+
primaryChain: chain,
|
|
3299
|
+
rpcUrl,
|
|
3300
|
+
callList
|
|
3301
|
+
});
|
|
3302
|
+
console.log(`\u2705 Sent! Hash: ${execution.txHash}`);
|
|
3303
|
+
if (execution.txHashes.length > 1) {
|
|
3304
|
+
console.log(`Count: ${execution.txHashes.length}`);
|
|
3305
|
+
}
|
|
3306
|
+
if (execution.sponsored) {
|
|
3307
|
+
console.log("Gas: sponsored");
|
|
3308
|
+
}
|
|
3309
|
+
if (execution.AAAddress) {
|
|
3310
|
+
console.log(`AA: ${execution.AAAddress}`);
|
|
3311
|
+
}
|
|
3312
|
+
if (execution.delegationAddress) {
|
|
3313
|
+
console.log(`Deleg: ${execution.delegationAddress}`);
|
|
3314
|
+
}
|
|
3315
|
+
signedRecords = pendingTxs.map(
|
|
3316
|
+
(tx, index) => toSignedTransactionRecord(
|
|
3317
|
+
tx,
|
|
3318
|
+
execution,
|
|
3319
|
+
account.address,
|
|
3320
|
+
resolvedChainIds[index],
|
|
3321
|
+
Date.now(),
|
|
3322
|
+
finalDecision.execution === "aa" ? finalDecision.provider : void 0,
|
|
3323
|
+
finalDecision.execution === "aa" ? finalDecision.aaMode : void 0
|
|
3324
|
+
)
|
|
3325
|
+
);
|
|
3326
|
+
backendNotifications = pendingTxs.map(() => ({
|
|
2369
3327
|
type: "wallet:tx_complete",
|
|
2370
|
-
payload: { txHash:
|
|
2371
|
-
};
|
|
3328
|
+
payload: { txHash: execution.txHash, status: "success" }
|
|
3329
|
+
}));
|
|
2372
3330
|
} else {
|
|
3331
|
+
if (pendingTxs.length > 1) {
|
|
3332
|
+
fatal("Batch signing is only supported for transaction requests, not EIP-712 requests.");
|
|
3333
|
+
}
|
|
3334
|
+
const pendingTx = pendingTxs[0];
|
|
3335
|
+
const walletClient = createWalletClient({
|
|
3336
|
+
account,
|
|
3337
|
+
chain,
|
|
3338
|
+
transport: http(resolvedRpcUrl)
|
|
3339
|
+
});
|
|
2373
3340
|
const typedData = pendingTx.payload.typed_data;
|
|
2374
3341
|
if (!typedData) {
|
|
2375
3342
|
fatal("EIP-712 request is missing typed_data payload.");
|
|
@@ -2391,36 +3358,42 @@ async function signCommand(runtime) {
|
|
|
2391
3358
|
message
|
|
2392
3359
|
});
|
|
2393
3360
|
console.log(`\u2705 Signed! Signature: ${signature.slice(0, 20)}...`);
|
|
2394
|
-
|
|
2395
|
-
id:
|
|
3361
|
+
signedRecords = [{
|
|
3362
|
+
id: pendingTx.id,
|
|
2396
3363
|
kind: "eip712_sign",
|
|
2397
3364
|
signature,
|
|
2398
3365
|
from: account.address,
|
|
2399
3366
|
description: pendingTx.description,
|
|
2400
3367
|
timestamp: Date.now()
|
|
2401
|
-
};
|
|
2402
|
-
|
|
3368
|
+
}];
|
|
3369
|
+
backendNotifications = [{
|
|
2403
3370
|
type: "wallet_eip712_response",
|
|
2404
3371
|
payload: {
|
|
2405
3372
|
status: "success",
|
|
2406
3373
|
signature,
|
|
2407
3374
|
description: pendingTx.description
|
|
2408
3375
|
}
|
|
2409
|
-
};
|
|
3376
|
+
}];
|
|
2410
3377
|
}
|
|
2411
3378
|
await persistResolvedSignerState(
|
|
2412
3379
|
session,
|
|
2413
3380
|
state,
|
|
2414
3381
|
account.address,
|
|
2415
|
-
|
|
3382
|
+
primaryChainId
|
|
2416
3383
|
);
|
|
2417
|
-
|
|
3384
|
+
for (const txId of txIds) {
|
|
3385
|
+
removePendingTx(state, txId);
|
|
3386
|
+
}
|
|
2418
3387
|
const freshState = readState();
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
3388
|
+
for (const signedRecord of signedRecords) {
|
|
3389
|
+
addSignedTx(freshState, signedRecord);
|
|
3390
|
+
}
|
|
3391
|
+
for (const backendNotification of backendNotifications) {
|
|
3392
|
+
await session.client.sendSystemMessage(
|
|
3393
|
+
state.sessionId,
|
|
3394
|
+
JSON.stringify(backendNotification)
|
|
3395
|
+
);
|
|
3396
|
+
}
|
|
2424
3397
|
console.log("Backend notified.");
|
|
2425
3398
|
} catch (err) {
|
|
2426
3399
|
if (err instanceof CliExit) throw err;
|
|
@@ -2450,7 +3423,8 @@ Usage:
|
|
|
2450
3423
|
Delete a local session file (session-id or session-N)
|
|
2451
3424
|
aomi log Show full conversation history with tool results
|
|
2452
3425
|
aomi tx List pending and signed transactions
|
|
2453
|
-
aomi sign <tx-id>
|
|
3426
|
+
aomi sign <tx-id> [<tx-id> ...] [--aa | --eoa] [--aa-provider <name>] [--aa-mode <mode>]
|
|
3427
|
+
Sign and submit a pending transaction
|
|
2454
3428
|
aomi status Show current session state
|
|
2455
3429
|
aomi events List system events
|
|
2456
3430
|
aomi close Close the current session
|
|
@@ -2465,12 +3439,28 @@ Options:
|
|
|
2465
3439
|
--rpc-url <url> RPC URL for transaction submission
|
|
2466
3440
|
--verbose, -v Show tool calls and streaming output (for chat)
|
|
2467
3441
|
|
|
3442
|
+
Sign options:
|
|
3443
|
+
aomi sign <tx-id> --aa
|
|
3444
|
+
Require account-abstraction execution (default)
|
|
3445
|
+
aomi sign <tx-id> --eoa
|
|
3446
|
+
Force plain EOA execution
|
|
3447
|
+
aomi sign <tx-id> --aa-provider <name>
|
|
3448
|
+
AA provider: alchemy | pimlico
|
|
3449
|
+
aomi sign <tx-id> --aa-mode <mode>
|
|
3450
|
+
AA mode: 4337 | 7702
|
|
3451
|
+
|
|
2468
3452
|
Environment (overridden by flags):
|
|
2469
3453
|
AOMI_BASE_URL Backend URL
|
|
2470
3454
|
AOMI_API_KEY API key
|
|
2471
3455
|
AOMI_APP App
|
|
2472
3456
|
AOMI_MODEL Model rig
|
|
2473
3457
|
AOMI_PUBLIC_KEY Wallet address
|
|
3458
|
+
AOMI_AA_PROVIDER AA provider: alchemy | pimlico
|
|
3459
|
+
AOMI_AA_MODE AA mode: 4337 | 7702
|
|
3460
|
+
ALCHEMY_API_KEY Alchemy AA API key
|
|
3461
|
+
ALCHEMY_GAS_POLICY_ID
|
|
3462
|
+
Optional Alchemy gas sponsorship policy ID
|
|
3463
|
+
PIMLICO_API_KEY Pimlico AA API key
|
|
2474
3464
|
PRIVATE_KEY Hex private key for signing
|
|
2475
3465
|
CHAIN_RPC_URL RPC URL for transaction submission
|
|
2476
3466
|
`.trim());
|