@aomi-labs/client 0.1.19 → 0.1.21

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 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.19",
25
+ version: "0.1.20",
26
26
  description: "Platform-agnostic TypeScript client for the Aomi backend API",
27
27
  type: "module",
28
28
  main: "./dist/index.cjs",
@@ -500,6 +500,12 @@ function getNextTxId(state) {
500
500
  }
501
501
  function addPendingTx(state, tx) {
502
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
+ }
503
509
  const pending = __spreadProps(__spreadValues({}, tx), {
504
510
  id: getNextTxId(state)
505
511
  });
@@ -1452,6 +1458,7 @@ var ClientSession = class extends TypedEventEmitter {
1452
1458
  this.pollTimer = null;
1453
1459
  this.unsubscribeSSE = null;
1454
1460
  this._isProcessing = false;
1461
+ this._backendWasProcessing = false;
1455
1462
  this.walletRequests = [];
1456
1463
  this.walletRequestNextId = 1;
1457
1464
  this._messages = [];
@@ -1682,6 +1689,7 @@ var ClientSession = class extends TypedEventEmitter {
1682
1689
  startPolling() {
1683
1690
  var _a3;
1684
1691
  if (this.pollTimer || this.closed) return;
1692
+ this._backendWasProcessing = true;
1685
1693
  (_a3 = this.logger) == null ? void 0 : _a3.debug("[session] polling started", this.sessionId);
1686
1694
  this.pollTimer = setInterval(() => {
1687
1695
  void this.pollTick();
@@ -1707,6 +1715,10 @@ var ClientSession = class extends TypedEventEmitter {
1707
1715
  if (!this.pollTimer) return;
1708
1716
  this.assertUserStateAligned(state.user_state);
1709
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;
1710
1722
  if (!state.is_processing && this.walletRequests.length === 0) {
1711
1723
  this.stopPolling();
1712
1724
  this._isProcessing = false;
@@ -2102,11 +2114,7 @@ async function chatCommand(runtime) {
2102
2114
  }
2103
2115
  if (session.getIsProcessing()) {
2104
2116
  await new Promise((resolve) => {
2105
- const checkWallet = () => {
2106
- if (capturedRequests.length > 0) resolve();
2107
- };
2108
- session.on("wallet_tx_request", checkWallet);
2109
- session.on("wallet_eip712_request", checkWallet);
2117
+ session.on("backend_idle", () => resolve());
2110
2118
  session.on("processing_end", () => resolve());
2111
2119
  });
2112
2120
  }
@@ -2142,6 +2150,10 @@ async function chatCommand(runtime) {
2142
2150
  }
2143
2151
  for (const request of capturedRequests) {
2144
2152
  const pending = addPendingTx(state, walletRequestToPendingTx(request));
2153
+ if (!pending) {
2154
+ console.log("\u26A0\uFE0F Duplicate wallet request skipped");
2155
+ continue;
2156
+ }
2145
2157
  console.log(`\u26A1 Wallet request queued: ${pending.id}`);
2146
2158
  if (request.kind === "transaction") {
2147
2159
  const payload = request.payload;
@@ -2314,6 +2326,10 @@ async function executeViaAA(callList, providerState) {
2314
2326
  const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
2315
2327
  const txHash = receipt.transactionHash;
2316
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
+ }
2317
2333
  return {
2318
2334
  txHash,
2319
2335
  txHashes: [txHash],
@@ -2321,9 +2337,36 @@ async function executeViaAA(callList, providerState) {
2321
2337
  batched: callList.length > 1,
2322
2338
  sponsored: plan.sponsorship !== "disabled",
2323
2339
  AAAddress: AA.AAAddress,
2324
- delegationAddress: AA.mode === "7702" ? AA.delegationAddress : void 0
2340
+ delegationAddress
2325
2341
  };
2326
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
+ }
2327
2370
  async function executeViaEoa({
2328
2371
  callList,
2329
2372
  currentChainId,
@@ -3252,11 +3295,12 @@ function resolvePimlicoConfig(options) {
3252
3295
 
3253
3296
  // src/aa/adapt.ts
3254
3297
  function adaptSmartAccount(account) {
3298
+ const delegationAddress = account.mode === "7702" && account.delegationAddress && account.smartAccountAddress && account.delegationAddress.toLowerCase() === account.smartAccountAddress.toLowerCase() ? void 0 : account.delegationAddress;
3255
3299
  return {
3256
3300
  provider: account.provider,
3257
3301
  mode: account.mode,
3258
3302
  AAAddress: account.smartAccountAddress,
3259
- delegationAddress: account.delegationAddress,
3303
+ delegationAddress,
3260
3304
  sendTransaction: async (call) => {
3261
3305
  const receipt = await account.sendTransaction(call);
3262
3306
  return { transactionHash: receipt.transactionHash };
@@ -3277,6 +3321,7 @@ function isAlchemySponsorshipLimitError(error) {
3277
3321
  import { createAlchemySmartAccount } from "@getpara/aa-alchemy";
3278
3322
  import { createPimlicoSmartAccount } from "@getpara/aa-pimlico";
3279
3323
  import { privateKeyToAccount } from "viem/accounts";
3324
+ var ALCHEMY_7702_DELEGATION_ADDRESS = "0x69007702764179f14F51cdce752f4f775d74E139";
3280
3325
  async function createAAProviderState(options) {
3281
3326
  if (options.provider === "alchemy") {
3282
3327
  return createAlchemyAAState({
@@ -3476,7 +3521,7 @@ async function createAlchemyWalletApisState(params) {
3476
3521
  provider: "alchemy",
3477
3522
  mode: params.mode,
3478
3523
  AAAddress: accountAddress,
3479
- delegationAddress: params.mode === "7702" ? signer.address : void 0,
3524
+ delegationAddress: params.mode === "7702" ? ALCHEMY_7702_DELEGATION_ADDRESS : void 0,
3480
3525
  sendTransaction: async (call) => sendCalls([call]),
3481
3526
  sendBatchTransaction: async (calls) => sendCalls(calls)
3482
3527
  };
@@ -3550,6 +3595,42 @@ async function createPimlicoAAState(options) {
3550
3595
  }
3551
3596
 
3552
3597
  // src/cli/execution.ts
3598
+ var ERC20_SELECTORS = /* @__PURE__ */ new Set([
3599
+ "0x095ea7b3",
3600
+ // approve(address,uint256)
3601
+ "0xa9059cbb",
3602
+ // transfer(address,uint256)
3603
+ "0x23b872dd"
3604
+ // transferFrom(address,address,uint256)
3605
+ ]);
3606
+ function callsContainTokenOperations(calls) {
3607
+ return calls.some(
3608
+ (call) => call.data && ERC20_SELECTORS.has(call.data.slice(0, 10).toLowerCase())
3609
+ );
3610
+ }
3611
+ function maybeOverride4337ForTokenOps(params) {
3612
+ const { mode, callList, chain, explicitMode } = params;
3613
+ if (mode !== "4337" || !callsContainTokenOperations(callList)) {
3614
+ return { mode, warned: false };
3615
+ }
3616
+ const chainConfig = getAAChainConfig(DEFAULT_AA_CONFIG, callList, {
3617
+ [chain.id]: chain
3618
+ });
3619
+ if ((chainConfig == null ? void 0 : chainConfig.supportedModes.includes("7702")) && !explicitMode) {
3620
+ console.log(
3621
+ "\u26A0\uFE0F 4337 batch contains ERC-20 calls but tokens are in your EOA, not the 4337 smart account."
3622
+ );
3623
+ console.log(" Switching to 7702 (EOA keeps smart-account capabilities, no token transfer needed).");
3624
+ return { mode: "7702", warned: true };
3625
+ }
3626
+ console.log(
3627
+ "\u26A0\uFE0F 4337 batch contains ERC-20 calls. Tokens must be in the smart account, not your EOA."
3628
+ );
3629
+ console.log(
3630
+ " This batch may revert. Consider transferring tokens to the smart account first."
3631
+ );
3632
+ return { mode, warned: true };
3633
+ }
3553
3634
  function resolveAAProvider(config, options) {
3554
3635
  const provider = config.aaProvider;
3555
3636
  if (provider) {
@@ -3585,10 +3666,16 @@ function getResolvedAAMode(params) {
3585
3666
  if (!resolved) {
3586
3667
  throw new Error(`AA config resolution failed for provider "${provider}".`);
3587
3668
  }
3669
+ const { mode: finalMode } = maybeOverride4337ForTokenOps({
3670
+ mode: resolved.plan.mode,
3671
+ callList,
3672
+ chain,
3673
+ explicitMode: Boolean(config.aaMode)
3674
+ });
3588
3675
  return {
3589
3676
  execution: "aa",
3590
3677
  provider,
3591
- aaMode: resolved.plan.mode,
3678
+ aaMode: finalMode,
3592
3679
  fallbackToEoa
3593
3680
  };
3594
3681
  }
package/dist/index.cjs CHANGED
@@ -910,6 +910,7 @@ var ClientSession = class extends TypedEventEmitter {
910
910
  this.pollTimer = null;
911
911
  this.unsubscribeSSE = null;
912
912
  this._isProcessing = false;
913
+ this._backendWasProcessing = false;
913
914
  this.walletRequests = [];
914
915
  this.walletRequestNextId = 1;
915
916
  this._messages = [];
@@ -1140,6 +1141,7 @@ var ClientSession = class extends TypedEventEmitter {
1140
1141
  startPolling() {
1141
1142
  var _a;
1142
1143
  if (this.pollTimer || this.closed) return;
1144
+ this._backendWasProcessing = true;
1143
1145
  (_a = this.logger) == null ? void 0 : _a.debug("[session] polling started", this.sessionId);
1144
1146
  this.pollTimer = setInterval(() => {
1145
1147
  void this.pollTick();
@@ -1165,6 +1167,10 @@ var ClientSession = class extends TypedEventEmitter {
1165
1167
  if (!this.pollTimer) return;
1166
1168
  this.assertUserStateAligned(state.user_state);
1167
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;
1168
1174
  if (!state.is_processing && this.walletRequests.length === 0) {
1169
1175
  this.stopPolling();
1170
1176
  this._isProcessing = false;
@@ -1476,6 +1482,10 @@ async function executeViaAA(callList, providerState) {
1476
1482
  const receipt = callList.length > 1 ? await AA.sendBatchTransaction(callsPayload) : await AA.sendTransaction(callsPayload[0]);
1477
1483
  const txHash = receipt.transactionHash;
1478
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
+ }
1479
1489
  return {
1480
1490
  txHash,
1481
1491
  txHashes: [txHash],
@@ -1483,9 +1493,36 @@ async function executeViaAA(callList, providerState) {
1483
1493
  batched: callList.length > 1,
1484
1494
  sponsored: plan.sponsorship !== "disabled",
1485
1495
  AAAddress: AA.AAAddress,
1486
- delegationAddress: AA.mode === "7702" ? AA.delegationAddress : void 0
1496
+ delegationAddress
1487
1497
  };
1488
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
+ }
1489
1526
  async function executeViaEoa({
1490
1527
  callList,
1491
1528
  currentChainId,
@@ -1844,11 +1881,12 @@ function createPimlicoAAProvider({
1844
1881
 
1845
1882
  // src/aa/adapt.ts
1846
1883
  function adaptSmartAccount(account) {
1884
+ const delegationAddress = account.mode === "7702" && account.delegationAddress && account.smartAccountAddress && account.delegationAddress.toLowerCase() === account.smartAccountAddress.toLowerCase() ? void 0 : account.delegationAddress;
1847
1885
  return {
1848
1886
  provider: account.provider,
1849
1887
  mode: account.mode,
1850
1888
  AAAddress: account.smartAccountAddress,
1851
- delegationAddress: account.delegationAddress,
1889
+ delegationAddress,
1852
1890
  sendTransaction: async (call) => {
1853
1891
  const receipt = await account.sendTransaction(call);
1854
1892
  return { transactionHash: receipt.transactionHash };
@@ -1869,6 +1907,7 @@ function isAlchemySponsorshipLimitError(error) {
1869
1907
  var import_aa_alchemy = require("@getpara/aa-alchemy");
1870
1908
  var import_aa_pimlico = require("@getpara/aa-pimlico");
1871
1909
  var import_accounts = require("viem/accounts");
1910
+ var ALCHEMY_7702_DELEGATION_ADDRESS = "0x69007702764179f14F51cdce752f4f775d74E139";
1872
1911
  async function createAAProviderState(options) {
1873
1912
  if (options.provider === "alchemy") {
1874
1913
  return createAlchemyAAState({
@@ -2068,7 +2107,7 @@ async function createAlchemyWalletApisState(params) {
2068
2107
  provider: "alchemy",
2069
2108
  mode: params.mode,
2070
2109
  AAAddress: accountAddress,
2071
- delegationAddress: params.mode === "7702" ? signer.address : void 0,
2110
+ delegationAddress: params.mode === "7702" ? ALCHEMY_7702_DELEGATION_ADDRESS : void 0,
2072
2111
  sendTransaction: async (call) => sendCalls([call]),
2073
2112
  sendBatchTransaction: async (calls) => sendCalls(calls)
2074
2113
  };