@aomi-labs/client 0.1.18 → 0.1.20
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 +203 -23
- package/dist/index.cjs +111 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -3
- package/dist/index.d.ts +20 -3
- package/dist/index.js +111 -6
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
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
|
|
|
@@ -499,6 +500,12 @@ function getNextTxId(state) {
|
|
|
499
500
|
}
|
|
500
501
|
function addPendingTx(state, tx) {
|
|
501
502
|
if (!state.pendingTxs) state.pendingTxs = [];
|
|
503
|
+
const isDuplicate = state.pendingTxs.some(
|
|
504
|
+
(existing) => existing.kind === tx.kind && existing.to === tx.to && existing.data === tx.data && existing.value === tx.value && existing.chainId === tx.chainId
|
|
505
|
+
);
|
|
506
|
+
if (isDuplicate) {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
502
509
|
const pending = __spreadProps(__spreadValues({}, tx), {
|
|
503
510
|
id: getNextTxId(state)
|
|
504
511
|
});
|
|
@@ -1161,10 +1168,11 @@ var AomiClient = class {
|
|
|
1161
1168
|
// Batch Simulation
|
|
1162
1169
|
// ===========================================================================
|
|
1163
1170
|
/**
|
|
1164
|
-
* Simulate
|
|
1171
|
+
* Simulate transactions as an atomic batch.
|
|
1165
1172
|
* Each tx sees state changes from previous txs (e.g., approve → swap).
|
|
1173
|
+
* Sends full tx payloads — the backend does not look up by ID.
|
|
1166
1174
|
*/
|
|
1167
|
-
async simulateBatch(sessionId,
|
|
1175
|
+
async simulateBatch(sessionId, transactions, options) {
|
|
1168
1176
|
const url = joinApiPath(this.baseUrl, "/api/simulate");
|
|
1169
1177
|
const headers = new Headers(
|
|
1170
1178
|
withSessionHeader(sessionId, { "Content-Type": "application/json" })
|
|
@@ -1172,13 +1180,20 @@ var AomiClient = class {
|
|
|
1172
1180
|
if (this.apiKey) {
|
|
1173
1181
|
headers.set(API_KEY_HEADER, this.apiKey);
|
|
1174
1182
|
}
|
|
1183
|
+
const payload = {
|
|
1184
|
+
transactions,
|
|
1185
|
+
from: options == null ? void 0 : options.from,
|
|
1186
|
+
chain_id: options == null ? void 0 : options.chainId
|
|
1187
|
+
};
|
|
1175
1188
|
const response = await fetch(url, {
|
|
1176
1189
|
method: "POST",
|
|
1177
1190
|
headers,
|
|
1178
|
-
body: JSON.stringify(
|
|
1191
|
+
body: JSON.stringify(payload)
|
|
1179
1192
|
});
|
|
1180
1193
|
if (!response.ok) {
|
|
1181
|
-
|
|
1194
|
+
const body = await response.text().catch(() => "");
|
|
1195
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}${body ? `
|
|
1196
|
+
${body}` : ""}`);
|
|
1182
1197
|
}
|
|
1183
1198
|
return await response.json();
|
|
1184
1199
|
}
|
|
@@ -1443,6 +1458,7 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1443
1458
|
this.pollTimer = null;
|
|
1444
1459
|
this.unsubscribeSSE = null;
|
|
1445
1460
|
this._isProcessing = false;
|
|
1461
|
+
this._backendWasProcessing = false;
|
|
1446
1462
|
this.walletRequests = [];
|
|
1447
1463
|
this.walletRequestNextId = 1;
|
|
1448
1464
|
this._messages = [];
|
|
@@ -1673,6 +1689,7 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1673
1689
|
startPolling() {
|
|
1674
1690
|
var _a3;
|
|
1675
1691
|
if (this.pollTimer || this.closed) return;
|
|
1692
|
+
this._backendWasProcessing = true;
|
|
1676
1693
|
(_a3 = this.logger) == null ? void 0 : _a3.debug("[session] polling started", this.sessionId);
|
|
1677
1694
|
this.pollTimer = setInterval(() => {
|
|
1678
1695
|
void this.pollTick();
|
|
@@ -1698,6 +1715,10 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1698
1715
|
if (!this.pollTimer) return;
|
|
1699
1716
|
this.assertUserStateAligned(state.user_state);
|
|
1700
1717
|
this.applyState(state);
|
|
1718
|
+
if (this._backendWasProcessing && !state.is_processing) {
|
|
1719
|
+
this.emit("backend_idle", void 0);
|
|
1720
|
+
}
|
|
1721
|
+
this._backendWasProcessing = !!state.is_processing;
|
|
1701
1722
|
if (!state.is_processing && this.walletRequests.length === 0) {
|
|
1702
1723
|
this.stopPolling();
|
|
1703
1724
|
this._isProcessing = false;
|
|
@@ -2093,11 +2114,7 @@ async function chatCommand(runtime) {
|
|
|
2093
2114
|
}
|
|
2094
2115
|
if (session.getIsProcessing()) {
|
|
2095
2116
|
await new Promise((resolve) => {
|
|
2096
|
-
|
|
2097
|
-
if (capturedRequests.length > 0) resolve();
|
|
2098
|
-
};
|
|
2099
|
-
session.on("wallet_tx_request", checkWallet);
|
|
2100
|
-
session.on("wallet_eip712_request", checkWallet);
|
|
2117
|
+
session.on("backend_idle", () => resolve());
|
|
2101
2118
|
session.on("processing_end", () => resolve());
|
|
2102
2119
|
});
|
|
2103
2120
|
}
|
|
@@ -2133,6 +2150,10 @@ async function chatCommand(runtime) {
|
|
|
2133
2150
|
}
|
|
2134
2151
|
for (const request of capturedRequests) {
|
|
2135
2152
|
const pending = addPendingTx(state, walletRequestToPendingTx(request));
|
|
2153
|
+
if (!pending) {
|
|
2154
|
+
console.log("\u26A0\uFE0F Duplicate wallet request skipped");
|
|
2155
|
+
continue;
|
|
2156
|
+
}
|
|
2136
2157
|
console.log(`\u26A1 Wallet request queued: ${pending.id}`);
|
|
2137
2158
|
if (request.kind === "transaction") {
|
|
2138
2159
|
const payload = request.payload;
|
|
@@ -2305,6 +2326,10 @@ async function executeViaAA(callList, providerState) {
|
|
|
2305
2326
|
const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
|
|
2306
2327
|
const txHash = receipt.transactionHash;
|
|
2307
2328
|
const providerPrefix = AA.provider.toLowerCase();
|
|
2329
|
+
let delegationAddress = AA.mode === "7702" ? AA.delegationAddress : void 0;
|
|
2330
|
+
if (AA.mode === "7702" && !delegationAddress) {
|
|
2331
|
+
delegationAddress = await resolve7702Delegation(txHash, callList);
|
|
2332
|
+
}
|
|
2308
2333
|
return {
|
|
2309
2334
|
txHash,
|
|
2310
2335
|
txHashes: [txHash],
|
|
@@ -2312,9 +2337,36 @@ async function executeViaAA(callList, providerState) {
|
|
|
2312
2337
|
batched: callList.length > 1,
|
|
2313
2338
|
sponsored: plan.sponsorship !== "disabled",
|
|
2314
2339
|
AAAddress: AA.AAAddress,
|
|
2315
|
-
delegationAddress
|
|
2340
|
+
delegationAddress
|
|
2316
2341
|
};
|
|
2317
2342
|
}
|
|
2343
|
+
async function resolve7702Delegation(txHash, callList) {
|
|
2344
|
+
var _a3, _b, _c, _d;
|
|
2345
|
+
try {
|
|
2346
|
+
const { createPublicClient, http: http2 } = await import("viem");
|
|
2347
|
+
const chainId = (_a3 = callList[0]) == null ? void 0 : _a3.chainId;
|
|
2348
|
+
if (!chainId) return void 0;
|
|
2349
|
+
const { mainnet, polygon, arbitrum, optimism, base } = await import("viem/chains");
|
|
2350
|
+
const knownChains = {
|
|
2351
|
+
1: mainnet,
|
|
2352
|
+
137: polygon,
|
|
2353
|
+
42161: arbitrum,
|
|
2354
|
+
10: optimism,
|
|
2355
|
+
8453: base
|
|
2356
|
+
};
|
|
2357
|
+
const chain = knownChains[chainId];
|
|
2358
|
+
if (!chain) return void 0;
|
|
2359
|
+
const client = createPublicClient({ chain, transport: http2() });
|
|
2360
|
+
const tx = await client.getTransaction({ hash: txHash });
|
|
2361
|
+
const authList = tx.authorizationList;
|
|
2362
|
+
const target = (_d = (_b = authList == null ? void 0 : authList[0]) == null ? void 0 : _b.address) != null ? _d : (_c = authList == null ? void 0 : authList[0]) == null ? void 0 : _c.contractAddress;
|
|
2363
|
+
if (target) {
|
|
2364
|
+
return target;
|
|
2365
|
+
}
|
|
2366
|
+
} catch (e) {
|
|
2367
|
+
}
|
|
2368
|
+
return void 0;
|
|
2369
|
+
}
|
|
2318
2370
|
async function executeViaEoa({
|
|
2319
2371
|
callList,
|
|
2320
2372
|
currentChainId,
|
|
@@ -2978,7 +3030,7 @@ Run \`aomi tx\` to see available IDs.`
|
|
|
2978
3030
|
return pendingTx;
|
|
2979
3031
|
}
|
|
2980
3032
|
async function simulateCommand(runtime) {
|
|
2981
|
-
var _a3;
|
|
3033
|
+
var _a3, _b, _c;
|
|
2982
3034
|
const state = readState();
|
|
2983
3035
|
if (!state) {
|
|
2984
3036
|
fatal("No active session. Run `aomi chat` first.");
|
|
@@ -2987,9 +3039,7 @@ async function simulateCommand(runtime) {
|
|
|
2987
3039
|
if (txIds.length === 0) {
|
|
2988
3040
|
fatal("Usage: aomi simulate <tx-id> [<tx-id> ...]\nRun `aomi tx` to see available IDs.");
|
|
2989
3041
|
}
|
|
2990
|
-
|
|
2991
|
-
requirePendingTx(state, txId);
|
|
2992
|
-
}
|
|
3042
|
+
const pendingTxs = txIds.map((txId) => requirePendingTx(state, txId));
|
|
2993
3043
|
console.log(
|
|
2994
3044
|
`${DIM}Simulating ${txIds.length} transaction(s) as atomic batch...${RESET}`
|
|
2995
3045
|
);
|
|
@@ -2997,7 +3047,23 @@ async function simulateCommand(runtime) {
|
|
|
2997
3047
|
baseUrl: state.baseUrl,
|
|
2998
3048
|
apiKey: state.apiKey
|
|
2999
3049
|
});
|
|
3000
|
-
const
|
|
3050
|
+
const transactions = pendingTxs.map((tx) => {
|
|
3051
|
+
var _a4;
|
|
3052
|
+
return {
|
|
3053
|
+
to: tx.to,
|
|
3054
|
+
value: tx.value,
|
|
3055
|
+
data: tx.data,
|
|
3056
|
+
label: (_a4 = tx.description) != null ? _a4 : tx.id
|
|
3057
|
+
};
|
|
3058
|
+
});
|
|
3059
|
+
const response = await client.simulateBatch(
|
|
3060
|
+
state.sessionId,
|
|
3061
|
+
transactions,
|
|
3062
|
+
{
|
|
3063
|
+
from: (_a3 = state.publicKey) != null ? _a3 : void 0,
|
|
3064
|
+
chainId: (_b = state.chainId) != null ? _b : void 0
|
|
3065
|
+
}
|
|
3066
|
+
);
|
|
3001
3067
|
const { result } = response;
|
|
3002
3068
|
const modeLabel = result.stateful ? "stateful (Anvil snapshot)" : "stateless (independent eth_call)";
|
|
3003
3069
|
console.log(`
|
|
@@ -3032,7 +3098,7 @@ ${DIM}Total gas: ${result.total_gas.toLocaleString()}${RESET}`);
|
|
|
3032
3098
|
} else {
|
|
3033
3099
|
const failed = result.steps.find((s) => !s.success);
|
|
3034
3100
|
console.log(
|
|
3035
|
-
`\x1B[31mBatch failed at step ${(
|
|
3101
|
+
`\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.`
|
|
3036
3102
|
);
|
|
3037
3103
|
}
|
|
3038
3104
|
}
|
|
@@ -3229,11 +3295,12 @@ function resolvePimlicoConfig(options) {
|
|
|
3229
3295
|
|
|
3230
3296
|
// src/aa/adapt.ts
|
|
3231
3297
|
function adaptSmartAccount(account) {
|
|
3298
|
+
const delegationAddress = account.mode === "7702" && account.delegationAddress && account.smartAccountAddress && account.delegationAddress.toLowerCase() === account.smartAccountAddress.toLowerCase() ? void 0 : account.delegationAddress;
|
|
3232
3299
|
return {
|
|
3233
3300
|
provider: account.provider,
|
|
3234
3301
|
mode: account.mode,
|
|
3235
3302
|
AAAddress: account.smartAccountAddress,
|
|
3236
|
-
delegationAddress
|
|
3303
|
+
delegationAddress,
|
|
3237
3304
|
sendTransaction: async (call) => {
|
|
3238
3305
|
const receipt = await account.sendTransaction(call);
|
|
3239
3306
|
return { transactionHash: receipt.transactionHash };
|
|
@@ -3374,6 +3441,25 @@ async function createAlchemyAAState(options) {
|
|
|
3374
3441
|
if (ownerParams.kind === "unsupported_adapter") {
|
|
3375
3442
|
return getUnsupportedAdapterState(plan, ownerParams.adapter);
|
|
3376
3443
|
}
|
|
3444
|
+
if (owner.kind === "direct") {
|
|
3445
|
+
try {
|
|
3446
|
+
return await createAlchemyWalletApisState({
|
|
3447
|
+
plan,
|
|
3448
|
+
chain,
|
|
3449
|
+
privateKey: owner.privateKey,
|
|
3450
|
+
apiKey,
|
|
3451
|
+
gasPolicyId,
|
|
3452
|
+
mode: plan.mode
|
|
3453
|
+
});
|
|
3454
|
+
} catch (error) {
|
|
3455
|
+
return {
|
|
3456
|
+
plan,
|
|
3457
|
+
AA: null,
|
|
3458
|
+
isPending: false,
|
|
3459
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3460
|
+
};
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3377
3463
|
try {
|
|
3378
3464
|
const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
3379
3465
|
apiKey,
|
|
@@ -3405,6 +3491,46 @@ async function createAlchemyAAState(options) {
|
|
|
3405
3491
|
};
|
|
3406
3492
|
}
|
|
3407
3493
|
}
|
|
3494
|
+
async function createAlchemyWalletApisState(params) {
|
|
3495
|
+
const { createSmartWalletClient, alchemyWalletTransport } = await import("@alchemy/wallet-apis");
|
|
3496
|
+
const signer = privateKeyToAccount(params.privateKey);
|
|
3497
|
+
const walletClient = createSmartWalletClient(__spreadValues({
|
|
3498
|
+
transport: alchemyWalletTransport({ apiKey: params.apiKey }),
|
|
3499
|
+
chain: params.chain,
|
|
3500
|
+
signer
|
|
3501
|
+
}, params.gasPolicyId ? { paymaster: { policyId: params.gasPolicyId } } : {}));
|
|
3502
|
+
let accountAddress = signer.address;
|
|
3503
|
+
if (params.mode === "4337") {
|
|
3504
|
+
const account = await walletClient.requestAccount();
|
|
3505
|
+
accountAddress = account.address;
|
|
3506
|
+
}
|
|
3507
|
+
const sendCalls = async (calls) => {
|
|
3508
|
+
var _a3, _b;
|
|
3509
|
+
const result = await walletClient.sendCalls(__spreadProps(__spreadValues({}, params.mode === "4337" ? { account: accountAddress } : {}), {
|
|
3510
|
+
calls
|
|
3511
|
+
}));
|
|
3512
|
+
const status = await walletClient.waitForCallsStatus({ id: result.id });
|
|
3513
|
+
const transactionHash = (_b = (_a3 = status.receipts) == null ? void 0 : _a3[0]) == null ? void 0 : _b.transactionHash;
|
|
3514
|
+
if (!transactionHash) {
|
|
3515
|
+
throw new Error("Alchemy Wallets API did not return a transaction hash.");
|
|
3516
|
+
}
|
|
3517
|
+
return { transactionHash };
|
|
3518
|
+
};
|
|
3519
|
+
const AA = {
|
|
3520
|
+
provider: "alchemy",
|
|
3521
|
+
mode: params.mode,
|
|
3522
|
+
AAAddress: accountAddress,
|
|
3523
|
+
delegationAddress: params.mode === "7702" ? signer.address : void 0,
|
|
3524
|
+
sendTransaction: async (call) => sendCalls([call]),
|
|
3525
|
+
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
3526
|
+
};
|
|
3527
|
+
return {
|
|
3528
|
+
plan: params.plan,
|
|
3529
|
+
AA,
|
|
3530
|
+
isPending: false,
|
|
3531
|
+
error: null
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
3408
3534
|
async function createPimlicoAAState(options) {
|
|
3409
3535
|
var _a3;
|
|
3410
3536
|
const {
|
|
@@ -3468,6 +3594,42 @@ async function createPimlicoAAState(options) {
|
|
|
3468
3594
|
}
|
|
3469
3595
|
|
|
3470
3596
|
// src/cli/execution.ts
|
|
3597
|
+
var ERC20_SELECTORS = /* @__PURE__ */ new Set([
|
|
3598
|
+
"0x095ea7b3",
|
|
3599
|
+
// approve(address,uint256)
|
|
3600
|
+
"0xa9059cbb",
|
|
3601
|
+
// transfer(address,uint256)
|
|
3602
|
+
"0x23b872dd"
|
|
3603
|
+
// transferFrom(address,address,uint256)
|
|
3604
|
+
]);
|
|
3605
|
+
function callsContainTokenOperations(calls) {
|
|
3606
|
+
return calls.some(
|
|
3607
|
+
(call) => call.data && ERC20_SELECTORS.has(call.data.slice(0, 10).toLowerCase())
|
|
3608
|
+
);
|
|
3609
|
+
}
|
|
3610
|
+
function maybeOverride4337ForTokenOps(params) {
|
|
3611
|
+
const { mode, callList, chain, explicitMode } = params;
|
|
3612
|
+
if (mode !== "4337" || !callsContainTokenOperations(callList)) {
|
|
3613
|
+
return { mode, warned: false };
|
|
3614
|
+
}
|
|
3615
|
+
const chainConfig = getAAChainConfig(DEFAULT_AA_CONFIG, callList, {
|
|
3616
|
+
[chain.id]: chain
|
|
3617
|
+
});
|
|
3618
|
+
if ((chainConfig == null ? void 0 : chainConfig.supportedModes.includes("7702")) && !explicitMode) {
|
|
3619
|
+
console.log(
|
|
3620
|
+
"\u26A0\uFE0F 4337 batch contains ERC-20 calls but tokens are in your EOA, not the 4337 smart account."
|
|
3621
|
+
);
|
|
3622
|
+
console.log(" Switching to 7702 (EOA keeps smart-account capabilities, no token transfer needed).");
|
|
3623
|
+
return { mode: "7702", warned: true };
|
|
3624
|
+
}
|
|
3625
|
+
console.log(
|
|
3626
|
+
"\u26A0\uFE0F 4337 batch contains ERC-20 calls. Tokens must be in the smart account, not your EOA."
|
|
3627
|
+
);
|
|
3628
|
+
console.log(
|
|
3629
|
+
" This batch may revert. Consider transferring tokens to the smart account first."
|
|
3630
|
+
);
|
|
3631
|
+
return { mode, warned: true };
|
|
3632
|
+
}
|
|
3471
3633
|
function resolveAAProvider(config, options) {
|
|
3472
3634
|
const provider = config.aaProvider;
|
|
3473
3635
|
if (provider) {
|
|
@@ -3503,10 +3665,16 @@ function getResolvedAAMode(params) {
|
|
|
3503
3665
|
if (!resolved) {
|
|
3504
3666
|
throw new Error(`AA config resolution failed for provider "${provider}".`);
|
|
3505
3667
|
}
|
|
3668
|
+
const { mode: finalMode } = maybeOverride4337ForTokenOps({
|
|
3669
|
+
mode: resolved.plan.mode,
|
|
3670
|
+
callList,
|
|
3671
|
+
chain,
|
|
3672
|
+
explicitMode: Boolean(config.aaMode)
|
|
3673
|
+
});
|
|
3506
3674
|
return {
|
|
3507
3675
|
execution: "aa",
|
|
3508
3676
|
provider,
|
|
3509
|
-
aaMode:
|
|
3677
|
+
aaMode: finalMode,
|
|
3510
3678
|
fallbackToEoa
|
|
3511
3679
|
};
|
|
3512
3680
|
}
|
|
@@ -3839,7 +4007,19 @@ async function signCommand(runtime) {
|
|
|
3839
4007
|
try {
|
|
3840
4008
|
const simResponse = await session.client.simulateBatch(
|
|
3841
4009
|
state.sessionId,
|
|
3842
|
-
pendingTxs.map((tx) =>
|
|
4010
|
+
pendingTxs.map((tx) => {
|
|
4011
|
+
var _a4;
|
|
4012
|
+
return {
|
|
4013
|
+
to: tx.to,
|
|
4014
|
+
value: tx.value,
|
|
4015
|
+
data: tx.data,
|
|
4016
|
+
label: (_a4 = tx.description) != null ? _a4 : tx.id
|
|
4017
|
+
};
|
|
4018
|
+
}),
|
|
4019
|
+
{
|
|
4020
|
+
from: account.address,
|
|
4021
|
+
chainId: primaryChainId
|
|
4022
|
+
}
|
|
3843
4023
|
);
|
|
3844
4024
|
const { result: sim } = simResponse;
|
|
3845
4025
|
if (!sim.batch_success) {
|
package/dist/index.cjs
CHANGED
|
@@ -619,10 +619,11 @@ var AomiClient = class {
|
|
|
619
619
|
// Batch Simulation
|
|
620
620
|
// ===========================================================================
|
|
621
621
|
/**
|
|
622
|
-
* Simulate
|
|
622
|
+
* Simulate transactions as an atomic batch.
|
|
623
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.
|
|
624
625
|
*/
|
|
625
|
-
async simulateBatch(sessionId,
|
|
626
|
+
async simulateBatch(sessionId, transactions, options) {
|
|
626
627
|
const url = joinApiPath(this.baseUrl, "/api/simulate");
|
|
627
628
|
const headers = new Headers(
|
|
628
629
|
withSessionHeader(sessionId, { "Content-Type": "application/json" })
|
|
@@ -630,13 +631,20 @@ var AomiClient = class {
|
|
|
630
631
|
if (this.apiKey) {
|
|
631
632
|
headers.set(API_KEY_HEADER, this.apiKey);
|
|
632
633
|
}
|
|
634
|
+
const payload = {
|
|
635
|
+
transactions,
|
|
636
|
+
from: options == null ? void 0 : options.from,
|
|
637
|
+
chain_id: options == null ? void 0 : options.chainId
|
|
638
|
+
};
|
|
633
639
|
const response = await fetch(url, {
|
|
634
640
|
method: "POST",
|
|
635
641
|
headers,
|
|
636
|
-
body: JSON.stringify(
|
|
642
|
+
body: JSON.stringify(payload)
|
|
637
643
|
});
|
|
638
644
|
if (!response.ok) {
|
|
639
|
-
|
|
645
|
+
const body = await response.text().catch(() => "");
|
|
646
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}${body ? `
|
|
647
|
+
${body}` : ""}`);
|
|
640
648
|
}
|
|
641
649
|
return await response.json();
|
|
642
650
|
}
|
|
@@ -902,6 +910,7 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
902
910
|
this.pollTimer = null;
|
|
903
911
|
this.unsubscribeSSE = null;
|
|
904
912
|
this._isProcessing = false;
|
|
913
|
+
this._backendWasProcessing = false;
|
|
905
914
|
this.walletRequests = [];
|
|
906
915
|
this.walletRequestNextId = 1;
|
|
907
916
|
this._messages = [];
|
|
@@ -1132,6 +1141,7 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1132
1141
|
startPolling() {
|
|
1133
1142
|
var _a;
|
|
1134
1143
|
if (this.pollTimer || this.closed) return;
|
|
1144
|
+
this._backendWasProcessing = true;
|
|
1135
1145
|
(_a = this.logger) == null ? void 0 : _a.debug("[session] polling started", this.sessionId);
|
|
1136
1146
|
this.pollTimer = setInterval(() => {
|
|
1137
1147
|
void this.pollTick();
|
|
@@ -1157,6 +1167,10 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1157
1167
|
if (!this.pollTimer) return;
|
|
1158
1168
|
this.assertUserStateAligned(state.user_state);
|
|
1159
1169
|
this.applyState(state);
|
|
1170
|
+
if (this._backendWasProcessing && !state.is_processing) {
|
|
1171
|
+
this.emit("backend_idle", void 0);
|
|
1172
|
+
}
|
|
1173
|
+
this._backendWasProcessing = !!state.is_processing;
|
|
1160
1174
|
if (!state.is_processing && this.walletRequests.length === 0) {
|
|
1161
1175
|
this.stopPolling();
|
|
1162
1176
|
this._isProcessing = false;
|
|
@@ -1468,6 +1482,10 @@ async function executeViaAA(callList, providerState) {
|
|
|
1468
1482
|
const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
|
|
1469
1483
|
const txHash = receipt.transactionHash;
|
|
1470
1484
|
const providerPrefix = AA.provider.toLowerCase();
|
|
1485
|
+
let delegationAddress = AA.mode === "7702" ? AA.delegationAddress : void 0;
|
|
1486
|
+
if (AA.mode === "7702" && !delegationAddress) {
|
|
1487
|
+
delegationAddress = await resolve7702Delegation(txHash, callList);
|
|
1488
|
+
}
|
|
1471
1489
|
return {
|
|
1472
1490
|
txHash,
|
|
1473
1491
|
txHashes: [txHash],
|
|
@@ -1475,9 +1493,36 @@ async function executeViaAA(callList, providerState) {
|
|
|
1475
1493
|
batched: callList.length > 1,
|
|
1476
1494
|
sponsored: plan.sponsorship !== "disabled",
|
|
1477
1495
|
AAAddress: AA.AAAddress,
|
|
1478
|
-
delegationAddress
|
|
1496
|
+
delegationAddress
|
|
1479
1497
|
};
|
|
1480
1498
|
}
|
|
1499
|
+
async function resolve7702Delegation(txHash, callList) {
|
|
1500
|
+
var _a, _b, _c, _d;
|
|
1501
|
+
try {
|
|
1502
|
+
const { createPublicClient, http } = await import("viem");
|
|
1503
|
+
const chainId = (_a = callList[0]) == null ? void 0 : _a.chainId;
|
|
1504
|
+
if (!chainId) return void 0;
|
|
1505
|
+
const { mainnet, polygon, arbitrum, optimism, base } = await import("viem/chains");
|
|
1506
|
+
const knownChains = {
|
|
1507
|
+
1: mainnet,
|
|
1508
|
+
137: polygon,
|
|
1509
|
+
42161: arbitrum,
|
|
1510
|
+
10: optimism,
|
|
1511
|
+
8453: base
|
|
1512
|
+
};
|
|
1513
|
+
const chain = knownChains[chainId];
|
|
1514
|
+
if (!chain) return void 0;
|
|
1515
|
+
const client = createPublicClient({ chain, transport: http() });
|
|
1516
|
+
const tx = await client.getTransaction({ hash: txHash });
|
|
1517
|
+
const authList = tx.authorizationList;
|
|
1518
|
+
const target = (_d = (_b = authList == null ? void 0 : authList[0]) == null ? void 0 : _b.address) != null ? _d : (_c = authList == null ? void 0 : authList[0]) == null ? void 0 : _c.contractAddress;
|
|
1519
|
+
if (target) {
|
|
1520
|
+
return target;
|
|
1521
|
+
}
|
|
1522
|
+
} catch (e) {
|
|
1523
|
+
}
|
|
1524
|
+
return void 0;
|
|
1525
|
+
}
|
|
1481
1526
|
async function executeViaEoa({
|
|
1482
1527
|
callList,
|
|
1483
1528
|
currentChainId,
|
|
@@ -1836,11 +1881,12 @@ function createPimlicoAAProvider({
|
|
|
1836
1881
|
|
|
1837
1882
|
// src/aa/adapt.ts
|
|
1838
1883
|
function adaptSmartAccount(account) {
|
|
1884
|
+
const delegationAddress = account.mode === "7702" && account.delegationAddress && account.smartAccountAddress && account.delegationAddress.toLowerCase() === account.smartAccountAddress.toLowerCase() ? void 0 : account.delegationAddress;
|
|
1839
1885
|
return {
|
|
1840
1886
|
provider: account.provider,
|
|
1841
1887
|
mode: account.mode,
|
|
1842
1888
|
AAAddress: account.smartAccountAddress,
|
|
1843
|
-
delegationAddress
|
|
1889
|
+
delegationAddress,
|
|
1844
1890
|
sendTransaction: async (call) => {
|
|
1845
1891
|
const receipt = await account.sendTransaction(call);
|
|
1846
1892
|
return { transactionHash: receipt.transactionHash };
|
|
@@ -1981,6 +2027,25 @@ async function createAlchemyAAState(options) {
|
|
|
1981
2027
|
if (ownerParams.kind === "unsupported_adapter") {
|
|
1982
2028
|
return getUnsupportedAdapterState(plan, ownerParams.adapter);
|
|
1983
2029
|
}
|
|
2030
|
+
if (owner.kind === "direct") {
|
|
2031
|
+
try {
|
|
2032
|
+
return await createAlchemyWalletApisState({
|
|
2033
|
+
plan,
|
|
2034
|
+
chain,
|
|
2035
|
+
privateKey: owner.privateKey,
|
|
2036
|
+
apiKey,
|
|
2037
|
+
gasPolicyId,
|
|
2038
|
+
mode: plan.mode
|
|
2039
|
+
});
|
|
2040
|
+
} catch (error) {
|
|
2041
|
+
return {
|
|
2042
|
+
plan,
|
|
2043
|
+
AA: null,
|
|
2044
|
+
isPending: false,
|
|
2045
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2046
|
+
};
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
1984
2049
|
try {
|
|
1985
2050
|
const smartAccount = await (0, import_aa_alchemy.createAlchemySmartAccount)(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
1986
2051
|
apiKey,
|
|
@@ -2012,6 +2077,46 @@ async function createAlchemyAAState(options) {
|
|
|
2012
2077
|
};
|
|
2013
2078
|
}
|
|
2014
2079
|
}
|
|
2080
|
+
async function createAlchemyWalletApisState(params) {
|
|
2081
|
+
const { createSmartWalletClient, alchemyWalletTransport } = await import("@alchemy/wallet-apis");
|
|
2082
|
+
const signer = (0, import_accounts.privateKeyToAccount)(params.privateKey);
|
|
2083
|
+
const walletClient = createSmartWalletClient(__spreadValues({
|
|
2084
|
+
transport: alchemyWalletTransport({ apiKey: params.apiKey }),
|
|
2085
|
+
chain: params.chain,
|
|
2086
|
+
signer
|
|
2087
|
+
}, params.gasPolicyId ? { paymaster: { policyId: params.gasPolicyId } } : {}));
|
|
2088
|
+
let accountAddress = signer.address;
|
|
2089
|
+
if (params.mode === "4337") {
|
|
2090
|
+
const account = await walletClient.requestAccount();
|
|
2091
|
+
accountAddress = account.address;
|
|
2092
|
+
}
|
|
2093
|
+
const sendCalls = async (calls) => {
|
|
2094
|
+
var _a, _b;
|
|
2095
|
+
const result = await walletClient.sendCalls(__spreadProps(__spreadValues({}, params.mode === "4337" ? { account: accountAddress } : {}), {
|
|
2096
|
+
calls
|
|
2097
|
+
}));
|
|
2098
|
+
const status = await walletClient.waitForCallsStatus({ id: result.id });
|
|
2099
|
+
const transactionHash = (_b = (_a = status.receipts) == null ? void 0 : _a[0]) == null ? void 0 : _b.transactionHash;
|
|
2100
|
+
if (!transactionHash) {
|
|
2101
|
+
throw new Error("Alchemy Wallets API did not return a transaction hash.");
|
|
2102
|
+
}
|
|
2103
|
+
return { transactionHash };
|
|
2104
|
+
};
|
|
2105
|
+
const AA = {
|
|
2106
|
+
provider: "alchemy",
|
|
2107
|
+
mode: params.mode,
|
|
2108
|
+
AAAddress: accountAddress,
|
|
2109
|
+
delegationAddress: params.mode === "7702" ? signer.address : void 0,
|
|
2110
|
+
sendTransaction: async (call) => sendCalls([call]),
|
|
2111
|
+
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
2112
|
+
};
|
|
2113
|
+
return {
|
|
2114
|
+
plan: params.plan,
|
|
2115
|
+
AA,
|
|
2116
|
+
isPending: false,
|
|
2117
|
+
error: null
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2015
2120
|
async function createPimlicoAAState(options) {
|
|
2016
2121
|
var _a;
|
|
2017
2122
|
const {
|