@aomi-labs/client 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +239 -15
- package/dist/index.cjs +92 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/skills/aomi-transact/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -307,7 +307,7 @@ All config can be passed as flags (which take priority over env vars):
|
|
|
307
307
|
|
|
308
308
|
| Flag | Env Variable | Default | Description |
|
|
309
309
|
| ----------------------- | ----------------- | ---------------------- | -------------------------------------------- |
|
|
310
|
-
| `--backend-url` | `
|
|
310
|
+
| `--backend-url` | `AOMI_BACKEND_URL` | `https://api.aomi.dev` | Backend URL |
|
|
311
311
|
| `--api-key` | `AOMI_API_KEY` | — | API key for non-default apps |
|
|
312
312
|
| `--app` | `AOMI_APP` | `default` | App |
|
|
313
313
|
| `--model` | `AOMI_MODEL` | — | Model rig to apply before chat |
|
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,7 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
|
22
22
|
// package.json
|
|
23
23
|
var package_default = {
|
|
24
24
|
name: "@aomi-labs/client",
|
|
25
|
-
version: "0.1.
|
|
25
|
+
version: "0.1.19",
|
|
26
26
|
description: "Platform-agnostic TypeScript client for the Aomi backend API",
|
|
27
27
|
type: "module",
|
|
28
28
|
main: "./dist/index.cjs",
|
|
@@ -53,9 +53,10 @@ var package_default = {
|
|
|
53
53
|
"clean:dist": "rm -rf dist"
|
|
54
54
|
},
|
|
55
55
|
dependencies: {
|
|
56
|
-
"@
|
|
57
|
-
"@getpara/aa-
|
|
58
|
-
|
|
56
|
+
"@alchemy/wallet-apis": "5.0.0-beta.22",
|
|
57
|
+
"@getpara/aa-alchemy": "2.21.0",
|
|
58
|
+
"@getpara/aa-pimlico": "2.21.0",
|
|
59
|
+
viem: "^2.47.11"
|
|
59
60
|
}
|
|
60
61
|
};
|
|
61
62
|
|
|
@@ -68,17 +69,17 @@ var CliExit = class extends Error {
|
|
|
68
69
|
};
|
|
69
70
|
function fatal(message) {
|
|
70
71
|
const RED = "\x1B[31m";
|
|
71
|
-
const
|
|
72
|
-
const
|
|
72
|
+
const DIM2 = "\x1B[2m";
|
|
73
|
+
const RESET2 = "\x1B[0m";
|
|
73
74
|
const lines = message.split("\n");
|
|
74
75
|
const [headline, ...details] = lines;
|
|
75
|
-
console.error(`${RED}\u274C ${headline}${
|
|
76
|
+
console.error(`${RED}\u274C ${headline}${RESET2}`);
|
|
76
77
|
for (const detail of details) {
|
|
77
78
|
if (!detail.trim()) {
|
|
78
79
|
console.error("");
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
81
|
-
console.error(`${
|
|
82
|
+
console.error(`${DIM2}${detail}${RESET2}`);
|
|
82
83
|
}
|
|
83
84
|
throw new CliExit(1);
|
|
84
85
|
}
|
|
@@ -202,7 +203,7 @@ function getConfig(parsed) {
|
|
|
202
203
|
fatal("`--aa-provider` and `--aa-mode` cannot be used with `--eoa`.");
|
|
203
204
|
}
|
|
204
205
|
return {
|
|
205
|
-
baseUrl: (_d = (_c = parsed.flags["backend-url"]) != null ? _c : process.env.
|
|
206
|
+
baseUrl: (_d = (_c = parsed.flags["backend-url"]) != null ? _c : process.env.AOMI_BACKEND_URL) != null ? _d : "https://api.aomi.dev",
|
|
206
207
|
apiKey: (_e = parsed.flags["api-key"]) != null ? _e : process.env.AOMI_API_KEY,
|
|
207
208
|
app: (_g = (_f = parsed.flags["app"]) != null ? _f : process.env.AOMI_APP) != null ? _g : "default",
|
|
208
209
|
model: (_h = parsed.flags["model"]) != null ? _h : process.env.AOMI_MODEL,
|
|
@@ -1157,6 +1158,39 @@ var AomiClient = class {
|
|
|
1157
1158
|
}
|
|
1158
1159
|
return postState(this.baseUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
1159
1160
|
}
|
|
1161
|
+
// ===========================================================================
|
|
1162
|
+
// Batch Simulation
|
|
1163
|
+
// ===========================================================================
|
|
1164
|
+
/**
|
|
1165
|
+
* Simulate transactions as an atomic batch.
|
|
1166
|
+
* Each tx sees state changes from previous txs (e.g., approve → swap).
|
|
1167
|
+
* Sends full tx payloads — the backend does not look up by ID.
|
|
1168
|
+
*/
|
|
1169
|
+
async simulateBatch(sessionId, transactions, options) {
|
|
1170
|
+
const url = joinApiPath(this.baseUrl, "/api/simulate");
|
|
1171
|
+
const headers = new Headers(
|
|
1172
|
+
withSessionHeader(sessionId, { "Content-Type": "application/json" })
|
|
1173
|
+
);
|
|
1174
|
+
if (this.apiKey) {
|
|
1175
|
+
headers.set(API_KEY_HEADER, this.apiKey);
|
|
1176
|
+
}
|
|
1177
|
+
const payload = {
|
|
1178
|
+
transactions,
|
|
1179
|
+
from: options == null ? void 0 : options.from,
|
|
1180
|
+
chain_id: options == null ? void 0 : options.chainId
|
|
1181
|
+
};
|
|
1182
|
+
const response = await fetch(url, {
|
|
1183
|
+
method: "POST",
|
|
1184
|
+
headers,
|
|
1185
|
+
body: JSON.stringify(payload)
|
|
1186
|
+
});
|
|
1187
|
+
if (!response.ok) {
|
|
1188
|
+
const body = await response.text().catch(() => "");
|
|
1189
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}${body ? `
|
|
1190
|
+
${body}` : ""}`);
|
|
1191
|
+
}
|
|
1192
|
+
return await response.json();
|
|
1193
|
+
}
|
|
1160
1194
|
};
|
|
1161
1195
|
|
|
1162
1196
|
// src/types.ts
|
|
@@ -2940,6 +2974,92 @@ async function sessionCommand(runtime) {
|
|
|
2940
2974
|
);
|
|
2941
2975
|
}
|
|
2942
2976
|
|
|
2977
|
+
// src/cli/commands/simulate.ts
|
|
2978
|
+
function requirePendingTx(state, txId) {
|
|
2979
|
+
var _a3;
|
|
2980
|
+
const pendingTx = ((_a3 = state.pendingTxs) != null ? _a3 : []).find((tx) => tx.id === txId);
|
|
2981
|
+
if (!pendingTx) {
|
|
2982
|
+
fatal(
|
|
2983
|
+
`No pending transaction with id "${txId}".
|
|
2984
|
+
Run \`aomi tx\` to see available IDs.`
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
return pendingTx;
|
|
2988
|
+
}
|
|
2989
|
+
async function simulateCommand(runtime) {
|
|
2990
|
+
var _a3, _b, _c;
|
|
2991
|
+
const state = readState();
|
|
2992
|
+
if (!state) {
|
|
2993
|
+
fatal("No active session. Run `aomi chat` first.");
|
|
2994
|
+
}
|
|
2995
|
+
const txIds = runtime.parsed.positional;
|
|
2996
|
+
if (txIds.length === 0) {
|
|
2997
|
+
fatal("Usage: aomi simulate <tx-id> [<tx-id> ...]\nRun `aomi tx` to see available IDs.");
|
|
2998
|
+
}
|
|
2999
|
+
const pendingTxs = txIds.map((txId) => requirePendingTx(state, txId));
|
|
3000
|
+
console.log(
|
|
3001
|
+
`${DIM}Simulating ${txIds.length} transaction(s) as atomic batch...${RESET}`
|
|
3002
|
+
);
|
|
3003
|
+
const client = new AomiClient({
|
|
3004
|
+
baseUrl: state.baseUrl,
|
|
3005
|
+
apiKey: state.apiKey
|
|
3006
|
+
});
|
|
3007
|
+
const transactions = pendingTxs.map((tx) => {
|
|
3008
|
+
var _a4;
|
|
3009
|
+
return {
|
|
3010
|
+
to: tx.to,
|
|
3011
|
+
value: tx.value,
|
|
3012
|
+
data: tx.data,
|
|
3013
|
+
label: (_a4 = tx.description) != null ? _a4 : tx.id
|
|
3014
|
+
};
|
|
3015
|
+
});
|
|
3016
|
+
const response = await client.simulateBatch(
|
|
3017
|
+
state.sessionId,
|
|
3018
|
+
transactions,
|
|
3019
|
+
{
|
|
3020
|
+
from: (_a3 = state.publicKey) != null ? _a3 : void 0,
|
|
3021
|
+
chainId: (_b = state.chainId) != null ? _b : void 0
|
|
3022
|
+
}
|
|
3023
|
+
);
|
|
3024
|
+
const { result } = response;
|
|
3025
|
+
const modeLabel = result.stateful ? "stateful (Anvil snapshot)" : "stateless (independent eth_call)";
|
|
3026
|
+
console.log(`
|
|
3027
|
+
Batch simulation (${modeLabel}):`);
|
|
3028
|
+
console.log(`From: ${result.from} | Network: ${result.network}
|
|
3029
|
+
`);
|
|
3030
|
+
for (const step of result.steps) {
|
|
3031
|
+
const icon = step.success ? `${GREEN}\u2713${RESET}` : `\x1B[31m\u2717${RESET}`;
|
|
3032
|
+
const label = step.label || `Step ${step.step}`;
|
|
3033
|
+
const gasInfo = step.gas_used ? ` | gas: ${step.gas_used.toLocaleString()}` : "";
|
|
3034
|
+
console.log(` ${icon} ${step.step}. ${label}`);
|
|
3035
|
+
console.log(` ${DIM}to: ${step.tx.to} | value: ${step.tx.value_eth} ETH${gasInfo}${RESET}`);
|
|
3036
|
+
if (!step.success && step.revert_reason) {
|
|
3037
|
+
console.log(` \x1B[31mRevert: ${step.revert_reason}${RESET}`);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
if (result.total_gas) {
|
|
3041
|
+
console.log(`
|
|
3042
|
+
${DIM}Total gas: ${result.total_gas.toLocaleString()}${RESET}`);
|
|
3043
|
+
}
|
|
3044
|
+
if (result.fee) {
|
|
3045
|
+
const feeEth = (Number(result.fee.amount_wei) / 1e18).toFixed(6);
|
|
3046
|
+
console.log(
|
|
3047
|
+
`Service fee: ${feeEth} ETH \u2192 ${result.fee.recipient}`
|
|
3048
|
+
);
|
|
3049
|
+
}
|
|
3050
|
+
console.log();
|
|
3051
|
+
if (result.batch_success) {
|
|
3052
|
+
console.log(
|
|
3053
|
+
`${GREEN}All steps passed.${RESET} Run \`aomi sign ${txIds.join(" ")}\` to execute.`
|
|
3054
|
+
);
|
|
3055
|
+
} else {
|
|
3056
|
+
const failed = result.steps.find((s) => !s.success);
|
|
3057
|
+
console.log(
|
|
3058
|
+
`\x1B[31mBatch failed at step ${(_c = failed == null ? void 0 : failed.step) != null ? _c : "?"}.${RESET} Fix the issue and re-queue, or run \`aomi sign\` on the successful prefix.`
|
|
3059
|
+
);
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
|
|
2943
3063
|
// src/cli/commands/wallet.ts
|
|
2944
3064
|
import { createWalletClient, http } from "viem";
|
|
2945
3065
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
@@ -3277,6 +3397,25 @@ async function createAlchemyAAState(options) {
|
|
|
3277
3397
|
if (ownerParams.kind === "unsupported_adapter") {
|
|
3278
3398
|
return getUnsupportedAdapterState(plan, ownerParams.adapter);
|
|
3279
3399
|
}
|
|
3400
|
+
if (owner.kind === "direct") {
|
|
3401
|
+
try {
|
|
3402
|
+
return await createAlchemyWalletApisState({
|
|
3403
|
+
plan,
|
|
3404
|
+
chain,
|
|
3405
|
+
privateKey: owner.privateKey,
|
|
3406
|
+
apiKey,
|
|
3407
|
+
gasPolicyId,
|
|
3408
|
+
mode: plan.mode
|
|
3409
|
+
});
|
|
3410
|
+
} catch (error) {
|
|
3411
|
+
return {
|
|
3412
|
+
plan,
|
|
3413
|
+
AA: null,
|
|
3414
|
+
isPending: false,
|
|
3415
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3416
|
+
};
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3280
3419
|
try {
|
|
3281
3420
|
const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
3282
3421
|
apiKey,
|
|
@@ -3308,6 +3447,46 @@ async function createAlchemyAAState(options) {
|
|
|
3308
3447
|
};
|
|
3309
3448
|
}
|
|
3310
3449
|
}
|
|
3450
|
+
async function createAlchemyWalletApisState(params) {
|
|
3451
|
+
const { createSmartWalletClient, alchemyWalletTransport } = await import("@alchemy/wallet-apis");
|
|
3452
|
+
const signer = privateKeyToAccount(params.privateKey);
|
|
3453
|
+
const walletClient = createSmartWalletClient(__spreadValues({
|
|
3454
|
+
transport: alchemyWalletTransport({ apiKey: params.apiKey }),
|
|
3455
|
+
chain: params.chain,
|
|
3456
|
+
signer
|
|
3457
|
+
}, params.gasPolicyId ? { paymaster: { policyId: params.gasPolicyId } } : {}));
|
|
3458
|
+
let accountAddress = signer.address;
|
|
3459
|
+
if (params.mode === "4337") {
|
|
3460
|
+
const account = await walletClient.requestAccount();
|
|
3461
|
+
accountAddress = account.address;
|
|
3462
|
+
}
|
|
3463
|
+
const sendCalls = async (calls) => {
|
|
3464
|
+
var _a3, _b;
|
|
3465
|
+
const result = await walletClient.sendCalls(__spreadProps(__spreadValues({}, params.mode === "4337" ? { account: accountAddress } : {}), {
|
|
3466
|
+
calls
|
|
3467
|
+
}));
|
|
3468
|
+
const status = await walletClient.waitForCallsStatus({ id: result.id });
|
|
3469
|
+
const transactionHash = (_b = (_a3 = status.receipts) == null ? void 0 : _a3[0]) == null ? void 0 : _b.transactionHash;
|
|
3470
|
+
if (!transactionHash) {
|
|
3471
|
+
throw new Error("Alchemy Wallets API did not return a transaction hash.");
|
|
3472
|
+
}
|
|
3473
|
+
return { transactionHash };
|
|
3474
|
+
};
|
|
3475
|
+
const AA = {
|
|
3476
|
+
provider: "alchemy",
|
|
3477
|
+
mode: params.mode,
|
|
3478
|
+
AAAddress: accountAddress,
|
|
3479
|
+
delegationAddress: params.mode === "7702" ? signer.address : void 0,
|
|
3480
|
+
sendTransaction: async (call) => sendCalls([call]),
|
|
3481
|
+
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
3482
|
+
};
|
|
3483
|
+
return {
|
|
3484
|
+
plan: params.plan,
|
|
3485
|
+
AA,
|
|
3486
|
+
isPending: false,
|
|
3487
|
+
error: null
|
|
3488
|
+
};
|
|
3489
|
+
}
|
|
3311
3490
|
async function createPimlicoAAState(options) {
|
|
3312
3491
|
var _a3;
|
|
3313
3492
|
const {
|
|
@@ -3491,7 +3670,7 @@ function txCommand() {
|
|
|
3491
3670
|
}
|
|
3492
3671
|
printDataFileLocation();
|
|
3493
3672
|
}
|
|
3494
|
-
function
|
|
3673
|
+
function requirePendingTx2(state, txId) {
|
|
3495
3674
|
var _a3;
|
|
3496
3675
|
const pendingTx = ((_a3 = state.pendingTxs) != null ? _a3 : []).find((tx) => tx.id === txId);
|
|
3497
3676
|
if (!pendingTx) {
|
|
@@ -3507,7 +3686,7 @@ function requirePendingTxs(state, txIds) {
|
|
|
3507
3686
|
if (uniqueIds.length !== txIds.length) {
|
|
3508
3687
|
fatal("Duplicate transaction IDs are not allowed in a single `aomi sign` call.");
|
|
3509
3688
|
}
|
|
3510
|
-
return uniqueIds.map((txId) =>
|
|
3689
|
+
return uniqueIds.map((txId) => requirePendingTx2(state, txId));
|
|
3511
3690
|
}
|
|
3512
3691
|
function rewriteSessionState(runtime, state) {
|
|
3513
3692
|
let changed = false;
|
|
@@ -3669,7 +3848,7 @@ async function executeTransactionWithFallback(params) {
|
|
|
3669
3848
|
}
|
|
3670
3849
|
}
|
|
3671
3850
|
async function signCommand(runtime) {
|
|
3672
|
-
var _a3, _b;
|
|
3851
|
+
var _a3, _b, _c, _d;
|
|
3673
3852
|
const txIds = runtime.parsed.positional;
|
|
3674
3853
|
if (txIds.length === 0) {
|
|
3675
3854
|
fatal(
|
|
@@ -3739,6 +3918,46 @@ async function signCommand(runtime) {
|
|
|
3739
3918
|
if (callList.length > 1 && rpcUrl && new Set(callList.map((call) => call.chainId)).size > 1) {
|
|
3740
3919
|
fatal("A single `--rpc-url` override cannot be used for a mixed-chain multi-sign request.");
|
|
3741
3920
|
}
|
|
3921
|
+
try {
|
|
3922
|
+
const simResponse = await session.client.simulateBatch(
|
|
3923
|
+
state.sessionId,
|
|
3924
|
+
pendingTxs.map((tx) => {
|
|
3925
|
+
var _a4;
|
|
3926
|
+
return {
|
|
3927
|
+
to: tx.to,
|
|
3928
|
+
value: tx.value,
|
|
3929
|
+
data: tx.data,
|
|
3930
|
+
label: (_a4 = tx.description) != null ? _a4 : tx.id
|
|
3931
|
+
};
|
|
3932
|
+
}),
|
|
3933
|
+
{
|
|
3934
|
+
from: account.address,
|
|
3935
|
+
chainId: primaryChainId
|
|
3936
|
+
}
|
|
3937
|
+
);
|
|
3938
|
+
const { result: sim } = simResponse;
|
|
3939
|
+
if (!sim.batch_success) {
|
|
3940
|
+
const failed = sim.steps.find((s) => !s.success);
|
|
3941
|
+
fatal(
|
|
3942
|
+
`Simulation failed at step ${(_c = failed == null ? void 0 : failed.step) != null ? _c : "?"}: ${(_d = failed == null ? void 0 : failed.revert_reason) != null ? _d : "unknown"}`
|
|
3943
|
+
);
|
|
3944
|
+
}
|
|
3945
|
+
if (sim.fee) {
|
|
3946
|
+
const feeEth = (Number(sim.fee.amount_wei) / 1e18).toFixed(6);
|
|
3947
|
+
console.log(
|
|
3948
|
+
`Fee: ${feeEth} ETH \u2192 ${sim.fee.recipient.slice(0, 10)}...`
|
|
3949
|
+
);
|
|
3950
|
+
callList.push({
|
|
3951
|
+
to: sim.fee.recipient,
|
|
3952
|
+
value: sim.fee.amount_wei,
|
|
3953
|
+
chainId: primaryChainId
|
|
3954
|
+
});
|
|
3955
|
+
}
|
|
3956
|
+
} catch (e) {
|
|
3957
|
+
console.log(
|
|
3958
|
+
`${DIM}Simulation unavailable, skipping fee injection.${RESET}`
|
|
3959
|
+
);
|
|
3960
|
+
}
|
|
3742
3961
|
const decision = resolveCliExecutionDecision({
|
|
3743
3962
|
config: runtime.config,
|
|
3744
3963
|
chain,
|
|
@@ -3875,6 +4094,8 @@ Usage:
|
|
|
3875
4094
|
Delete a local session file (session-id or session-N)
|
|
3876
4095
|
aomi log Show full conversation history with tool results
|
|
3877
4096
|
aomi tx List pending and signed transactions
|
|
4097
|
+
aomi simulate <tx-id> [<tx-id> ...]
|
|
4098
|
+
Batch-simulate pending txs atomically (approve \u2192 swap)
|
|
3878
4099
|
aomi sign <tx-id> [<tx-id> ...] [--eoa | --aa] [--aa-provider <name>] [--aa-mode <mode>]
|
|
3879
4100
|
Sign and submit a pending transaction
|
|
3880
4101
|
aomi secret list List configured secrets for the active session
|
|
@@ -3914,7 +4135,7 @@ Default signing behavior:
|
|
|
3914
4135
|
fall back to EOA automatically if AA is unavailable
|
|
3915
4136
|
|
|
3916
4137
|
Environment (overridden by flags):
|
|
3917
|
-
|
|
4138
|
+
AOMI_BACKEND_URL Backend URL
|
|
3918
4139
|
AOMI_API_KEY API key
|
|
3919
4140
|
AOMI_APP App
|
|
3920
4141
|
AOMI_MODEL Model rig
|
|
@@ -3959,6 +4180,9 @@ async function main(runtime) {
|
|
|
3959
4180
|
case "sign":
|
|
3960
4181
|
await signCommand(runtime);
|
|
3961
4182
|
break;
|
|
4183
|
+
case "simulate":
|
|
4184
|
+
await simulateCommand(runtime);
|
|
4185
|
+
break;
|
|
3962
4186
|
case "status":
|
|
3963
4187
|
await statusCommand(runtime);
|
|
3964
4188
|
break;
|
|
@@ -3996,7 +4220,7 @@ function isPnpmExecWrapper() {
|
|
|
3996
4220
|
async function runCli(argv = process.argv) {
|
|
3997
4221
|
const runtime = createRuntime(argv);
|
|
3998
4222
|
const RED = "\x1B[31m";
|
|
3999
|
-
const
|
|
4223
|
+
const RESET2 = "\x1B[0m";
|
|
4000
4224
|
const strictExit = process.env.AOMI_CLI_STRICT_EXIT === "1";
|
|
4001
4225
|
try {
|
|
4002
4226
|
await main(runtime);
|
|
@@ -4009,7 +4233,7 @@ async function runCli(argv = process.argv) {
|
|
|
4009
4233
|
return;
|
|
4010
4234
|
}
|
|
4011
4235
|
const message = err instanceof Error ? err.message : String(err);
|
|
4012
|
-
console.error(`${RED}\u274C ${message}${
|
|
4236
|
+
console.error(`${RED}\u274C ${message}${RESET2}`);
|
|
4013
4237
|
process.exit(1);
|
|
4014
4238
|
}
|
|
4015
4239
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -615,6 +615,39 @@ var AomiClient = class {
|
|
|
615
615
|
}
|
|
616
616
|
return postState(this.baseUrl, "/api/control/model", payload, sessionId, apiKey);
|
|
617
617
|
}
|
|
618
|
+
// ===========================================================================
|
|
619
|
+
// Batch Simulation
|
|
620
|
+
// ===========================================================================
|
|
621
|
+
/**
|
|
622
|
+
* Simulate transactions as an atomic batch.
|
|
623
|
+
* Each tx sees state changes from previous txs (e.g., approve → swap).
|
|
624
|
+
* Sends full tx payloads — the backend does not look up by ID.
|
|
625
|
+
*/
|
|
626
|
+
async simulateBatch(sessionId, transactions, options) {
|
|
627
|
+
const url = joinApiPath(this.baseUrl, "/api/simulate");
|
|
628
|
+
const headers = new Headers(
|
|
629
|
+
withSessionHeader(sessionId, { "Content-Type": "application/json" })
|
|
630
|
+
);
|
|
631
|
+
if (this.apiKey) {
|
|
632
|
+
headers.set(API_KEY_HEADER, this.apiKey);
|
|
633
|
+
}
|
|
634
|
+
const payload = {
|
|
635
|
+
transactions,
|
|
636
|
+
from: options == null ? void 0 : options.from,
|
|
637
|
+
chain_id: options == null ? void 0 : options.chainId
|
|
638
|
+
};
|
|
639
|
+
const response = await fetch(url, {
|
|
640
|
+
method: "POST",
|
|
641
|
+
headers,
|
|
642
|
+
body: JSON.stringify(payload)
|
|
643
|
+
});
|
|
644
|
+
if (!response.ok) {
|
|
645
|
+
const body = await response.text().catch(() => "");
|
|
646
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}${body ? `
|
|
647
|
+
${body}` : ""}`);
|
|
648
|
+
}
|
|
649
|
+
return await response.json();
|
|
650
|
+
}
|
|
618
651
|
};
|
|
619
652
|
|
|
620
653
|
// src/types.ts
|
|
@@ -1956,6 +1989,25 @@ async function createAlchemyAAState(options) {
|
|
|
1956
1989
|
if (ownerParams.kind === "unsupported_adapter") {
|
|
1957
1990
|
return getUnsupportedAdapterState(plan, ownerParams.adapter);
|
|
1958
1991
|
}
|
|
1992
|
+
if (owner.kind === "direct") {
|
|
1993
|
+
try {
|
|
1994
|
+
return await createAlchemyWalletApisState({
|
|
1995
|
+
plan,
|
|
1996
|
+
chain,
|
|
1997
|
+
privateKey: owner.privateKey,
|
|
1998
|
+
apiKey,
|
|
1999
|
+
gasPolicyId,
|
|
2000
|
+
mode: plan.mode
|
|
2001
|
+
});
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
return {
|
|
2004
|
+
plan,
|
|
2005
|
+
AA: null,
|
|
2006
|
+
isPending: false,
|
|
2007
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
1959
2011
|
try {
|
|
1960
2012
|
const smartAccount = await (0, import_aa_alchemy.createAlchemySmartAccount)(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
1961
2013
|
apiKey,
|
|
@@ -1987,6 +2039,46 @@ async function createAlchemyAAState(options) {
|
|
|
1987
2039
|
};
|
|
1988
2040
|
}
|
|
1989
2041
|
}
|
|
2042
|
+
async function createAlchemyWalletApisState(params) {
|
|
2043
|
+
const { createSmartWalletClient, alchemyWalletTransport } = await import("@alchemy/wallet-apis");
|
|
2044
|
+
const signer = (0, import_accounts.privateKeyToAccount)(params.privateKey);
|
|
2045
|
+
const walletClient = createSmartWalletClient(__spreadValues({
|
|
2046
|
+
transport: alchemyWalletTransport({ apiKey: params.apiKey }),
|
|
2047
|
+
chain: params.chain,
|
|
2048
|
+
signer
|
|
2049
|
+
}, params.gasPolicyId ? { paymaster: { policyId: params.gasPolicyId } } : {}));
|
|
2050
|
+
let accountAddress = signer.address;
|
|
2051
|
+
if (params.mode === "4337") {
|
|
2052
|
+
const account = await walletClient.requestAccount();
|
|
2053
|
+
accountAddress = account.address;
|
|
2054
|
+
}
|
|
2055
|
+
const sendCalls = async (calls) => {
|
|
2056
|
+
var _a, _b;
|
|
2057
|
+
const result = await walletClient.sendCalls(__spreadProps(__spreadValues({}, params.mode === "4337" ? { account: accountAddress } : {}), {
|
|
2058
|
+
calls
|
|
2059
|
+
}));
|
|
2060
|
+
const status = await walletClient.waitForCallsStatus({ id: result.id });
|
|
2061
|
+
const transactionHash = (_b = (_a = status.receipts) == null ? void 0 : _a[0]) == null ? void 0 : _b.transactionHash;
|
|
2062
|
+
if (!transactionHash) {
|
|
2063
|
+
throw new Error("Alchemy Wallets API did not return a transaction hash.");
|
|
2064
|
+
}
|
|
2065
|
+
return { transactionHash };
|
|
2066
|
+
};
|
|
2067
|
+
const AA = {
|
|
2068
|
+
provider: "alchemy",
|
|
2069
|
+
mode: params.mode,
|
|
2070
|
+
AAAddress: accountAddress,
|
|
2071
|
+
delegationAddress: params.mode === "7702" ? signer.address : void 0,
|
|
2072
|
+
sendTransaction: async (call) => sendCalls([call]),
|
|
2073
|
+
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
2074
|
+
};
|
|
2075
|
+
return {
|
|
2076
|
+
plan: params.plan,
|
|
2077
|
+
AA,
|
|
2078
|
+
isPending: false,
|
|
2079
|
+
error: null
|
|
2080
|
+
};
|
|
2081
|
+
}
|
|
1990
2082
|
async function createPimlicoAAState(options) {
|
|
1991
2083
|
var _a;
|
|
1992
2084
|
const {
|