@aomi-labs/client 0.1.22 → 0.1.24
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 +2468 -2757
- package/dist/index.cjs +478 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +132 -182
- package/dist/index.d.ts +132 -182
- package/dist/index.js +477 -306
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/skills/README.md +2 -2
- package/skills/{aomi-app-builder → aomi-build}/SKILL.md +2 -2
- package/skills/aomi-build/agents/openai.yaml +4 -0
- package/skills/aomi-transact/.skill-optimizer/cli-commands.json +124 -0
- package/skills/aomi-transact/.skill-optimizer/skill-optimizer.json +52 -0
- package/skills/aomi-transact/SKILL.md +176 -72
- package/skills/aomi-app-builder/agents/openai.yaml +0 -4
- /package/skills/{aomi-app-builder → aomi-build}/references/aomi-sdk-patterns.md +0 -0
- /package/skills/{aomi-app-builder → aomi-build}/references/spec-to-tools.md +0 -0
package/dist/index.cjs
CHANGED
|
@@ -65,16 +65,12 @@ __export(index_exports, {
|
|
|
65
65
|
isAlchemySponsorshipLimitError: () => isAlchemySponsorshipLimitError,
|
|
66
66
|
isAsyncCallback: () => isAsyncCallback,
|
|
67
67
|
isInlineCall: () => isInlineCall,
|
|
68
|
-
isProviderConfigured: () => isProviderConfigured,
|
|
69
68
|
isSystemError: () => isSystemError,
|
|
70
69
|
isSystemNotice: () => isSystemNotice,
|
|
71
70
|
normalizeEip712Payload: () => normalizeEip712Payload,
|
|
72
71
|
normalizeTxPayload: () => normalizeTxPayload,
|
|
73
|
-
parseAAConfig: () => parseAAConfig,
|
|
74
|
-
readEnv: () => readEnv,
|
|
75
|
-
resolveAlchemyConfig: () => resolveAlchemyConfig,
|
|
76
|
-
resolveDefaultProvider: () => resolveDefaultProvider,
|
|
77
72
|
resolvePimlicoConfig: () => resolvePimlicoConfig,
|
|
73
|
+
toAAWalletCall: () => toAAWalletCall,
|
|
78
74
|
toViemSignTypedDataArgs: () => toViemSignTypedDataArgs,
|
|
79
75
|
unwrapSystemEvent: () => unwrapSystemEvent
|
|
80
76
|
});
|
|
@@ -675,14 +671,11 @@ function isAsyncCallback(event) {
|
|
|
675
671
|
return "AsyncCallback" in event;
|
|
676
672
|
}
|
|
677
673
|
|
|
678
|
-
// src/event
|
|
674
|
+
// src/event.ts
|
|
679
675
|
var TypedEventEmitter = class {
|
|
680
676
|
constructor() {
|
|
681
677
|
this.listeners = /* @__PURE__ */ new Map();
|
|
682
678
|
}
|
|
683
|
-
/**
|
|
684
|
-
* Subscribe to an event type. Returns an unsubscribe function.
|
|
685
|
-
*/
|
|
686
679
|
on(type, handler) {
|
|
687
680
|
let set = this.listeners.get(type);
|
|
688
681
|
if (!set) {
|
|
@@ -697,9 +690,6 @@ var TypedEventEmitter = class {
|
|
|
697
690
|
}
|
|
698
691
|
};
|
|
699
692
|
}
|
|
700
|
-
/**
|
|
701
|
-
* Subscribe to an event type for a single emission, then auto-unsubscribe.
|
|
702
|
-
*/
|
|
703
693
|
once(type, handler) {
|
|
704
694
|
const wrapper = ((payload) => {
|
|
705
695
|
unsub();
|
|
@@ -708,9 +698,6 @@ var TypedEventEmitter = class {
|
|
|
708
698
|
const unsub = this.on(type, wrapper);
|
|
709
699
|
return unsub;
|
|
710
700
|
}
|
|
711
|
-
/**
|
|
712
|
-
* Emit an event to all listeners of `type` and wildcard `"*"` listeners.
|
|
713
|
-
*/
|
|
714
701
|
emit(type, payload) {
|
|
715
702
|
const typeSet = this.listeners.get(type);
|
|
716
703
|
if (typeSet) {
|
|
@@ -727,9 +714,6 @@ var TypedEventEmitter = class {
|
|
|
727
714
|
}
|
|
728
715
|
}
|
|
729
716
|
}
|
|
730
|
-
/**
|
|
731
|
-
* Remove a specific handler from an event type.
|
|
732
|
-
*/
|
|
733
717
|
off(type, handler) {
|
|
734
718
|
const set = this.listeners.get(type);
|
|
735
719
|
if (set) {
|
|
@@ -739,15 +723,10 @@ var TypedEventEmitter = class {
|
|
|
739
723
|
}
|
|
740
724
|
}
|
|
741
725
|
}
|
|
742
|
-
/**
|
|
743
|
-
* Remove all listeners for all event types.
|
|
744
|
-
*/
|
|
745
726
|
removeAllListeners() {
|
|
746
727
|
this.listeners.clear();
|
|
747
728
|
}
|
|
748
729
|
};
|
|
749
|
-
|
|
750
|
-
// src/event-unwrap.ts
|
|
751
730
|
function unwrapSystemEvent(event) {
|
|
752
731
|
var _a;
|
|
753
732
|
if (isInlineCall(event)) {
|
|
@@ -848,6 +827,15 @@ function normalizeEip712Payload(payload) {
|
|
|
848
827
|
const description = typeof args.description === "string" ? args.description : void 0;
|
|
849
828
|
return { typed_data: typedData, description };
|
|
850
829
|
}
|
|
830
|
+
function toAAWalletCall(payload, defaultChainId = 1) {
|
|
831
|
+
var _a, _b;
|
|
832
|
+
return {
|
|
833
|
+
to: payload.to,
|
|
834
|
+
value: BigInt((_a = payload.value) != null ? _a : "0"),
|
|
835
|
+
data: payload.data ? payload.data : void 0,
|
|
836
|
+
chainId: (_b = payload.chainId) != null ? _b : defaultChainId
|
|
837
|
+
};
|
|
838
|
+
}
|
|
851
839
|
function toViemSignTypedDataArgs(payload) {
|
|
852
840
|
var _a;
|
|
853
841
|
const typedData = payload.typed_data;
|
|
@@ -1136,8 +1124,37 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1136
1124
|
return state;
|
|
1137
1125
|
}
|
|
1138
1126
|
// ===========================================================================
|
|
1139
|
-
//
|
|
1127
|
+
// Public API — Polling Control
|
|
1140
1128
|
// ===========================================================================
|
|
1129
|
+
/** Whether the session is currently polling for state updates. */
|
|
1130
|
+
getIsPolling() {
|
|
1131
|
+
return this.pollTimer !== null;
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Fetch the current state from the backend (one-shot).
|
|
1135
|
+
* Automatically starts polling if the backend is processing.
|
|
1136
|
+
*/
|
|
1137
|
+
async fetchCurrentState() {
|
|
1138
|
+
this.assertOpen();
|
|
1139
|
+
const state = await this.client.fetchState(
|
|
1140
|
+
this.sessionId,
|
|
1141
|
+
this.userState,
|
|
1142
|
+
this.clientId
|
|
1143
|
+
);
|
|
1144
|
+
this.assertUserStateAligned(state.user_state);
|
|
1145
|
+
this.applyState(state);
|
|
1146
|
+
if (state.is_processing && !this.pollTimer) {
|
|
1147
|
+
this._isProcessing = true;
|
|
1148
|
+
this.emit("processing_start", void 0);
|
|
1149
|
+
this.startPolling();
|
|
1150
|
+
} else if (!state.is_processing) {
|
|
1151
|
+
this._isProcessing = false;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Start polling for state updates. Idempotent — no-op if already polling.
|
|
1156
|
+
* Useful for resuming polling after resolving a wallet request.
|
|
1157
|
+
*/
|
|
1141
1158
|
startPolling() {
|
|
1142
1159
|
var _a;
|
|
1143
1160
|
if (this.pollTimer || this.closed) return;
|
|
@@ -1147,6 +1164,7 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1147
1164
|
void this.pollTick();
|
|
1148
1165
|
}, this.pollIntervalMs);
|
|
1149
1166
|
}
|
|
1167
|
+
/** Stop polling for state updates. Idempotent — no-op if not polling. */
|
|
1150
1168
|
stopPolling() {
|
|
1151
1169
|
var _a;
|
|
1152
1170
|
if (this.pollTimer) {
|
|
@@ -1278,79 +1296,14 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1278
1296
|
if (!isSubsetMatch(this.userState, actualUserState)) {
|
|
1279
1297
|
const expected = JSON.stringify(sortJson(this.userState));
|
|
1280
1298
|
const actual = JSON.stringify(sortJson(actualUserState));
|
|
1281
|
-
|
|
1282
|
-
`Backend user_state mismatch. expected subset=${expected} actual=${actual}`
|
|
1299
|
+
console.warn(
|
|
1300
|
+
`[session] Backend user_state mismatch (non-fatal). expected subset=${expected} actual=${actual}`
|
|
1283
1301
|
);
|
|
1284
1302
|
}
|
|
1285
1303
|
}
|
|
1286
1304
|
};
|
|
1287
1305
|
|
|
1288
1306
|
// src/aa/types.ts
|
|
1289
|
-
var MODES = /* @__PURE__ */ new Set(["4337", "7702"]);
|
|
1290
|
-
var SPONSORSHIP_MODES = /* @__PURE__ */ new Set([
|
|
1291
|
-
"disabled",
|
|
1292
|
-
"optional",
|
|
1293
|
-
"required"
|
|
1294
|
-
]);
|
|
1295
|
-
function isObject(value) {
|
|
1296
|
-
return typeof value === "object" && value !== null;
|
|
1297
|
-
}
|
|
1298
|
-
function assertChainConfig(value, index) {
|
|
1299
|
-
if (!isObject(value)) {
|
|
1300
|
-
throw new Error(`Invalid AA config chain at index ${index}: expected object`);
|
|
1301
|
-
}
|
|
1302
|
-
if (typeof value.chainId !== "number") {
|
|
1303
|
-
throw new Error(`Invalid AA config chain at index ${index}: chainId must be a number`);
|
|
1304
|
-
}
|
|
1305
|
-
if (typeof value.enabled !== "boolean") {
|
|
1306
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: enabled must be a boolean`);
|
|
1307
|
-
}
|
|
1308
|
-
if (!MODES.has(value.defaultMode)) {
|
|
1309
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: unsupported defaultMode`);
|
|
1310
|
-
}
|
|
1311
|
-
if (!Array.isArray(value.supportedModes) || value.supportedModes.length === 0) {
|
|
1312
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: supportedModes must be a non-empty array`);
|
|
1313
|
-
}
|
|
1314
|
-
if (!value.supportedModes.every((mode) => MODES.has(mode))) {
|
|
1315
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: supportedModes contains an unsupported mode`);
|
|
1316
|
-
}
|
|
1317
|
-
if (!value.supportedModes.includes(value.defaultMode)) {
|
|
1318
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: defaultMode must be in supportedModes`);
|
|
1319
|
-
}
|
|
1320
|
-
if (typeof value.allowBatching !== "boolean") {
|
|
1321
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: allowBatching must be a boolean`);
|
|
1322
|
-
}
|
|
1323
|
-
if (!SPONSORSHIP_MODES.has(value.sponsorship)) {
|
|
1324
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: unsupported sponsorship mode`);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
function parseAAConfig(value) {
|
|
1328
|
-
if (!isObject(value)) {
|
|
1329
|
-
throw new Error("Invalid AA config: expected object");
|
|
1330
|
-
}
|
|
1331
|
-
if (typeof value.enabled !== "boolean") {
|
|
1332
|
-
throw new Error("Invalid AA config: enabled must be a boolean");
|
|
1333
|
-
}
|
|
1334
|
-
if (typeof value.provider !== "string" || !value.provider) {
|
|
1335
|
-
throw new Error("Invalid AA config: provider must be a non-empty string");
|
|
1336
|
-
}
|
|
1337
|
-
if (value.provider !== "alchemy" && value.provider !== "pimlico") {
|
|
1338
|
-
throw new Error('Invalid AA config: provider must be either "alchemy" or "pimlico"');
|
|
1339
|
-
}
|
|
1340
|
-
if (typeof value.fallbackToEoa !== "boolean") {
|
|
1341
|
-
throw new Error("Invalid AA config: fallbackToEoa must be a boolean");
|
|
1342
|
-
}
|
|
1343
|
-
if (!Array.isArray(value.chains)) {
|
|
1344
|
-
throw new Error("Invalid AA config: chains must be an array");
|
|
1345
|
-
}
|
|
1346
|
-
value.chains.forEach((chain, index) => assertChainConfig(chain, index));
|
|
1347
|
-
return {
|
|
1348
|
-
enabled: value.enabled,
|
|
1349
|
-
provider: value.provider,
|
|
1350
|
-
fallbackToEoa: value.fallbackToEoa,
|
|
1351
|
-
chains: value.chains
|
|
1352
|
-
};
|
|
1353
|
-
}
|
|
1354
1307
|
function getAAChainConfig(config, calls, chainsById) {
|
|
1355
1308
|
if (!config.enabled || calls.length === 0) {
|
|
1356
1309
|
return null;
|
|
@@ -1389,13 +1342,6 @@ function buildAAExecutionPlan(config, chainConfig) {
|
|
|
1389
1342
|
function getWalletExecutorReady(providerState) {
|
|
1390
1343
|
return !providerState.resolved || !providerState.pending && (Boolean(providerState.account) || Boolean(providerState.error) || providerState.resolved.fallbackToEoa);
|
|
1391
1344
|
}
|
|
1392
|
-
function mapCall(call) {
|
|
1393
|
-
return {
|
|
1394
|
-
to: call.to,
|
|
1395
|
-
value: BigInt(call.value),
|
|
1396
|
-
data: call.data ? call.data : void 0
|
|
1397
|
-
};
|
|
1398
|
-
}
|
|
1399
1345
|
var DEFAULT_AA_CONFIG = {
|
|
1400
1346
|
enabled: true,
|
|
1401
1347
|
provider: "alchemy",
|
|
@@ -1443,6 +1389,27 @@ var DEFAULT_AA_CONFIG = {
|
|
|
1443
1389
|
}
|
|
1444
1390
|
]
|
|
1445
1391
|
};
|
|
1392
|
+
|
|
1393
|
+
// src/chains.ts
|
|
1394
|
+
var import_chains = require("viem/chains");
|
|
1395
|
+
var ALCHEMY_CHAIN_SLUGS = {
|
|
1396
|
+
1: "eth-mainnet",
|
|
1397
|
+
137: "polygon-mainnet",
|
|
1398
|
+
42161: "arb-mainnet",
|
|
1399
|
+
8453: "base-mainnet",
|
|
1400
|
+
10: "opt-mainnet",
|
|
1401
|
+
11155111: "eth-sepolia"
|
|
1402
|
+
};
|
|
1403
|
+
var CHAINS_BY_ID = {
|
|
1404
|
+
1: import_chains.mainnet,
|
|
1405
|
+
137: import_chains.polygon,
|
|
1406
|
+
42161: import_chains.arbitrum,
|
|
1407
|
+
10: import_chains.optimism,
|
|
1408
|
+
8453: import_chains.base,
|
|
1409
|
+
11155111: import_chains.sepolia
|
|
1410
|
+
};
|
|
1411
|
+
|
|
1412
|
+
// src/aa/execute.ts
|
|
1446
1413
|
async function executeWalletCalls(params) {
|
|
1447
1414
|
const {
|
|
1448
1415
|
callList,
|
|
@@ -1481,7 +1448,7 @@ async function executeViaAA(callList, providerState) {
|
|
|
1481
1448
|
if (!account || !resolved) {
|
|
1482
1449
|
throw (_a = providerState.error) != null ? _a : new Error("smart_account_unavailable");
|
|
1483
1450
|
}
|
|
1484
|
-
const callsPayload = callList.map(
|
|
1451
|
+
const callsPayload = callList.map(({ to, value, data }) => ({ to, value, data }));
|
|
1485
1452
|
const receipt = callList.length > 1 ? await account.sendBatchTransaction(callsPayload) : await account.sendTransaction(callsPayload[0]);
|
|
1486
1453
|
const txHash = receipt.transactionHash;
|
|
1487
1454
|
const providerPrefix = account.provider.toLowerCase();
|
|
@@ -1505,15 +1472,7 @@ async function resolve7702Delegation(txHash, callList) {
|
|
|
1505
1472
|
const { createPublicClient, http } = await import("viem");
|
|
1506
1473
|
const chainId = (_a = callList[0]) == null ? void 0 : _a.chainId;
|
|
1507
1474
|
if (!chainId) return void 0;
|
|
1508
|
-
const
|
|
1509
|
-
const knownChains = {
|
|
1510
|
-
1: mainnet,
|
|
1511
|
-
137: polygon,
|
|
1512
|
-
42161: arbitrum,
|
|
1513
|
-
10: optimism,
|
|
1514
|
-
8453: base
|
|
1515
|
-
};
|
|
1516
|
-
const chain = knownChains[chainId];
|
|
1475
|
+
const chain = CHAINS_BY_ID[chainId];
|
|
1517
1476
|
if (!chain) return void 0;
|
|
1518
1477
|
const client = createPublicClient({ chain, transport: http() });
|
|
1519
1478
|
const tx = await client.getTransaction({ hash: txHash });
|
|
@@ -1539,7 +1498,7 @@ async function executeViaEoa({
|
|
|
1539
1498
|
}) {
|
|
1540
1499
|
var _a, _b;
|
|
1541
1500
|
const { createPublicClient, createWalletClient, http } = await import("viem");
|
|
1542
|
-
const { privateKeyToAccount:
|
|
1501
|
+
const { privateKeyToAccount: privateKeyToAccount4 } = await import("viem/accounts");
|
|
1543
1502
|
const hashes = [];
|
|
1544
1503
|
if (localPrivateKey) {
|
|
1545
1504
|
for (const call of callList) {
|
|
@@ -1551,7 +1510,7 @@ async function executeViaEoa({
|
|
|
1551
1510
|
if (!rpcUrl) {
|
|
1552
1511
|
throw new Error(`No RPC for chain ${call.chainId}`);
|
|
1553
1512
|
}
|
|
1554
|
-
const account =
|
|
1513
|
+
const account = privateKeyToAccount4(localPrivateKey);
|
|
1555
1514
|
const walletClient = createWalletClient({
|
|
1556
1515
|
account,
|
|
1557
1516
|
chain,
|
|
@@ -1560,8 +1519,8 @@ async function executeViaEoa({
|
|
|
1560
1519
|
const hash = await walletClient.sendTransaction({
|
|
1561
1520
|
account,
|
|
1562
1521
|
to: call.to,
|
|
1563
|
-
value:
|
|
1564
|
-
data: call.data
|
|
1522
|
+
value: call.value,
|
|
1523
|
+
data: call.data
|
|
1565
1524
|
});
|
|
1566
1525
|
const publicClient = createPublicClient({
|
|
1567
1526
|
chain,
|
|
@@ -1591,7 +1550,7 @@ async function executeViaEoa({
|
|
|
1591
1550
|
const canUseSendCalls = atomicStatus === "supported" || atomicStatus === "ready";
|
|
1592
1551
|
if (canUseSendCalls) {
|
|
1593
1552
|
const batchResult = await sendCallsSyncAsync({
|
|
1594
|
-
calls: callList.map(
|
|
1553
|
+
calls: callList.map(({ to, value, data }) => ({ to, value, data })),
|
|
1595
1554
|
capabilities: {
|
|
1596
1555
|
atomic: {
|
|
1597
1556
|
required: true
|
|
@@ -1609,8 +1568,8 @@ async function executeViaEoa({
|
|
|
1609
1568
|
const hash = await sendTransactionAsync({
|
|
1610
1569
|
chainId: call.chainId,
|
|
1611
1570
|
to: call.to,
|
|
1612
|
-
value:
|
|
1613
|
-
data: call.data
|
|
1571
|
+
value: call.value,
|
|
1572
|
+
data: call.data
|
|
1614
1573
|
});
|
|
1615
1574
|
hashes.push(hash);
|
|
1616
1575
|
}
|
|
@@ -1624,136 +1583,28 @@ async function executeViaEoa({
|
|
|
1624
1583
|
};
|
|
1625
1584
|
}
|
|
1626
1585
|
|
|
1627
|
-
// src/aa/alchemy/
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
"ALCHEMY_GAS_POLICY_ID",
|
|
1634
|
-
"NEXT_PUBLIC_ALCHEMY_GAS_POLICY_ID"
|
|
1635
|
-
];
|
|
1636
|
-
|
|
1637
|
-
// src/aa/pimlico/env.ts
|
|
1638
|
-
var PIMLICO_API_KEY_ENVS = [
|
|
1639
|
-
"PIMLICO_API_KEY",
|
|
1640
|
-
"NEXT_PUBLIC_PIMLICO_API_KEY"
|
|
1641
|
-
];
|
|
1642
|
-
|
|
1643
|
-
// src/aa/env.ts
|
|
1644
|
-
function readEnv(candidates, options = {}) {
|
|
1645
|
-
var _a;
|
|
1646
|
-
const { publicOnly = false } = options;
|
|
1647
|
-
for (const name of candidates) {
|
|
1648
|
-
if (publicOnly && !name.startsWith("NEXT_PUBLIC_")) {
|
|
1649
|
-
continue;
|
|
1650
|
-
}
|
|
1651
|
-
const value = (_a = process.env[name]) == null ? void 0 : _a.trim();
|
|
1652
|
-
if (value) return value;
|
|
1653
|
-
}
|
|
1654
|
-
return void 0;
|
|
1655
|
-
}
|
|
1656
|
-
function readGasPolicyEnv(chainId, chainSlugById, baseCandidates, options = {}) {
|
|
1657
|
-
const slug = chainSlugById[chainId];
|
|
1658
|
-
if (slug) {
|
|
1659
|
-
const chainSpecific = baseCandidates.map(
|
|
1660
|
-
(base) => `${base}_${slug.toUpperCase()}`
|
|
1661
|
-
);
|
|
1662
|
-
const found = readEnv(chainSpecific, options);
|
|
1663
|
-
if (found) return found;
|
|
1664
|
-
}
|
|
1665
|
-
return readEnv(baseCandidates, options);
|
|
1666
|
-
}
|
|
1667
|
-
function isProviderConfigured(provider, options = {}) {
|
|
1668
|
-
return provider === "alchemy" ? Boolean(readEnv(ALCHEMY_API_KEY_ENVS, options)) : Boolean(readEnv(PIMLICO_API_KEY_ENVS, options));
|
|
1669
|
-
}
|
|
1670
|
-
function resolveDefaultProvider(options = {}) {
|
|
1671
|
-
if (isProviderConfigured("alchemy", options)) return "alchemy";
|
|
1672
|
-
if (isProviderConfigured("pimlico", options)) return "pimlico";
|
|
1673
|
-
throw new Error(
|
|
1674
|
-
"AA requires provider credentials. Set ALCHEMY_API_KEY or PIMLICO_API_KEY, or use --eoa."
|
|
1675
|
-
);
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
// src/aa/alchemy/resolve.ts
|
|
1679
|
-
function resolveAlchemyConfig(options) {
|
|
1680
|
-
const {
|
|
1681
|
-
calls,
|
|
1682
|
-
localPrivateKey,
|
|
1683
|
-
accountAbstractionConfig = DEFAULT_AA_CONFIG,
|
|
1684
|
-
chainsById,
|
|
1685
|
-
chainSlugById = {},
|
|
1686
|
-
getPreferredRpcUrl = (chain2) => {
|
|
1687
|
-
var _a;
|
|
1688
|
-
return (_a = chain2.rpcUrls.default.http[0]) != null ? _a : "";
|
|
1689
|
-
},
|
|
1690
|
-
modeOverride,
|
|
1691
|
-
publicOnly = false,
|
|
1692
|
-
throwOnMissingConfig = false,
|
|
1693
|
-
apiKey: preResolvedApiKey,
|
|
1694
|
-
gasPolicyId: preResolvedGasPolicyId
|
|
1695
|
-
} = options;
|
|
1696
|
-
if (!calls || localPrivateKey) {
|
|
1697
|
-
return null;
|
|
1698
|
-
}
|
|
1699
|
-
const config = __spreadProps(__spreadValues({}, accountAbstractionConfig), {
|
|
1700
|
-
provider: "alchemy"
|
|
1701
|
-
});
|
|
1586
|
+
// src/aa/alchemy/provider.ts
|
|
1587
|
+
function resolveForHook(params) {
|
|
1588
|
+
var _a, _b;
|
|
1589
|
+
const { calls, localPrivateKey, accountAbstractionConfig, chainsById, getPreferredRpcUrl } = params;
|
|
1590
|
+
if (!calls || localPrivateKey) return null;
|
|
1591
|
+
const config = __spreadProps(__spreadValues({}, accountAbstractionConfig), { provider: "alchemy" });
|
|
1702
1592
|
const chainConfig = getAAChainConfig(config, calls, chainsById);
|
|
1703
|
-
if (!chainConfig)
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
throw new Error(
|
|
1707
|
-
`AA is not configured for chain ${chainIds[0]}, or batching is disabled for that chain.`
|
|
1708
|
-
);
|
|
1709
|
-
}
|
|
1710
|
-
return null;
|
|
1711
|
-
}
|
|
1712
|
-
const apiKey = preResolvedApiKey != null ? preResolvedApiKey : readEnv(ALCHEMY_API_KEY_ENVS, { publicOnly });
|
|
1713
|
-
if (!apiKey) {
|
|
1714
|
-
if (throwOnMissingConfig) {
|
|
1715
|
-
throw new Error("Alchemy AA requires ALCHEMY_API_KEY.");
|
|
1716
|
-
}
|
|
1717
|
-
return null;
|
|
1718
|
-
}
|
|
1593
|
+
if (!chainConfig) return null;
|
|
1594
|
+
const apiKey = (_a = process.env.NEXT_PUBLIC_ALCHEMY_API_KEY) == null ? void 0 : _a.trim();
|
|
1595
|
+
if (!apiKey) return null;
|
|
1719
1596
|
const chain = chainsById[chainConfig.chainId];
|
|
1720
|
-
if (!chain)
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
const gasPolicyId = preResolvedGasPolicyId != null ? preResolvedGasPolicyId : readGasPolicyEnv(
|
|
1724
|
-
chainConfig.chainId,
|
|
1725
|
-
chainSlugById,
|
|
1726
|
-
ALCHEMY_GAS_POLICY_ENVS,
|
|
1727
|
-
{ publicOnly }
|
|
1728
|
-
);
|
|
1729
|
-
if (chainConfig.sponsorship === "required" && !gasPolicyId) {
|
|
1730
|
-
if (throwOnMissingConfig) {
|
|
1731
|
-
throw new Error(
|
|
1732
|
-
`Alchemy gas policy required for chain ${chainConfig.chainId} but not configured.`
|
|
1733
|
-
);
|
|
1734
|
-
}
|
|
1735
|
-
return null;
|
|
1736
|
-
}
|
|
1737
|
-
if (modeOverride && !chainConfig.supportedModes.includes(modeOverride)) {
|
|
1738
|
-
if (throwOnMissingConfig) {
|
|
1739
|
-
throw new Error(
|
|
1740
|
-
`AA mode "${modeOverride}" is not supported on chain ${chainConfig.chainId}.`
|
|
1741
|
-
);
|
|
1742
|
-
}
|
|
1743
|
-
return null;
|
|
1744
|
-
}
|
|
1745
|
-
const resolvedChainConfig = modeOverride ? __spreadProps(__spreadValues({}, chainConfig), { defaultMode: modeOverride }) : chainConfig;
|
|
1746
|
-
const resolved = buildAAExecutionPlan(config, resolvedChainConfig);
|
|
1597
|
+
if (!chain) return null;
|
|
1598
|
+
const gasPolicyId = (_b = process.env.NEXT_PUBLIC_ALCHEMY_GAS_POLICY_ID) == null ? void 0 : _b.trim();
|
|
1599
|
+
const resolved = buildAAExecutionPlan(config, chainConfig);
|
|
1747
1600
|
return __spreadProps(__spreadValues({}, resolved), {
|
|
1748
1601
|
apiKey,
|
|
1749
1602
|
chain,
|
|
1750
1603
|
rpcUrl: getPreferredRpcUrl(chain),
|
|
1751
1604
|
gasPolicyId,
|
|
1752
|
-
mode:
|
|
1605
|
+
mode: chainConfig.defaultMode
|
|
1753
1606
|
});
|
|
1754
1607
|
}
|
|
1755
|
-
|
|
1756
|
-
// src/aa/alchemy/provider.ts
|
|
1757
1608
|
function createAlchemyAAProvider({
|
|
1758
1609
|
accountAbstractionConfig = DEFAULT_AA_CONFIG,
|
|
1759
1610
|
useAlchemyAA,
|
|
@@ -1763,14 +1614,13 @@ function createAlchemyAAProvider({
|
|
|
1763
1614
|
}) {
|
|
1764
1615
|
return function useAlchemyAAProvider(calls, localPrivateKey) {
|
|
1765
1616
|
var _a;
|
|
1766
|
-
const resolved =
|
|
1617
|
+
const resolved = resolveForHook({
|
|
1767
1618
|
calls,
|
|
1768
1619
|
localPrivateKey,
|
|
1769
1620
|
accountAbstractionConfig,
|
|
1770
1621
|
chainsById,
|
|
1771
1622
|
chainSlugById,
|
|
1772
|
-
getPreferredRpcUrl
|
|
1773
|
-
publicOnly: true
|
|
1623
|
+
getPreferredRpcUrl
|
|
1774
1624
|
});
|
|
1775
1625
|
const params = resolved ? {
|
|
1776
1626
|
enabled: true,
|
|
@@ -1885,32 +1735,69 @@ function getUnsupportedAdapterState(resolved, adapter) {
|
|
|
1885
1735
|
|
|
1886
1736
|
// src/aa/alchemy/create.ts
|
|
1887
1737
|
var ALCHEMY_7702_DELEGATION_ADDRESS = "0x69007702764179f14F51cdce752f4f775d74E139";
|
|
1738
|
+
var AA_DEBUG_ENABLED = process.env.AOMI_AA_DEBUG === "1";
|
|
1739
|
+
var EIP_7702_AUTH_GAS_OVERHEAD = BigInt(25e3);
|
|
1740
|
+
function alchemyRpcUrl(chainId, apiKey) {
|
|
1741
|
+
var _a;
|
|
1742
|
+
const slug = (_a = ALCHEMY_CHAIN_SLUGS[chainId]) != null ? _a : "eth-mainnet";
|
|
1743
|
+
return `https://${slug}.g.alchemy.com/v2/${apiKey}`;
|
|
1744
|
+
}
|
|
1745
|
+
function aaDebug(message, fields) {
|
|
1746
|
+
if (!AA_DEBUG_ENABLED) return;
|
|
1747
|
+
if (fields) {
|
|
1748
|
+
console.debug(`[aomi][aa][alchemy] ${message}`, fields);
|
|
1749
|
+
return;
|
|
1750
|
+
}
|
|
1751
|
+
console.debug(`[aomi][aa][alchemy] ${message}`);
|
|
1752
|
+
}
|
|
1753
|
+
function extractExistingAccountAddress(error) {
|
|
1754
|
+
var _a;
|
|
1755
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1756
|
+
const match = message.match(/Account with address (0x[a-fA-F0-9]{40}) already exists/);
|
|
1757
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : null;
|
|
1758
|
+
}
|
|
1759
|
+
function deriveAlchemy4337AccountId(address) {
|
|
1760
|
+
var _a;
|
|
1761
|
+
const hex = address.toLowerCase().slice(2).padEnd(32, "0").slice(0, 32).split("");
|
|
1762
|
+
const namespace = ["4", "3", "3", "7", "5", "a", "a", "b"];
|
|
1763
|
+
for (let i = 0; i < namespace.length; i += 1) {
|
|
1764
|
+
hex[i] = namespace[i];
|
|
1765
|
+
}
|
|
1766
|
+
hex[12] = "4";
|
|
1767
|
+
const variant = Number.parseInt((_a = hex[16]) != null ? _a : "0", 16);
|
|
1768
|
+
hex[16] = (variant & 3 | 8).toString(16);
|
|
1769
|
+
return [
|
|
1770
|
+
hex.slice(0, 8).join(""),
|
|
1771
|
+
hex.slice(8, 12).join(""),
|
|
1772
|
+
hex.slice(12, 16).join(""),
|
|
1773
|
+
hex.slice(16, 20).join(""),
|
|
1774
|
+
hex.slice(20, 32).join("")
|
|
1775
|
+
].join("-");
|
|
1776
|
+
}
|
|
1888
1777
|
async function createAlchemyAAState(options) {
|
|
1889
1778
|
var _a, _b;
|
|
1890
1779
|
const {
|
|
1891
1780
|
chain,
|
|
1892
1781
|
owner,
|
|
1893
|
-
rpcUrl,
|
|
1894
1782
|
callList,
|
|
1895
1783
|
mode,
|
|
1896
1784
|
sponsored = true
|
|
1897
1785
|
} = options;
|
|
1898
|
-
const
|
|
1899
|
-
|
|
1900
|
-
chainsById: { [chain.id]: chain },
|
|
1901
|
-
modeOverride: mode,
|
|
1902
|
-
throwOnMissingConfig: true,
|
|
1903
|
-
getPreferredRpcUrl: () => rpcUrl,
|
|
1904
|
-
apiKey: options.apiKey,
|
|
1905
|
-
gasPolicyId: options.gasPolicyId
|
|
1786
|
+
const chainConfig = getAAChainConfig(DEFAULT_AA_CONFIG, callList, {
|
|
1787
|
+
[chain.id]: chain
|
|
1906
1788
|
});
|
|
1907
|
-
if (!
|
|
1908
|
-
throw new Error(
|
|
1789
|
+
if (!chainConfig) {
|
|
1790
|
+
throw new Error(`AA is not configured for chain ${chain.id}.`);
|
|
1909
1791
|
}
|
|
1910
|
-
const
|
|
1911
|
-
const
|
|
1912
|
-
|
|
1913
|
-
|
|
1792
|
+
const effectiveMode = mode != null ? mode : chainConfig.defaultMode;
|
|
1793
|
+
const plan = buildAAExecutionPlan(
|
|
1794
|
+
__spreadProps(__spreadValues({}, DEFAULT_AA_CONFIG), { provider: "alchemy" }),
|
|
1795
|
+
__spreadProps(__spreadValues({}, chainConfig), { defaultMode: effectiveMode })
|
|
1796
|
+
);
|
|
1797
|
+
const gasPolicyId = sponsored ? (_b = options.gasPolicyId) != null ? _b : (_a = process.env.ALCHEMY_GAS_POLICY_ID) == null ? void 0 : _a.trim() : void 0;
|
|
1798
|
+
const execution = __spreadProps(__spreadValues({}, plan), {
|
|
1799
|
+
mode: effectiveMode,
|
|
1800
|
+
sponsorship: gasPolicyId ? plan.sponsorship : "disabled",
|
|
1914
1801
|
fallbackToEoa: false
|
|
1915
1802
|
});
|
|
1916
1803
|
const ownerParams = getOwnerParams(owner);
|
|
@@ -1921,15 +1808,16 @@ async function createAlchemyAAState(options) {
|
|
|
1921
1808
|
return getUnsupportedAdapterState(execution, ownerParams.adapter);
|
|
1922
1809
|
}
|
|
1923
1810
|
if (owner.kind === "direct") {
|
|
1811
|
+
const directParams = {
|
|
1812
|
+
resolved: execution,
|
|
1813
|
+
chain,
|
|
1814
|
+
privateKey: owner.privateKey,
|
|
1815
|
+
apiKey: options.apiKey,
|
|
1816
|
+
proxyBaseUrl: options.proxyBaseUrl,
|
|
1817
|
+
gasPolicyId
|
|
1818
|
+
};
|
|
1924
1819
|
try {
|
|
1925
|
-
return await
|
|
1926
|
-
resolved: execution,
|
|
1927
|
-
chain,
|
|
1928
|
-
privateKey: owner.privateKey,
|
|
1929
|
-
apiKey,
|
|
1930
|
-
gasPolicyId,
|
|
1931
|
-
mode: execution.mode
|
|
1932
|
-
});
|
|
1820
|
+
return await (execution.mode === "7702" ? createAlchemy7702State(directParams) : createAlchemy4337State(directParams));
|
|
1933
1821
|
} catch (error) {
|
|
1934
1822
|
return {
|
|
1935
1823
|
resolved: execution,
|
|
@@ -1939,13 +1827,23 @@ async function createAlchemyAAState(options) {
|
|
|
1939
1827
|
};
|
|
1940
1828
|
}
|
|
1941
1829
|
}
|
|
1830
|
+
if (!options.apiKey) {
|
|
1831
|
+
return {
|
|
1832
|
+
resolved: execution,
|
|
1833
|
+
account: null,
|
|
1834
|
+
pending: false,
|
|
1835
|
+
error: new Error(
|
|
1836
|
+
"Alchemy AA with session/adapter owner requires ALCHEMY_API_KEY."
|
|
1837
|
+
)
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1942
1840
|
try {
|
|
1943
1841
|
const { createAlchemySmartAccount } = await import("@getpara/aa-alchemy");
|
|
1944
1842
|
const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
1945
|
-
apiKey,
|
|
1843
|
+
apiKey: options.apiKey,
|
|
1946
1844
|
gasPolicyId,
|
|
1947
1845
|
chain,
|
|
1948
|
-
rpcUrl,
|
|
1846
|
+
rpcUrl: options.rpcUrl,
|
|
1949
1847
|
mode: execution.mode
|
|
1950
1848
|
}));
|
|
1951
1849
|
if (!smartAccount) {
|
|
@@ -1971,42 +1869,197 @@ async function createAlchemyAAState(options) {
|
|
|
1971
1869
|
};
|
|
1972
1870
|
}
|
|
1973
1871
|
}
|
|
1974
|
-
async function
|
|
1872
|
+
async function createAlchemy4337State(params) {
|
|
1975
1873
|
const { createSmartWalletClient, alchemyWalletTransport } = await import("@alchemy/wallet-apis");
|
|
1874
|
+
const transport = params.proxyBaseUrl ? alchemyWalletTransport({ url: params.proxyBaseUrl }) : alchemyWalletTransport({ apiKey: params.apiKey });
|
|
1976
1875
|
const signer = (0, import_accounts2.privateKeyToAccount)(params.privateKey);
|
|
1977
|
-
const
|
|
1978
|
-
transport
|
|
1876
|
+
const alchemyClient = createSmartWalletClient(__spreadValues({
|
|
1877
|
+
transport,
|
|
1979
1878
|
chain: params.chain,
|
|
1980
1879
|
signer
|
|
1981
1880
|
}, params.gasPolicyId ? { paymaster: { policyId: params.gasPolicyId } } : {}));
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1881
|
+
const signerAddress = signer.address;
|
|
1882
|
+
const accountId = deriveAlchemy4337AccountId(signerAddress);
|
|
1883
|
+
aaDebug("4337:requestAccount:start", {
|
|
1884
|
+
signerAddress,
|
|
1885
|
+
chainId: params.chain.id,
|
|
1886
|
+
accountId,
|
|
1887
|
+
hasGasPolicyId: Boolean(params.gasPolicyId)
|
|
1888
|
+
});
|
|
1889
|
+
let account;
|
|
1890
|
+
try {
|
|
1891
|
+
account = await alchemyClient.requestAccount({
|
|
1892
|
+
signerAddress,
|
|
1893
|
+
id: accountId,
|
|
1894
|
+
creationHint: {
|
|
1895
|
+
accountType: "sma-b",
|
|
1896
|
+
createAdditional: true
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
} catch (error) {
|
|
1900
|
+
const existingAccountAddress = extractExistingAccountAddress(error);
|
|
1901
|
+
if (!existingAccountAddress) {
|
|
1902
|
+
throw error;
|
|
1903
|
+
}
|
|
1904
|
+
aaDebug("4337:requestAccount:existing-account", {
|
|
1905
|
+
existingAccountAddress
|
|
1906
|
+
});
|
|
1907
|
+
account = await alchemyClient.requestAccount({
|
|
1908
|
+
accountAddress: existingAccountAddress
|
|
1909
|
+
});
|
|
1986
1910
|
}
|
|
1911
|
+
const accountAddress = account.address;
|
|
1912
|
+
aaDebug("4337:requestAccount:done", { signerAddress, accountAddress });
|
|
1987
1913
|
const sendCalls = async (calls) => {
|
|
1988
|
-
var _a, _b;
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1914
|
+
var _a, _b, _c, _d;
|
|
1915
|
+
aaDebug("4337:sendCalls:start", {
|
|
1916
|
+
signerAddress,
|
|
1917
|
+
accountAddress,
|
|
1918
|
+
chainId: params.chain.id,
|
|
1919
|
+
callCount: calls.length,
|
|
1920
|
+
hasGasPolicyId: Boolean(params.gasPolicyId)
|
|
1921
|
+
});
|
|
1922
|
+
try {
|
|
1923
|
+
const result = await alchemyClient.sendCalls({
|
|
1924
|
+
account: accountAddress,
|
|
1925
|
+
calls
|
|
1926
|
+
});
|
|
1927
|
+
aaDebug("4337:sendCalls:submitted", { callId: result.id });
|
|
1928
|
+
const status = await alchemyClient.waitForCallsStatus({ id: result.id });
|
|
1929
|
+
const transactionHash = (_b = (_a = status.receipts) == null ? void 0 : _a[0]) == null ? void 0 : _b.transactionHash;
|
|
1930
|
+
aaDebug("4337:sendCalls:receipt", {
|
|
1931
|
+
callId: result.id,
|
|
1932
|
+
hasTransactionHash: Boolean(transactionHash),
|
|
1933
|
+
receipts: (_d = (_c = status.receipts) == null ? void 0 : _c.length) != null ? _d : 0
|
|
1934
|
+
});
|
|
1935
|
+
if (!transactionHash) {
|
|
1936
|
+
throw new Error("Alchemy Wallets API did not return a transaction hash.");
|
|
1937
|
+
}
|
|
1938
|
+
return { transactionHash };
|
|
1939
|
+
} catch (error) {
|
|
1940
|
+
aaDebug("4337:sendCalls:error", {
|
|
1941
|
+
signerAddress,
|
|
1942
|
+
accountAddress,
|
|
1943
|
+
chainId: params.chain.id,
|
|
1944
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1945
|
+
});
|
|
1946
|
+
throw error;
|
|
1996
1947
|
}
|
|
1997
|
-
return { transactionHash };
|
|
1998
1948
|
};
|
|
1999
|
-
const
|
|
1949
|
+
const smartAccount = {
|
|
2000
1950
|
provider: "alchemy",
|
|
2001
|
-
mode:
|
|
1951
|
+
mode: "4337",
|
|
2002
1952
|
AAAddress: accountAddress,
|
|
2003
|
-
delegationAddress: params.mode === "7702" ? ALCHEMY_7702_DELEGATION_ADDRESS : void 0,
|
|
2004
1953
|
sendTransaction: async (call) => sendCalls([call]),
|
|
2005
1954
|
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
2006
1955
|
};
|
|
2007
1956
|
return {
|
|
2008
1957
|
resolved: params.resolved,
|
|
2009
|
-
account,
|
|
1958
|
+
account: smartAccount,
|
|
1959
|
+
pending: false,
|
|
1960
|
+
error: null
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
async function createAlchemy7702State(params) {
|
|
1964
|
+
const { createWalletClient, createPublicClient, http } = await import("viem");
|
|
1965
|
+
const { encodeExecuteData } = await import("viem/experimental/erc7821");
|
|
1966
|
+
if (params.gasPolicyId) {
|
|
1967
|
+
aaDebug(
|
|
1968
|
+
"7702:gas-policy-ignored",
|
|
1969
|
+
{ gasPolicyId: params.gasPolicyId }
|
|
1970
|
+
);
|
|
1971
|
+
console.warn(
|
|
1972
|
+
"\u26A0\uFE0F Gas policy is not supported for raw EIP-7702 transactions. The signer's EOA pays gas directly."
|
|
1973
|
+
);
|
|
1974
|
+
}
|
|
1975
|
+
const signer = (0, import_accounts2.privateKeyToAccount)(params.privateKey);
|
|
1976
|
+
const signerAddress = signer.address;
|
|
1977
|
+
let rpcUrl;
|
|
1978
|
+
if (params.proxyBaseUrl) {
|
|
1979
|
+
rpcUrl = params.proxyBaseUrl;
|
|
1980
|
+
} else if (params.apiKey) {
|
|
1981
|
+
rpcUrl = alchemyRpcUrl(params.chain.id, params.apiKey);
|
|
1982
|
+
}
|
|
1983
|
+
const walletClient = createWalletClient({
|
|
1984
|
+
account: signer,
|
|
1985
|
+
chain: params.chain,
|
|
1986
|
+
transport: http(rpcUrl)
|
|
1987
|
+
});
|
|
1988
|
+
const publicClient = createPublicClient({
|
|
1989
|
+
chain: params.chain,
|
|
1990
|
+
transport: http(rpcUrl)
|
|
1991
|
+
});
|
|
1992
|
+
const send7702 = async (calls) => {
|
|
1993
|
+
aaDebug("7702:send:start", {
|
|
1994
|
+
signerAddress,
|
|
1995
|
+
chainId: params.chain.id,
|
|
1996
|
+
callCount: calls.length,
|
|
1997
|
+
calls: calls.map((call) => {
|
|
1998
|
+
var _a;
|
|
1999
|
+
return {
|
|
2000
|
+
to: call.to,
|
|
2001
|
+
value: call.value.toString(),
|
|
2002
|
+
data: (_a = call.data) != null ? _a : "0x"
|
|
2003
|
+
};
|
|
2004
|
+
})
|
|
2005
|
+
});
|
|
2006
|
+
const authorization = await walletClient.signAuthorization({
|
|
2007
|
+
contractAddress: ALCHEMY_7702_DELEGATION_ADDRESS
|
|
2008
|
+
});
|
|
2009
|
+
aaDebug("7702:authorization-signed", {
|
|
2010
|
+
contractAddress: ALCHEMY_7702_DELEGATION_ADDRESS
|
|
2011
|
+
});
|
|
2012
|
+
const data = encodeExecuteData({
|
|
2013
|
+
calls: calls.map((call) => {
|
|
2014
|
+
var _a;
|
|
2015
|
+
return {
|
|
2016
|
+
to: call.to,
|
|
2017
|
+
value: call.value,
|
|
2018
|
+
data: (_a = call.data) != null ? _a : "0x"
|
|
2019
|
+
};
|
|
2020
|
+
})
|
|
2021
|
+
});
|
|
2022
|
+
aaDebug("7702:calldata-encoded", { dataLength: data.length });
|
|
2023
|
+
const gasEstimate = await publicClient.estimateGas({
|
|
2024
|
+
account: signer,
|
|
2025
|
+
to: signerAddress,
|
|
2026
|
+
data,
|
|
2027
|
+
authorizationList: [authorization]
|
|
2028
|
+
});
|
|
2029
|
+
const gas = gasEstimate + EIP_7702_AUTH_GAS_OVERHEAD;
|
|
2030
|
+
aaDebug("7702:gas-estimated", {
|
|
2031
|
+
estimate: gasEstimate.toString(),
|
|
2032
|
+
total: gas.toString()
|
|
2033
|
+
});
|
|
2034
|
+
const hash = await walletClient.sendTransaction({
|
|
2035
|
+
to: signerAddress,
|
|
2036
|
+
data,
|
|
2037
|
+
gas,
|
|
2038
|
+
authorizationList: [authorization]
|
|
2039
|
+
});
|
|
2040
|
+
aaDebug("7702:tx-sent", { hash });
|
|
2041
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
2042
|
+
aaDebug("7702:tx-confirmed", {
|
|
2043
|
+
hash,
|
|
2044
|
+
status: receipt.status,
|
|
2045
|
+
gasUsed: receipt.gasUsed.toString()
|
|
2046
|
+
});
|
|
2047
|
+
if (receipt.status === "reverted") {
|
|
2048
|
+
throw new Error(`EIP-7702 transaction reverted: ${hash}`);
|
|
2049
|
+
}
|
|
2050
|
+
return { transactionHash: hash };
|
|
2051
|
+
};
|
|
2052
|
+
const smartAccount = {
|
|
2053
|
+
provider: "alchemy",
|
|
2054
|
+
mode: "7702",
|
|
2055
|
+
AAAddress: signerAddress,
|
|
2056
|
+
delegationAddress: ALCHEMY_7702_DELEGATION_ADDRESS,
|
|
2057
|
+
sendTransaction: async (call) => send7702([call]),
|
|
2058
|
+
sendBatchTransaction: async (calls) => send7702(calls)
|
|
2059
|
+
};
|
|
2060
|
+
return {
|
|
2061
|
+
resolved: params.resolved,
|
|
2062
|
+
account: smartAccount,
|
|
2010
2063
|
pending: false,
|
|
2011
2064
|
error: null
|
|
2012
2065
|
};
|
|
@@ -2014,6 +2067,7 @@ async function createAlchemyWalletApisState(params) {
|
|
|
2014
2067
|
|
|
2015
2068
|
// src/aa/pimlico/resolve.ts
|
|
2016
2069
|
function resolvePimlicoConfig(options) {
|
|
2070
|
+
var _a, _b, _c;
|
|
2017
2071
|
const {
|
|
2018
2072
|
calls,
|
|
2019
2073
|
localPrivateKey,
|
|
@@ -2041,7 +2095,7 @@ function resolvePimlicoConfig(options) {
|
|
|
2041
2095
|
}
|
|
2042
2096
|
return null;
|
|
2043
2097
|
}
|
|
2044
|
-
const apiKey = preResolvedApiKey != null ? preResolvedApiKey :
|
|
2098
|
+
const apiKey = (_c = preResolvedApiKey != null ? preResolvedApiKey : (_a = process.env.PIMLICO_API_KEY) == null ? void 0 : _a.trim()) != null ? _c : publicOnly ? (_b = process.env.NEXT_PUBLIC_PIMLICO_API_KEY) == null ? void 0 : _b.trim() : void 0;
|
|
2045
2099
|
if (!apiKey) {
|
|
2046
2100
|
if (throwOnMissingConfig) {
|
|
2047
2101
|
throw new Error("Pimlico AA requires PIMLICO_API_KEY.");
|
|
@@ -2105,28 +2159,36 @@ function createPimlicoAAProvider({
|
|
|
2105
2159
|
}
|
|
2106
2160
|
|
|
2107
2161
|
// src/aa/pimlico/create.ts
|
|
2162
|
+
var import_accounts3 = require("viem/accounts");
|
|
2163
|
+
var AA_DEBUG_ENABLED2 = process.env.AOMI_AA_DEBUG === "1";
|
|
2164
|
+
function pimDebug(message, fields) {
|
|
2165
|
+
if (!AA_DEBUG_ENABLED2) return;
|
|
2166
|
+
if (fields) {
|
|
2167
|
+
console.debug(`[aomi][aa][pimlico] ${message}`, fields);
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
console.debug(`[aomi][aa][pimlico] ${message}`);
|
|
2171
|
+
}
|
|
2108
2172
|
async function createPimlicoAAState(options) {
|
|
2109
|
-
var _a;
|
|
2110
|
-
const {
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
rpcUrl,
|
|
2114
|
-
callList,
|
|
2115
|
-
mode
|
|
2116
|
-
} = options;
|
|
2117
|
-
const resolved = resolvePimlicoConfig({
|
|
2118
|
-
calls: callList,
|
|
2119
|
-
chainsById: { [chain.id]: chain },
|
|
2120
|
-
rpcUrl,
|
|
2121
|
-
modeOverride: mode,
|
|
2122
|
-
throwOnMissingConfig: true,
|
|
2123
|
-
apiKey: options.apiKey
|
|
2173
|
+
var _a, _b;
|
|
2174
|
+
const { chain, owner, callList, mode } = options;
|
|
2175
|
+
const chainConfig = getAAChainConfig(DEFAULT_AA_CONFIG, callList, {
|
|
2176
|
+
[chain.id]: chain
|
|
2124
2177
|
});
|
|
2125
|
-
if (!
|
|
2126
|
-
throw new Error(
|
|
2178
|
+
if (!chainConfig) {
|
|
2179
|
+
throw new Error(`AA is not configured for chain ${chain.id}.`);
|
|
2180
|
+
}
|
|
2181
|
+
const effectiveMode = mode != null ? mode : chainConfig.defaultMode;
|
|
2182
|
+
const plan = buildAAExecutionPlan(
|
|
2183
|
+
__spreadProps(__spreadValues({}, DEFAULT_AA_CONFIG), { provider: "pimlico" }),
|
|
2184
|
+
__spreadProps(__spreadValues({}, chainConfig), { defaultMode: effectiveMode })
|
|
2185
|
+
);
|
|
2186
|
+
const apiKey = (_b = options.apiKey) != null ? _b : (_a = process.env.PIMLICO_API_KEY) == null ? void 0 : _a.trim();
|
|
2187
|
+
if (!apiKey) {
|
|
2188
|
+
throw new Error("Pimlico AA requires PIMLICO_API_KEY.");
|
|
2127
2189
|
}
|
|
2128
|
-
const
|
|
2129
|
-
|
|
2190
|
+
const execution = __spreadProps(__spreadValues({}, plan), {
|
|
2191
|
+
mode: effectiveMode,
|
|
2130
2192
|
fallbackToEoa: false
|
|
2131
2193
|
});
|
|
2132
2194
|
const ownerParams = getOwnerParams(owner);
|
|
@@ -2136,12 +2198,31 @@ async function createPimlicoAAState(options) {
|
|
|
2136
2198
|
if (ownerParams.kind === "unsupported_adapter") {
|
|
2137
2199
|
return getUnsupportedAdapterState(execution, ownerParams.adapter);
|
|
2138
2200
|
}
|
|
2201
|
+
if (owner.kind === "direct") {
|
|
2202
|
+
try {
|
|
2203
|
+
return await createPimlicoDirectState({
|
|
2204
|
+
resolved: execution,
|
|
2205
|
+
chain,
|
|
2206
|
+
privateKey: owner.privateKey,
|
|
2207
|
+
rpcUrl: options.rpcUrl,
|
|
2208
|
+
apiKey,
|
|
2209
|
+
mode: effectiveMode
|
|
2210
|
+
});
|
|
2211
|
+
} catch (error) {
|
|
2212
|
+
return {
|
|
2213
|
+
resolved: execution,
|
|
2214
|
+
account: null,
|
|
2215
|
+
pending: false,
|
|
2216
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2217
|
+
};
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2139
2220
|
try {
|
|
2140
2221
|
const { createPimlicoSmartAccount } = await import("@getpara/aa-pimlico");
|
|
2141
2222
|
const smartAccount = await createPimlicoSmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
2142
2223
|
apiKey,
|
|
2143
2224
|
chain,
|
|
2144
|
-
rpcUrl,
|
|
2225
|
+
rpcUrl: options.rpcUrl,
|
|
2145
2226
|
mode: execution.mode
|
|
2146
2227
|
}));
|
|
2147
2228
|
if (!smartAccount) {
|
|
@@ -2167,6 +2248,95 @@ async function createPimlicoAAState(options) {
|
|
|
2167
2248
|
};
|
|
2168
2249
|
}
|
|
2169
2250
|
}
|
|
2251
|
+
function buildPimlicoRpcUrl(chain, apiKey) {
|
|
2252
|
+
const slug = chain.name.toLowerCase().replace(/\s+/g, "-");
|
|
2253
|
+
return `https://api.pimlico.io/v2/${slug}/rpc?apikey=${apiKey}`;
|
|
2254
|
+
}
|
|
2255
|
+
async function createPimlicoDirectState(params) {
|
|
2256
|
+
const { createSmartAccountClient } = await import("permissionless");
|
|
2257
|
+
const { toSimpleSmartAccount } = await import("permissionless/accounts");
|
|
2258
|
+
const { createPimlicoClient } = await import("permissionless/clients/pimlico");
|
|
2259
|
+
const { createPublicClient, http } = await import("viem");
|
|
2260
|
+
const { entryPoint07Address } = await import("viem/account-abstraction");
|
|
2261
|
+
const signer = (0, import_accounts3.privateKeyToAccount)(params.privateKey);
|
|
2262
|
+
const signerAddress = signer.address;
|
|
2263
|
+
const pimlicoRpcUrl = buildPimlicoRpcUrl(params.chain, params.apiKey);
|
|
2264
|
+
pimDebug("4337:start", {
|
|
2265
|
+
signerAddress,
|
|
2266
|
+
chainId: params.chain.id,
|
|
2267
|
+
pimlicoRpcUrl: pimlicoRpcUrl.replace(params.apiKey, "***")
|
|
2268
|
+
});
|
|
2269
|
+
const publicClient = createPublicClient({
|
|
2270
|
+
chain: params.chain,
|
|
2271
|
+
transport: http(params.rpcUrl)
|
|
2272
|
+
});
|
|
2273
|
+
const paymasterClient = createPimlicoClient({
|
|
2274
|
+
entryPoint: { address: entryPoint07Address, version: "0.7" },
|
|
2275
|
+
transport: http(pimlicoRpcUrl)
|
|
2276
|
+
});
|
|
2277
|
+
const smartAccount = await toSimpleSmartAccount({
|
|
2278
|
+
client: publicClient,
|
|
2279
|
+
owner: signer,
|
|
2280
|
+
entryPoint: { address: entryPoint07Address, version: "0.7" }
|
|
2281
|
+
});
|
|
2282
|
+
const accountAddress = smartAccount.address;
|
|
2283
|
+
pimDebug("4337:account-created", {
|
|
2284
|
+
signerAddress,
|
|
2285
|
+
accountAddress
|
|
2286
|
+
});
|
|
2287
|
+
const smartAccountClient = createSmartAccountClient({
|
|
2288
|
+
account: smartAccount,
|
|
2289
|
+
chain: params.chain,
|
|
2290
|
+
paymaster: paymasterClient,
|
|
2291
|
+
bundlerTransport: http(pimlicoRpcUrl),
|
|
2292
|
+
userOperation: {
|
|
2293
|
+
estimateFeesPerGas: async () => {
|
|
2294
|
+
const gasPrice = await paymasterClient.getUserOperationGasPrice();
|
|
2295
|
+
return gasPrice.fast;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
});
|
|
2299
|
+
const sendCalls = async (calls) => {
|
|
2300
|
+
pimDebug("4337:send:start", {
|
|
2301
|
+
accountAddress,
|
|
2302
|
+
chainId: params.chain.id,
|
|
2303
|
+
callCount: calls.length
|
|
2304
|
+
});
|
|
2305
|
+
const hash = await smartAccountClient.sendTransaction({
|
|
2306
|
+
account: smartAccount,
|
|
2307
|
+
calls: calls.map((c) => {
|
|
2308
|
+
var _a;
|
|
2309
|
+
return {
|
|
2310
|
+
to: c.to,
|
|
2311
|
+
value: c.value,
|
|
2312
|
+
data: (_a = c.data) != null ? _a : "0x"
|
|
2313
|
+
};
|
|
2314
|
+
})
|
|
2315
|
+
});
|
|
2316
|
+
pimDebug("4337:send:userOpHash", { hash });
|
|
2317
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
2318
|
+
hash
|
|
2319
|
+
});
|
|
2320
|
+
pimDebug("4337:send:confirmed", {
|
|
2321
|
+
transactionHash: receipt.transactionHash,
|
|
2322
|
+
status: receipt.status
|
|
2323
|
+
});
|
|
2324
|
+
return { transactionHash: receipt.transactionHash };
|
|
2325
|
+
};
|
|
2326
|
+
const account = {
|
|
2327
|
+
provider: "pimlico",
|
|
2328
|
+
mode: "4337",
|
|
2329
|
+
AAAddress: accountAddress,
|
|
2330
|
+
sendTransaction: async (call) => sendCalls([call]),
|
|
2331
|
+
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
2332
|
+
};
|
|
2333
|
+
return {
|
|
2334
|
+
resolved: params.resolved,
|
|
2335
|
+
account,
|
|
2336
|
+
pending: false,
|
|
2337
|
+
error: null
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2170
2340
|
|
|
2171
2341
|
// src/aa/create.ts
|
|
2172
2342
|
async function createAAProviderState(options) {
|
|
@@ -2179,7 +2349,8 @@ async function createAAProviderState(options) {
|
|
|
2179
2349
|
mode: options.mode,
|
|
2180
2350
|
apiKey: options.apiKey,
|
|
2181
2351
|
gasPolicyId: options.gasPolicyId,
|
|
2182
|
-
sponsored: options.sponsored
|
|
2352
|
+
sponsored: options.sponsored,
|
|
2353
|
+
proxyBaseUrl: options.proxyBaseUrl
|
|
2183
2354
|
});
|
|
2184
2355
|
}
|
|
2185
2356
|
return createPimlicoAAState({
|
|
@@ -2211,16 +2382,12 @@ async function createAAProviderState(options) {
|
|
|
2211
2382
|
isAlchemySponsorshipLimitError,
|
|
2212
2383
|
isAsyncCallback,
|
|
2213
2384
|
isInlineCall,
|
|
2214
|
-
isProviderConfigured,
|
|
2215
2385
|
isSystemError,
|
|
2216
2386
|
isSystemNotice,
|
|
2217
2387
|
normalizeEip712Payload,
|
|
2218
2388
|
normalizeTxPayload,
|
|
2219
|
-
parseAAConfig,
|
|
2220
|
-
readEnv,
|
|
2221
|
-
resolveAlchemyConfig,
|
|
2222
|
-
resolveDefaultProvider,
|
|
2223
2389
|
resolvePimlicoConfig,
|
|
2390
|
+
toAAWalletCall,
|
|
2224
2391
|
toViemSignTypedDataArgs,
|
|
2225
2392
|
unwrapSystemEvent
|
|
2226
2393
|
});
|