@aomi-labs/client 0.1.22 → 0.1.23
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 +2461 -2750
- 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.md +144 -11
- 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.js
CHANGED
|
@@ -613,14 +613,11 @@ function isAsyncCallback(event) {
|
|
|
613
613
|
return "AsyncCallback" in event;
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
// src/event
|
|
616
|
+
// src/event.ts
|
|
617
617
|
var TypedEventEmitter = class {
|
|
618
618
|
constructor() {
|
|
619
619
|
this.listeners = /* @__PURE__ */ new Map();
|
|
620
620
|
}
|
|
621
|
-
/**
|
|
622
|
-
* Subscribe to an event type. Returns an unsubscribe function.
|
|
623
|
-
*/
|
|
624
621
|
on(type, handler) {
|
|
625
622
|
let set = this.listeners.get(type);
|
|
626
623
|
if (!set) {
|
|
@@ -635,9 +632,6 @@ var TypedEventEmitter = class {
|
|
|
635
632
|
}
|
|
636
633
|
};
|
|
637
634
|
}
|
|
638
|
-
/**
|
|
639
|
-
* Subscribe to an event type for a single emission, then auto-unsubscribe.
|
|
640
|
-
*/
|
|
641
635
|
once(type, handler) {
|
|
642
636
|
const wrapper = ((payload) => {
|
|
643
637
|
unsub();
|
|
@@ -646,9 +640,6 @@ var TypedEventEmitter = class {
|
|
|
646
640
|
const unsub = this.on(type, wrapper);
|
|
647
641
|
return unsub;
|
|
648
642
|
}
|
|
649
|
-
/**
|
|
650
|
-
* Emit an event to all listeners of `type` and wildcard `"*"` listeners.
|
|
651
|
-
*/
|
|
652
643
|
emit(type, payload) {
|
|
653
644
|
const typeSet = this.listeners.get(type);
|
|
654
645
|
if (typeSet) {
|
|
@@ -665,9 +656,6 @@ var TypedEventEmitter = class {
|
|
|
665
656
|
}
|
|
666
657
|
}
|
|
667
658
|
}
|
|
668
|
-
/**
|
|
669
|
-
* Remove a specific handler from an event type.
|
|
670
|
-
*/
|
|
671
659
|
off(type, handler) {
|
|
672
660
|
const set = this.listeners.get(type);
|
|
673
661
|
if (set) {
|
|
@@ -677,15 +665,10 @@ var TypedEventEmitter = class {
|
|
|
677
665
|
}
|
|
678
666
|
}
|
|
679
667
|
}
|
|
680
|
-
/**
|
|
681
|
-
* Remove all listeners for all event types.
|
|
682
|
-
*/
|
|
683
668
|
removeAllListeners() {
|
|
684
669
|
this.listeners.clear();
|
|
685
670
|
}
|
|
686
671
|
};
|
|
687
|
-
|
|
688
|
-
// src/event-unwrap.ts
|
|
689
672
|
function unwrapSystemEvent(event) {
|
|
690
673
|
var _a;
|
|
691
674
|
if (isInlineCall(event)) {
|
|
@@ -786,6 +769,15 @@ function normalizeEip712Payload(payload) {
|
|
|
786
769
|
const description = typeof args.description === "string" ? args.description : void 0;
|
|
787
770
|
return { typed_data: typedData, description };
|
|
788
771
|
}
|
|
772
|
+
function toAAWalletCall(payload, defaultChainId = 1) {
|
|
773
|
+
var _a, _b;
|
|
774
|
+
return {
|
|
775
|
+
to: payload.to,
|
|
776
|
+
value: BigInt((_a = payload.value) != null ? _a : "0"),
|
|
777
|
+
data: payload.data ? payload.data : void 0,
|
|
778
|
+
chainId: (_b = payload.chainId) != null ? _b : defaultChainId
|
|
779
|
+
};
|
|
780
|
+
}
|
|
789
781
|
function toViemSignTypedDataArgs(payload) {
|
|
790
782
|
var _a;
|
|
791
783
|
const typedData = payload.typed_data;
|
|
@@ -1074,8 +1066,37 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1074
1066
|
return state;
|
|
1075
1067
|
}
|
|
1076
1068
|
// ===========================================================================
|
|
1077
|
-
//
|
|
1069
|
+
// Public API — Polling Control
|
|
1078
1070
|
// ===========================================================================
|
|
1071
|
+
/** Whether the session is currently polling for state updates. */
|
|
1072
|
+
getIsPolling() {
|
|
1073
|
+
return this.pollTimer !== null;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Fetch the current state from the backend (one-shot).
|
|
1077
|
+
* Automatically starts polling if the backend is processing.
|
|
1078
|
+
*/
|
|
1079
|
+
async fetchCurrentState() {
|
|
1080
|
+
this.assertOpen();
|
|
1081
|
+
const state = await this.client.fetchState(
|
|
1082
|
+
this.sessionId,
|
|
1083
|
+
this.userState,
|
|
1084
|
+
this.clientId
|
|
1085
|
+
);
|
|
1086
|
+
this.assertUserStateAligned(state.user_state);
|
|
1087
|
+
this.applyState(state);
|
|
1088
|
+
if (state.is_processing && !this.pollTimer) {
|
|
1089
|
+
this._isProcessing = true;
|
|
1090
|
+
this.emit("processing_start", void 0);
|
|
1091
|
+
this.startPolling();
|
|
1092
|
+
} else if (!state.is_processing) {
|
|
1093
|
+
this._isProcessing = false;
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Start polling for state updates. Idempotent — no-op if already polling.
|
|
1098
|
+
* Useful for resuming polling after resolving a wallet request.
|
|
1099
|
+
*/
|
|
1079
1100
|
startPolling() {
|
|
1080
1101
|
var _a;
|
|
1081
1102
|
if (this.pollTimer || this.closed) return;
|
|
@@ -1085,6 +1106,7 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1085
1106
|
void this.pollTick();
|
|
1086
1107
|
}, this.pollIntervalMs);
|
|
1087
1108
|
}
|
|
1109
|
+
/** Stop polling for state updates. Idempotent — no-op if not polling. */
|
|
1088
1110
|
stopPolling() {
|
|
1089
1111
|
var _a;
|
|
1090
1112
|
if (this.pollTimer) {
|
|
@@ -1216,79 +1238,14 @@ var ClientSession = class extends TypedEventEmitter {
|
|
|
1216
1238
|
if (!isSubsetMatch(this.userState, actualUserState)) {
|
|
1217
1239
|
const expected = JSON.stringify(sortJson(this.userState));
|
|
1218
1240
|
const actual = JSON.stringify(sortJson(actualUserState));
|
|
1219
|
-
|
|
1220
|
-
`Backend user_state mismatch. expected subset=${expected} actual=${actual}`
|
|
1241
|
+
console.warn(
|
|
1242
|
+
`[session] Backend user_state mismatch (non-fatal). expected subset=${expected} actual=${actual}`
|
|
1221
1243
|
);
|
|
1222
1244
|
}
|
|
1223
1245
|
}
|
|
1224
1246
|
};
|
|
1225
1247
|
|
|
1226
1248
|
// src/aa/types.ts
|
|
1227
|
-
var MODES = /* @__PURE__ */ new Set(["4337", "7702"]);
|
|
1228
|
-
var SPONSORSHIP_MODES = /* @__PURE__ */ new Set([
|
|
1229
|
-
"disabled",
|
|
1230
|
-
"optional",
|
|
1231
|
-
"required"
|
|
1232
|
-
]);
|
|
1233
|
-
function isObject(value) {
|
|
1234
|
-
return typeof value === "object" && value !== null;
|
|
1235
|
-
}
|
|
1236
|
-
function assertChainConfig(value, index) {
|
|
1237
|
-
if (!isObject(value)) {
|
|
1238
|
-
throw new Error(`Invalid AA config chain at index ${index}: expected object`);
|
|
1239
|
-
}
|
|
1240
|
-
if (typeof value.chainId !== "number") {
|
|
1241
|
-
throw new Error(`Invalid AA config chain at index ${index}: chainId must be a number`);
|
|
1242
|
-
}
|
|
1243
|
-
if (typeof value.enabled !== "boolean") {
|
|
1244
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: enabled must be a boolean`);
|
|
1245
|
-
}
|
|
1246
|
-
if (!MODES.has(value.defaultMode)) {
|
|
1247
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: unsupported defaultMode`);
|
|
1248
|
-
}
|
|
1249
|
-
if (!Array.isArray(value.supportedModes) || value.supportedModes.length === 0) {
|
|
1250
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: supportedModes must be a non-empty array`);
|
|
1251
|
-
}
|
|
1252
|
-
if (!value.supportedModes.every((mode) => MODES.has(mode))) {
|
|
1253
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: supportedModes contains an unsupported mode`);
|
|
1254
|
-
}
|
|
1255
|
-
if (!value.supportedModes.includes(value.defaultMode)) {
|
|
1256
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: defaultMode must be in supportedModes`);
|
|
1257
|
-
}
|
|
1258
|
-
if (typeof value.allowBatching !== "boolean") {
|
|
1259
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: allowBatching must be a boolean`);
|
|
1260
|
-
}
|
|
1261
|
-
if (!SPONSORSHIP_MODES.has(value.sponsorship)) {
|
|
1262
|
-
throw new Error(`Invalid AA config chain ${value.chainId}: unsupported sponsorship mode`);
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
function parseAAConfig(value) {
|
|
1266
|
-
if (!isObject(value)) {
|
|
1267
|
-
throw new Error("Invalid AA config: expected object");
|
|
1268
|
-
}
|
|
1269
|
-
if (typeof value.enabled !== "boolean") {
|
|
1270
|
-
throw new Error("Invalid AA config: enabled must be a boolean");
|
|
1271
|
-
}
|
|
1272
|
-
if (typeof value.provider !== "string" || !value.provider) {
|
|
1273
|
-
throw new Error("Invalid AA config: provider must be a non-empty string");
|
|
1274
|
-
}
|
|
1275
|
-
if (value.provider !== "alchemy" && value.provider !== "pimlico") {
|
|
1276
|
-
throw new Error('Invalid AA config: provider must be either "alchemy" or "pimlico"');
|
|
1277
|
-
}
|
|
1278
|
-
if (typeof value.fallbackToEoa !== "boolean") {
|
|
1279
|
-
throw new Error("Invalid AA config: fallbackToEoa must be a boolean");
|
|
1280
|
-
}
|
|
1281
|
-
if (!Array.isArray(value.chains)) {
|
|
1282
|
-
throw new Error("Invalid AA config: chains must be an array");
|
|
1283
|
-
}
|
|
1284
|
-
value.chains.forEach((chain, index) => assertChainConfig(chain, index));
|
|
1285
|
-
return {
|
|
1286
|
-
enabled: value.enabled,
|
|
1287
|
-
provider: value.provider,
|
|
1288
|
-
fallbackToEoa: value.fallbackToEoa,
|
|
1289
|
-
chains: value.chains
|
|
1290
|
-
};
|
|
1291
|
-
}
|
|
1292
1249
|
function getAAChainConfig(config, calls, chainsById) {
|
|
1293
1250
|
if (!config.enabled || calls.length === 0) {
|
|
1294
1251
|
return null;
|
|
@@ -1327,13 +1284,6 @@ function buildAAExecutionPlan(config, chainConfig) {
|
|
|
1327
1284
|
function getWalletExecutorReady(providerState) {
|
|
1328
1285
|
return !providerState.resolved || !providerState.pending && (Boolean(providerState.account) || Boolean(providerState.error) || providerState.resolved.fallbackToEoa);
|
|
1329
1286
|
}
|
|
1330
|
-
function mapCall(call) {
|
|
1331
|
-
return {
|
|
1332
|
-
to: call.to,
|
|
1333
|
-
value: BigInt(call.value),
|
|
1334
|
-
data: call.data ? call.data : void 0
|
|
1335
|
-
};
|
|
1336
|
-
}
|
|
1337
1287
|
var DEFAULT_AA_CONFIG = {
|
|
1338
1288
|
enabled: true,
|
|
1339
1289
|
provider: "alchemy",
|
|
@@ -1381,6 +1331,27 @@ var DEFAULT_AA_CONFIG = {
|
|
|
1381
1331
|
}
|
|
1382
1332
|
]
|
|
1383
1333
|
};
|
|
1334
|
+
|
|
1335
|
+
// src/chains.ts
|
|
1336
|
+
import { mainnet, polygon, arbitrum, optimism, base, sepolia } from "viem/chains";
|
|
1337
|
+
var ALCHEMY_CHAIN_SLUGS = {
|
|
1338
|
+
1: "eth-mainnet",
|
|
1339
|
+
137: "polygon-mainnet",
|
|
1340
|
+
42161: "arb-mainnet",
|
|
1341
|
+
8453: "base-mainnet",
|
|
1342
|
+
10: "opt-mainnet",
|
|
1343
|
+
11155111: "eth-sepolia"
|
|
1344
|
+
};
|
|
1345
|
+
var CHAINS_BY_ID = {
|
|
1346
|
+
1: mainnet,
|
|
1347
|
+
137: polygon,
|
|
1348
|
+
42161: arbitrum,
|
|
1349
|
+
10: optimism,
|
|
1350
|
+
8453: base,
|
|
1351
|
+
11155111: sepolia
|
|
1352
|
+
};
|
|
1353
|
+
|
|
1354
|
+
// src/aa/execute.ts
|
|
1384
1355
|
async function executeWalletCalls(params) {
|
|
1385
1356
|
const {
|
|
1386
1357
|
callList,
|
|
@@ -1419,7 +1390,7 @@ async function executeViaAA(callList, providerState) {
|
|
|
1419
1390
|
if (!account || !resolved) {
|
|
1420
1391
|
throw (_a = providerState.error) != null ? _a : new Error("smart_account_unavailable");
|
|
1421
1392
|
}
|
|
1422
|
-
const callsPayload = callList.map(
|
|
1393
|
+
const callsPayload = callList.map(({ to, value, data }) => ({ to, value, data }));
|
|
1423
1394
|
const receipt = callList.length > 1 ? await account.sendBatchTransaction(callsPayload) : await account.sendTransaction(callsPayload[0]);
|
|
1424
1395
|
const txHash = receipt.transactionHash;
|
|
1425
1396
|
const providerPrefix = account.provider.toLowerCase();
|
|
@@ -1443,15 +1414,7 @@ async function resolve7702Delegation(txHash, callList) {
|
|
|
1443
1414
|
const { createPublicClient, http } = await import("viem");
|
|
1444
1415
|
const chainId = (_a = callList[0]) == null ? void 0 : _a.chainId;
|
|
1445
1416
|
if (!chainId) return void 0;
|
|
1446
|
-
const
|
|
1447
|
-
const knownChains = {
|
|
1448
|
-
1: mainnet,
|
|
1449
|
-
137: polygon,
|
|
1450
|
-
42161: arbitrum,
|
|
1451
|
-
10: optimism,
|
|
1452
|
-
8453: base
|
|
1453
|
-
};
|
|
1454
|
-
const chain = knownChains[chainId];
|
|
1417
|
+
const chain = CHAINS_BY_ID[chainId];
|
|
1455
1418
|
if (!chain) return void 0;
|
|
1456
1419
|
const client = createPublicClient({ chain, transport: http() });
|
|
1457
1420
|
const tx = await client.getTransaction({ hash: txHash });
|
|
@@ -1477,7 +1440,7 @@ async function executeViaEoa({
|
|
|
1477
1440
|
}) {
|
|
1478
1441
|
var _a, _b;
|
|
1479
1442
|
const { createPublicClient, createWalletClient, http } = await import("viem");
|
|
1480
|
-
const { privateKeyToAccount:
|
|
1443
|
+
const { privateKeyToAccount: privateKeyToAccount4 } = await import("viem/accounts");
|
|
1481
1444
|
const hashes = [];
|
|
1482
1445
|
if (localPrivateKey) {
|
|
1483
1446
|
for (const call of callList) {
|
|
@@ -1489,7 +1452,7 @@ async function executeViaEoa({
|
|
|
1489
1452
|
if (!rpcUrl) {
|
|
1490
1453
|
throw new Error(`No RPC for chain ${call.chainId}`);
|
|
1491
1454
|
}
|
|
1492
|
-
const account =
|
|
1455
|
+
const account = privateKeyToAccount4(localPrivateKey);
|
|
1493
1456
|
const walletClient = createWalletClient({
|
|
1494
1457
|
account,
|
|
1495
1458
|
chain,
|
|
@@ -1498,8 +1461,8 @@ async function executeViaEoa({
|
|
|
1498
1461
|
const hash = await walletClient.sendTransaction({
|
|
1499
1462
|
account,
|
|
1500
1463
|
to: call.to,
|
|
1501
|
-
value:
|
|
1502
|
-
data: call.data
|
|
1464
|
+
value: call.value,
|
|
1465
|
+
data: call.data
|
|
1503
1466
|
});
|
|
1504
1467
|
const publicClient = createPublicClient({
|
|
1505
1468
|
chain,
|
|
@@ -1529,7 +1492,7 @@ async function executeViaEoa({
|
|
|
1529
1492
|
const canUseSendCalls = atomicStatus === "supported" || atomicStatus === "ready";
|
|
1530
1493
|
if (canUseSendCalls) {
|
|
1531
1494
|
const batchResult = await sendCallsSyncAsync({
|
|
1532
|
-
calls: callList.map(
|
|
1495
|
+
calls: callList.map(({ to, value, data }) => ({ to, value, data })),
|
|
1533
1496
|
capabilities: {
|
|
1534
1497
|
atomic: {
|
|
1535
1498
|
required: true
|
|
@@ -1547,8 +1510,8 @@ async function executeViaEoa({
|
|
|
1547
1510
|
const hash = await sendTransactionAsync({
|
|
1548
1511
|
chainId: call.chainId,
|
|
1549
1512
|
to: call.to,
|
|
1550
|
-
value:
|
|
1551
|
-
data: call.data
|
|
1513
|
+
value: call.value,
|
|
1514
|
+
data: call.data
|
|
1552
1515
|
});
|
|
1553
1516
|
hashes.push(hash);
|
|
1554
1517
|
}
|
|
@@ -1562,136 +1525,28 @@ async function executeViaEoa({
|
|
|
1562
1525
|
};
|
|
1563
1526
|
}
|
|
1564
1527
|
|
|
1565
|
-
// src/aa/alchemy/
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
"ALCHEMY_GAS_POLICY_ID",
|
|
1572
|
-
"NEXT_PUBLIC_ALCHEMY_GAS_POLICY_ID"
|
|
1573
|
-
];
|
|
1574
|
-
|
|
1575
|
-
// src/aa/pimlico/env.ts
|
|
1576
|
-
var PIMLICO_API_KEY_ENVS = [
|
|
1577
|
-
"PIMLICO_API_KEY",
|
|
1578
|
-
"NEXT_PUBLIC_PIMLICO_API_KEY"
|
|
1579
|
-
];
|
|
1580
|
-
|
|
1581
|
-
// src/aa/env.ts
|
|
1582
|
-
function readEnv(candidates, options = {}) {
|
|
1583
|
-
var _a;
|
|
1584
|
-
const { publicOnly = false } = options;
|
|
1585
|
-
for (const name of candidates) {
|
|
1586
|
-
if (publicOnly && !name.startsWith("NEXT_PUBLIC_")) {
|
|
1587
|
-
continue;
|
|
1588
|
-
}
|
|
1589
|
-
const value = (_a = process.env[name]) == null ? void 0 : _a.trim();
|
|
1590
|
-
if (value) return value;
|
|
1591
|
-
}
|
|
1592
|
-
return void 0;
|
|
1593
|
-
}
|
|
1594
|
-
function readGasPolicyEnv(chainId, chainSlugById, baseCandidates, options = {}) {
|
|
1595
|
-
const slug = chainSlugById[chainId];
|
|
1596
|
-
if (slug) {
|
|
1597
|
-
const chainSpecific = baseCandidates.map(
|
|
1598
|
-
(base) => `${base}_${slug.toUpperCase()}`
|
|
1599
|
-
);
|
|
1600
|
-
const found = readEnv(chainSpecific, options);
|
|
1601
|
-
if (found) return found;
|
|
1602
|
-
}
|
|
1603
|
-
return readEnv(baseCandidates, options);
|
|
1604
|
-
}
|
|
1605
|
-
function isProviderConfigured(provider, options = {}) {
|
|
1606
|
-
return provider === "alchemy" ? Boolean(readEnv(ALCHEMY_API_KEY_ENVS, options)) : Boolean(readEnv(PIMLICO_API_KEY_ENVS, options));
|
|
1607
|
-
}
|
|
1608
|
-
function resolveDefaultProvider(options = {}) {
|
|
1609
|
-
if (isProviderConfigured("alchemy", options)) return "alchemy";
|
|
1610
|
-
if (isProviderConfigured("pimlico", options)) return "pimlico";
|
|
1611
|
-
throw new Error(
|
|
1612
|
-
"AA requires provider credentials. Set ALCHEMY_API_KEY or PIMLICO_API_KEY, or use --eoa."
|
|
1613
|
-
);
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
|
-
// src/aa/alchemy/resolve.ts
|
|
1617
|
-
function resolveAlchemyConfig(options) {
|
|
1618
|
-
const {
|
|
1619
|
-
calls,
|
|
1620
|
-
localPrivateKey,
|
|
1621
|
-
accountAbstractionConfig = DEFAULT_AA_CONFIG,
|
|
1622
|
-
chainsById,
|
|
1623
|
-
chainSlugById = {},
|
|
1624
|
-
getPreferredRpcUrl = (chain2) => {
|
|
1625
|
-
var _a;
|
|
1626
|
-
return (_a = chain2.rpcUrls.default.http[0]) != null ? _a : "";
|
|
1627
|
-
},
|
|
1628
|
-
modeOverride,
|
|
1629
|
-
publicOnly = false,
|
|
1630
|
-
throwOnMissingConfig = false,
|
|
1631
|
-
apiKey: preResolvedApiKey,
|
|
1632
|
-
gasPolicyId: preResolvedGasPolicyId
|
|
1633
|
-
} = options;
|
|
1634
|
-
if (!calls || localPrivateKey) {
|
|
1635
|
-
return null;
|
|
1636
|
-
}
|
|
1637
|
-
const config = __spreadProps(__spreadValues({}, accountAbstractionConfig), {
|
|
1638
|
-
provider: "alchemy"
|
|
1639
|
-
});
|
|
1528
|
+
// src/aa/alchemy/provider.ts
|
|
1529
|
+
function resolveForHook(params) {
|
|
1530
|
+
var _a, _b;
|
|
1531
|
+
const { calls, localPrivateKey, accountAbstractionConfig, chainsById, getPreferredRpcUrl } = params;
|
|
1532
|
+
if (!calls || localPrivateKey) return null;
|
|
1533
|
+
const config = __spreadProps(__spreadValues({}, accountAbstractionConfig), { provider: "alchemy" });
|
|
1640
1534
|
const chainConfig = getAAChainConfig(config, calls, chainsById);
|
|
1641
|
-
if (!chainConfig)
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
throw new Error(
|
|
1645
|
-
`AA is not configured for chain ${chainIds[0]}, or batching is disabled for that chain.`
|
|
1646
|
-
);
|
|
1647
|
-
}
|
|
1648
|
-
return null;
|
|
1649
|
-
}
|
|
1650
|
-
const apiKey = preResolvedApiKey != null ? preResolvedApiKey : readEnv(ALCHEMY_API_KEY_ENVS, { publicOnly });
|
|
1651
|
-
if (!apiKey) {
|
|
1652
|
-
if (throwOnMissingConfig) {
|
|
1653
|
-
throw new Error("Alchemy AA requires ALCHEMY_API_KEY.");
|
|
1654
|
-
}
|
|
1655
|
-
return null;
|
|
1656
|
-
}
|
|
1535
|
+
if (!chainConfig) return null;
|
|
1536
|
+
const apiKey = (_a = process.env.NEXT_PUBLIC_ALCHEMY_API_KEY) == null ? void 0 : _a.trim();
|
|
1537
|
+
if (!apiKey) return null;
|
|
1657
1538
|
const chain = chainsById[chainConfig.chainId];
|
|
1658
|
-
if (!chain)
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
const gasPolicyId = preResolvedGasPolicyId != null ? preResolvedGasPolicyId : readGasPolicyEnv(
|
|
1662
|
-
chainConfig.chainId,
|
|
1663
|
-
chainSlugById,
|
|
1664
|
-
ALCHEMY_GAS_POLICY_ENVS,
|
|
1665
|
-
{ publicOnly }
|
|
1666
|
-
);
|
|
1667
|
-
if (chainConfig.sponsorship === "required" && !gasPolicyId) {
|
|
1668
|
-
if (throwOnMissingConfig) {
|
|
1669
|
-
throw new Error(
|
|
1670
|
-
`Alchemy gas policy required for chain ${chainConfig.chainId} but not configured.`
|
|
1671
|
-
);
|
|
1672
|
-
}
|
|
1673
|
-
return null;
|
|
1674
|
-
}
|
|
1675
|
-
if (modeOverride && !chainConfig.supportedModes.includes(modeOverride)) {
|
|
1676
|
-
if (throwOnMissingConfig) {
|
|
1677
|
-
throw new Error(
|
|
1678
|
-
`AA mode "${modeOverride}" is not supported on chain ${chainConfig.chainId}.`
|
|
1679
|
-
);
|
|
1680
|
-
}
|
|
1681
|
-
return null;
|
|
1682
|
-
}
|
|
1683
|
-
const resolvedChainConfig = modeOverride ? __spreadProps(__spreadValues({}, chainConfig), { defaultMode: modeOverride }) : chainConfig;
|
|
1684
|
-
const resolved = buildAAExecutionPlan(config, resolvedChainConfig);
|
|
1539
|
+
if (!chain) return null;
|
|
1540
|
+
const gasPolicyId = (_b = process.env.NEXT_PUBLIC_ALCHEMY_GAS_POLICY_ID) == null ? void 0 : _b.trim();
|
|
1541
|
+
const resolved = buildAAExecutionPlan(config, chainConfig);
|
|
1685
1542
|
return __spreadProps(__spreadValues({}, resolved), {
|
|
1686
1543
|
apiKey,
|
|
1687
1544
|
chain,
|
|
1688
1545
|
rpcUrl: getPreferredRpcUrl(chain),
|
|
1689
1546
|
gasPolicyId,
|
|
1690
|
-
mode:
|
|
1547
|
+
mode: chainConfig.defaultMode
|
|
1691
1548
|
});
|
|
1692
1549
|
}
|
|
1693
|
-
|
|
1694
|
-
// src/aa/alchemy/provider.ts
|
|
1695
1550
|
function createAlchemyAAProvider({
|
|
1696
1551
|
accountAbstractionConfig = DEFAULT_AA_CONFIG,
|
|
1697
1552
|
useAlchemyAA,
|
|
@@ -1701,14 +1556,13 @@ function createAlchemyAAProvider({
|
|
|
1701
1556
|
}) {
|
|
1702
1557
|
return function useAlchemyAAProvider(calls, localPrivateKey) {
|
|
1703
1558
|
var _a;
|
|
1704
|
-
const resolved =
|
|
1559
|
+
const resolved = resolveForHook({
|
|
1705
1560
|
calls,
|
|
1706
1561
|
localPrivateKey,
|
|
1707
1562
|
accountAbstractionConfig,
|
|
1708
1563
|
chainsById,
|
|
1709
1564
|
chainSlugById,
|
|
1710
|
-
getPreferredRpcUrl
|
|
1711
|
-
publicOnly: true
|
|
1565
|
+
getPreferredRpcUrl
|
|
1712
1566
|
});
|
|
1713
1567
|
const params = resolved ? {
|
|
1714
1568
|
enabled: true,
|
|
@@ -1823,32 +1677,69 @@ function getUnsupportedAdapterState(resolved, adapter) {
|
|
|
1823
1677
|
|
|
1824
1678
|
// src/aa/alchemy/create.ts
|
|
1825
1679
|
var ALCHEMY_7702_DELEGATION_ADDRESS = "0x69007702764179f14F51cdce752f4f775d74E139";
|
|
1680
|
+
var AA_DEBUG_ENABLED = process.env.AOMI_AA_DEBUG === "1";
|
|
1681
|
+
var EIP_7702_AUTH_GAS_OVERHEAD = BigInt(25e3);
|
|
1682
|
+
function alchemyRpcUrl(chainId, apiKey) {
|
|
1683
|
+
var _a;
|
|
1684
|
+
const slug = (_a = ALCHEMY_CHAIN_SLUGS[chainId]) != null ? _a : "eth-mainnet";
|
|
1685
|
+
return `https://${slug}.g.alchemy.com/v2/${apiKey}`;
|
|
1686
|
+
}
|
|
1687
|
+
function aaDebug(message, fields) {
|
|
1688
|
+
if (!AA_DEBUG_ENABLED) return;
|
|
1689
|
+
if (fields) {
|
|
1690
|
+
console.debug(`[aomi][aa][alchemy] ${message}`, fields);
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
console.debug(`[aomi][aa][alchemy] ${message}`);
|
|
1694
|
+
}
|
|
1695
|
+
function extractExistingAccountAddress(error) {
|
|
1696
|
+
var _a;
|
|
1697
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1698
|
+
const match = message.match(/Account with address (0x[a-fA-F0-9]{40}) already exists/);
|
|
1699
|
+
return (_a = match == null ? void 0 : match[1]) != null ? _a : null;
|
|
1700
|
+
}
|
|
1701
|
+
function deriveAlchemy4337AccountId(address) {
|
|
1702
|
+
var _a;
|
|
1703
|
+
const hex = address.toLowerCase().slice(2).padEnd(32, "0").slice(0, 32).split("");
|
|
1704
|
+
const namespace = ["4", "3", "3", "7", "5", "a", "a", "b"];
|
|
1705
|
+
for (let i = 0; i < namespace.length; i += 1) {
|
|
1706
|
+
hex[i] = namespace[i];
|
|
1707
|
+
}
|
|
1708
|
+
hex[12] = "4";
|
|
1709
|
+
const variant = Number.parseInt((_a = hex[16]) != null ? _a : "0", 16);
|
|
1710
|
+
hex[16] = (variant & 3 | 8).toString(16);
|
|
1711
|
+
return [
|
|
1712
|
+
hex.slice(0, 8).join(""),
|
|
1713
|
+
hex.slice(8, 12).join(""),
|
|
1714
|
+
hex.slice(12, 16).join(""),
|
|
1715
|
+
hex.slice(16, 20).join(""),
|
|
1716
|
+
hex.slice(20, 32).join("")
|
|
1717
|
+
].join("-");
|
|
1718
|
+
}
|
|
1826
1719
|
async function createAlchemyAAState(options) {
|
|
1827
1720
|
var _a, _b;
|
|
1828
1721
|
const {
|
|
1829
1722
|
chain,
|
|
1830
1723
|
owner,
|
|
1831
|
-
rpcUrl,
|
|
1832
1724
|
callList,
|
|
1833
1725
|
mode,
|
|
1834
1726
|
sponsored = true
|
|
1835
1727
|
} = options;
|
|
1836
|
-
const
|
|
1837
|
-
|
|
1838
|
-
chainsById: { [chain.id]: chain },
|
|
1839
|
-
modeOverride: mode,
|
|
1840
|
-
throwOnMissingConfig: true,
|
|
1841
|
-
getPreferredRpcUrl: () => rpcUrl,
|
|
1842
|
-
apiKey: options.apiKey,
|
|
1843
|
-
gasPolicyId: options.gasPolicyId
|
|
1728
|
+
const chainConfig = getAAChainConfig(DEFAULT_AA_CONFIG, callList, {
|
|
1729
|
+
[chain.id]: chain
|
|
1844
1730
|
});
|
|
1845
|
-
if (!
|
|
1846
|
-
throw new Error(
|
|
1731
|
+
if (!chainConfig) {
|
|
1732
|
+
throw new Error(`AA is not configured for chain ${chain.id}.`);
|
|
1847
1733
|
}
|
|
1848
|
-
const
|
|
1849
|
-
const
|
|
1850
|
-
|
|
1851
|
-
|
|
1734
|
+
const effectiveMode = mode != null ? mode : chainConfig.defaultMode;
|
|
1735
|
+
const plan = buildAAExecutionPlan(
|
|
1736
|
+
__spreadProps(__spreadValues({}, DEFAULT_AA_CONFIG), { provider: "alchemy" }),
|
|
1737
|
+
__spreadProps(__spreadValues({}, chainConfig), { defaultMode: effectiveMode })
|
|
1738
|
+
);
|
|
1739
|
+
const gasPolicyId = sponsored ? (_b = options.gasPolicyId) != null ? _b : (_a = process.env.ALCHEMY_GAS_POLICY_ID) == null ? void 0 : _a.trim() : void 0;
|
|
1740
|
+
const execution = __spreadProps(__spreadValues({}, plan), {
|
|
1741
|
+
mode: effectiveMode,
|
|
1742
|
+
sponsorship: gasPolicyId ? plan.sponsorship : "disabled",
|
|
1852
1743
|
fallbackToEoa: false
|
|
1853
1744
|
});
|
|
1854
1745
|
const ownerParams = getOwnerParams(owner);
|
|
@@ -1859,15 +1750,16 @@ async function createAlchemyAAState(options) {
|
|
|
1859
1750
|
return getUnsupportedAdapterState(execution, ownerParams.adapter);
|
|
1860
1751
|
}
|
|
1861
1752
|
if (owner.kind === "direct") {
|
|
1753
|
+
const directParams = {
|
|
1754
|
+
resolved: execution,
|
|
1755
|
+
chain,
|
|
1756
|
+
privateKey: owner.privateKey,
|
|
1757
|
+
apiKey: options.apiKey,
|
|
1758
|
+
proxyBaseUrl: options.proxyBaseUrl,
|
|
1759
|
+
gasPolicyId
|
|
1760
|
+
};
|
|
1862
1761
|
try {
|
|
1863
|
-
return await
|
|
1864
|
-
resolved: execution,
|
|
1865
|
-
chain,
|
|
1866
|
-
privateKey: owner.privateKey,
|
|
1867
|
-
apiKey,
|
|
1868
|
-
gasPolicyId,
|
|
1869
|
-
mode: execution.mode
|
|
1870
|
-
});
|
|
1762
|
+
return await (execution.mode === "7702" ? createAlchemy7702State(directParams) : createAlchemy4337State(directParams));
|
|
1871
1763
|
} catch (error) {
|
|
1872
1764
|
return {
|
|
1873
1765
|
resolved: execution,
|
|
@@ -1877,13 +1769,23 @@ async function createAlchemyAAState(options) {
|
|
|
1877
1769
|
};
|
|
1878
1770
|
}
|
|
1879
1771
|
}
|
|
1772
|
+
if (!options.apiKey) {
|
|
1773
|
+
return {
|
|
1774
|
+
resolved: execution,
|
|
1775
|
+
account: null,
|
|
1776
|
+
pending: false,
|
|
1777
|
+
error: new Error(
|
|
1778
|
+
"Alchemy AA with session/adapter owner requires ALCHEMY_API_KEY."
|
|
1779
|
+
)
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1880
1782
|
try {
|
|
1881
1783
|
const { createAlchemySmartAccount } = await import("@getpara/aa-alchemy");
|
|
1882
1784
|
const smartAccount = await createAlchemySmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
1883
|
-
apiKey,
|
|
1785
|
+
apiKey: options.apiKey,
|
|
1884
1786
|
gasPolicyId,
|
|
1885
1787
|
chain,
|
|
1886
|
-
rpcUrl,
|
|
1788
|
+
rpcUrl: options.rpcUrl,
|
|
1887
1789
|
mode: execution.mode
|
|
1888
1790
|
}));
|
|
1889
1791
|
if (!smartAccount) {
|
|
@@ -1909,42 +1811,197 @@ async function createAlchemyAAState(options) {
|
|
|
1909
1811
|
};
|
|
1910
1812
|
}
|
|
1911
1813
|
}
|
|
1912
|
-
async function
|
|
1814
|
+
async function createAlchemy4337State(params) {
|
|
1913
1815
|
const { createSmartWalletClient, alchemyWalletTransport } = await import("@alchemy/wallet-apis");
|
|
1816
|
+
const transport = params.proxyBaseUrl ? alchemyWalletTransport({ url: params.proxyBaseUrl }) : alchemyWalletTransport({ apiKey: params.apiKey });
|
|
1914
1817
|
const signer = privateKeyToAccount2(params.privateKey);
|
|
1915
|
-
const
|
|
1916
|
-
transport
|
|
1818
|
+
const alchemyClient = createSmartWalletClient(__spreadValues({
|
|
1819
|
+
transport,
|
|
1917
1820
|
chain: params.chain,
|
|
1918
1821
|
signer
|
|
1919
1822
|
}, params.gasPolicyId ? { paymaster: { policyId: params.gasPolicyId } } : {}));
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1823
|
+
const signerAddress = signer.address;
|
|
1824
|
+
const accountId = deriveAlchemy4337AccountId(signerAddress);
|
|
1825
|
+
aaDebug("4337:requestAccount:start", {
|
|
1826
|
+
signerAddress,
|
|
1827
|
+
chainId: params.chain.id,
|
|
1828
|
+
accountId,
|
|
1829
|
+
hasGasPolicyId: Boolean(params.gasPolicyId)
|
|
1830
|
+
});
|
|
1831
|
+
let account;
|
|
1832
|
+
try {
|
|
1833
|
+
account = await alchemyClient.requestAccount({
|
|
1834
|
+
signerAddress,
|
|
1835
|
+
id: accountId,
|
|
1836
|
+
creationHint: {
|
|
1837
|
+
accountType: "sma-b",
|
|
1838
|
+
createAdditional: true
|
|
1839
|
+
}
|
|
1840
|
+
});
|
|
1841
|
+
} catch (error) {
|
|
1842
|
+
const existingAccountAddress = extractExistingAccountAddress(error);
|
|
1843
|
+
if (!existingAccountAddress) {
|
|
1844
|
+
throw error;
|
|
1845
|
+
}
|
|
1846
|
+
aaDebug("4337:requestAccount:existing-account", {
|
|
1847
|
+
existingAccountAddress
|
|
1848
|
+
});
|
|
1849
|
+
account = await alchemyClient.requestAccount({
|
|
1850
|
+
accountAddress: existingAccountAddress
|
|
1851
|
+
});
|
|
1924
1852
|
}
|
|
1853
|
+
const accountAddress = account.address;
|
|
1854
|
+
aaDebug("4337:requestAccount:done", { signerAddress, accountAddress });
|
|
1925
1855
|
const sendCalls = async (calls) => {
|
|
1926
|
-
var _a, _b;
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1856
|
+
var _a, _b, _c, _d;
|
|
1857
|
+
aaDebug("4337:sendCalls:start", {
|
|
1858
|
+
signerAddress,
|
|
1859
|
+
accountAddress,
|
|
1860
|
+
chainId: params.chain.id,
|
|
1861
|
+
callCount: calls.length,
|
|
1862
|
+
hasGasPolicyId: Boolean(params.gasPolicyId)
|
|
1863
|
+
});
|
|
1864
|
+
try {
|
|
1865
|
+
const result = await alchemyClient.sendCalls({
|
|
1866
|
+
account: accountAddress,
|
|
1867
|
+
calls
|
|
1868
|
+
});
|
|
1869
|
+
aaDebug("4337:sendCalls:submitted", { callId: result.id });
|
|
1870
|
+
const status = await alchemyClient.waitForCallsStatus({ id: result.id });
|
|
1871
|
+
const transactionHash = (_b = (_a = status.receipts) == null ? void 0 : _a[0]) == null ? void 0 : _b.transactionHash;
|
|
1872
|
+
aaDebug("4337:sendCalls:receipt", {
|
|
1873
|
+
callId: result.id,
|
|
1874
|
+
hasTransactionHash: Boolean(transactionHash),
|
|
1875
|
+
receipts: (_d = (_c = status.receipts) == null ? void 0 : _c.length) != null ? _d : 0
|
|
1876
|
+
});
|
|
1877
|
+
if (!transactionHash) {
|
|
1878
|
+
throw new Error("Alchemy Wallets API did not return a transaction hash.");
|
|
1879
|
+
}
|
|
1880
|
+
return { transactionHash };
|
|
1881
|
+
} catch (error) {
|
|
1882
|
+
aaDebug("4337:sendCalls:error", {
|
|
1883
|
+
signerAddress,
|
|
1884
|
+
accountAddress,
|
|
1885
|
+
chainId: params.chain.id,
|
|
1886
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1887
|
+
});
|
|
1888
|
+
throw error;
|
|
1934
1889
|
}
|
|
1935
|
-
return { transactionHash };
|
|
1936
1890
|
};
|
|
1937
|
-
const
|
|
1891
|
+
const smartAccount = {
|
|
1938
1892
|
provider: "alchemy",
|
|
1939
|
-
mode:
|
|
1893
|
+
mode: "4337",
|
|
1940
1894
|
AAAddress: accountAddress,
|
|
1941
|
-
delegationAddress: params.mode === "7702" ? ALCHEMY_7702_DELEGATION_ADDRESS : void 0,
|
|
1942
1895
|
sendTransaction: async (call) => sendCalls([call]),
|
|
1943
1896
|
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
1944
1897
|
};
|
|
1945
1898
|
return {
|
|
1946
1899
|
resolved: params.resolved,
|
|
1947
|
-
account,
|
|
1900
|
+
account: smartAccount,
|
|
1901
|
+
pending: false,
|
|
1902
|
+
error: null
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
async function createAlchemy7702State(params) {
|
|
1906
|
+
const { createWalletClient, createPublicClient, http } = await import("viem");
|
|
1907
|
+
const { encodeExecuteData } = await import("viem/experimental/erc7821");
|
|
1908
|
+
if (params.gasPolicyId) {
|
|
1909
|
+
aaDebug(
|
|
1910
|
+
"7702:gas-policy-ignored",
|
|
1911
|
+
{ gasPolicyId: params.gasPolicyId }
|
|
1912
|
+
);
|
|
1913
|
+
console.warn(
|
|
1914
|
+
"\u26A0\uFE0F Gas policy is not supported for raw EIP-7702 transactions. The signer's EOA pays gas directly."
|
|
1915
|
+
);
|
|
1916
|
+
}
|
|
1917
|
+
const signer = privateKeyToAccount2(params.privateKey);
|
|
1918
|
+
const signerAddress = signer.address;
|
|
1919
|
+
let rpcUrl;
|
|
1920
|
+
if (params.proxyBaseUrl) {
|
|
1921
|
+
rpcUrl = params.proxyBaseUrl;
|
|
1922
|
+
} else if (params.apiKey) {
|
|
1923
|
+
rpcUrl = alchemyRpcUrl(params.chain.id, params.apiKey);
|
|
1924
|
+
}
|
|
1925
|
+
const walletClient = createWalletClient({
|
|
1926
|
+
account: signer,
|
|
1927
|
+
chain: params.chain,
|
|
1928
|
+
transport: http(rpcUrl)
|
|
1929
|
+
});
|
|
1930
|
+
const publicClient = createPublicClient({
|
|
1931
|
+
chain: params.chain,
|
|
1932
|
+
transport: http(rpcUrl)
|
|
1933
|
+
});
|
|
1934
|
+
const send7702 = async (calls) => {
|
|
1935
|
+
aaDebug("7702:send:start", {
|
|
1936
|
+
signerAddress,
|
|
1937
|
+
chainId: params.chain.id,
|
|
1938
|
+
callCount: calls.length,
|
|
1939
|
+
calls: calls.map((call) => {
|
|
1940
|
+
var _a;
|
|
1941
|
+
return {
|
|
1942
|
+
to: call.to,
|
|
1943
|
+
value: call.value.toString(),
|
|
1944
|
+
data: (_a = call.data) != null ? _a : "0x"
|
|
1945
|
+
};
|
|
1946
|
+
})
|
|
1947
|
+
});
|
|
1948
|
+
const authorization = await walletClient.signAuthorization({
|
|
1949
|
+
contractAddress: ALCHEMY_7702_DELEGATION_ADDRESS
|
|
1950
|
+
});
|
|
1951
|
+
aaDebug("7702:authorization-signed", {
|
|
1952
|
+
contractAddress: ALCHEMY_7702_DELEGATION_ADDRESS
|
|
1953
|
+
});
|
|
1954
|
+
const data = encodeExecuteData({
|
|
1955
|
+
calls: calls.map((call) => {
|
|
1956
|
+
var _a;
|
|
1957
|
+
return {
|
|
1958
|
+
to: call.to,
|
|
1959
|
+
value: call.value,
|
|
1960
|
+
data: (_a = call.data) != null ? _a : "0x"
|
|
1961
|
+
};
|
|
1962
|
+
})
|
|
1963
|
+
});
|
|
1964
|
+
aaDebug("7702:calldata-encoded", { dataLength: data.length });
|
|
1965
|
+
const gasEstimate = await publicClient.estimateGas({
|
|
1966
|
+
account: signer,
|
|
1967
|
+
to: signerAddress,
|
|
1968
|
+
data,
|
|
1969
|
+
authorizationList: [authorization]
|
|
1970
|
+
});
|
|
1971
|
+
const gas = gasEstimate + EIP_7702_AUTH_GAS_OVERHEAD;
|
|
1972
|
+
aaDebug("7702:gas-estimated", {
|
|
1973
|
+
estimate: gasEstimate.toString(),
|
|
1974
|
+
total: gas.toString()
|
|
1975
|
+
});
|
|
1976
|
+
const hash = await walletClient.sendTransaction({
|
|
1977
|
+
to: signerAddress,
|
|
1978
|
+
data,
|
|
1979
|
+
gas,
|
|
1980
|
+
authorizationList: [authorization]
|
|
1981
|
+
});
|
|
1982
|
+
aaDebug("7702:tx-sent", { hash });
|
|
1983
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
1984
|
+
aaDebug("7702:tx-confirmed", {
|
|
1985
|
+
hash,
|
|
1986
|
+
status: receipt.status,
|
|
1987
|
+
gasUsed: receipt.gasUsed.toString()
|
|
1988
|
+
});
|
|
1989
|
+
if (receipt.status === "reverted") {
|
|
1990
|
+
throw new Error(`EIP-7702 transaction reverted: ${hash}`);
|
|
1991
|
+
}
|
|
1992
|
+
return { transactionHash: hash };
|
|
1993
|
+
};
|
|
1994
|
+
const smartAccount = {
|
|
1995
|
+
provider: "alchemy",
|
|
1996
|
+
mode: "7702",
|
|
1997
|
+
AAAddress: signerAddress,
|
|
1998
|
+
delegationAddress: ALCHEMY_7702_DELEGATION_ADDRESS,
|
|
1999
|
+
sendTransaction: async (call) => send7702([call]),
|
|
2000
|
+
sendBatchTransaction: async (calls) => send7702(calls)
|
|
2001
|
+
};
|
|
2002
|
+
return {
|
|
2003
|
+
resolved: params.resolved,
|
|
2004
|
+
account: smartAccount,
|
|
1948
2005
|
pending: false,
|
|
1949
2006
|
error: null
|
|
1950
2007
|
};
|
|
@@ -1952,6 +2009,7 @@ async function createAlchemyWalletApisState(params) {
|
|
|
1952
2009
|
|
|
1953
2010
|
// src/aa/pimlico/resolve.ts
|
|
1954
2011
|
function resolvePimlicoConfig(options) {
|
|
2012
|
+
var _a, _b, _c;
|
|
1955
2013
|
const {
|
|
1956
2014
|
calls,
|
|
1957
2015
|
localPrivateKey,
|
|
@@ -1979,7 +2037,7 @@ function resolvePimlicoConfig(options) {
|
|
|
1979
2037
|
}
|
|
1980
2038
|
return null;
|
|
1981
2039
|
}
|
|
1982
|
-
const apiKey = preResolvedApiKey != null ? preResolvedApiKey :
|
|
2040
|
+
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;
|
|
1983
2041
|
if (!apiKey) {
|
|
1984
2042
|
if (throwOnMissingConfig) {
|
|
1985
2043
|
throw new Error("Pimlico AA requires PIMLICO_API_KEY.");
|
|
@@ -2043,28 +2101,36 @@ function createPimlicoAAProvider({
|
|
|
2043
2101
|
}
|
|
2044
2102
|
|
|
2045
2103
|
// src/aa/pimlico/create.ts
|
|
2104
|
+
import { privateKeyToAccount as privateKeyToAccount3 } from "viem/accounts";
|
|
2105
|
+
var AA_DEBUG_ENABLED2 = process.env.AOMI_AA_DEBUG === "1";
|
|
2106
|
+
function pimDebug(message, fields) {
|
|
2107
|
+
if (!AA_DEBUG_ENABLED2) return;
|
|
2108
|
+
if (fields) {
|
|
2109
|
+
console.debug(`[aomi][aa][pimlico] ${message}`, fields);
|
|
2110
|
+
return;
|
|
2111
|
+
}
|
|
2112
|
+
console.debug(`[aomi][aa][pimlico] ${message}`);
|
|
2113
|
+
}
|
|
2046
2114
|
async function createPimlicoAAState(options) {
|
|
2047
|
-
var _a;
|
|
2048
|
-
const {
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
rpcUrl,
|
|
2052
|
-
callList,
|
|
2053
|
-
mode
|
|
2054
|
-
} = options;
|
|
2055
|
-
const resolved = resolvePimlicoConfig({
|
|
2056
|
-
calls: callList,
|
|
2057
|
-
chainsById: { [chain.id]: chain },
|
|
2058
|
-
rpcUrl,
|
|
2059
|
-
modeOverride: mode,
|
|
2060
|
-
throwOnMissingConfig: true,
|
|
2061
|
-
apiKey: options.apiKey
|
|
2115
|
+
var _a, _b;
|
|
2116
|
+
const { chain, owner, callList, mode } = options;
|
|
2117
|
+
const chainConfig = getAAChainConfig(DEFAULT_AA_CONFIG, callList, {
|
|
2118
|
+
[chain.id]: chain
|
|
2062
2119
|
});
|
|
2063
|
-
if (!
|
|
2064
|
-
throw new Error(
|
|
2120
|
+
if (!chainConfig) {
|
|
2121
|
+
throw new Error(`AA is not configured for chain ${chain.id}.`);
|
|
2122
|
+
}
|
|
2123
|
+
const effectiveMode = mode != null ? mode : chainConfig.defaultMode;
|
|
2124
|
+
const plan = buildAAExecutionPlan(
|
|
2125
|
+
__spreadProps(__spreadValues({}, DEFAULT_AA_CONFIG), { provider: "pimlico" }),
|
|
2126
|
+
__spreadProps(__spreadValues({}, chainConfig), { defaultMode: effectiveMode })
|
|
2127
|
+
);
|
|
2128
|
+
const apiKey = (_b = options.apiKey) != null ? _b : (_a = process.env.PIMLICO_API_KEY) == null ? void 0 : _a.trim();
|
|
2129
|
+
if (!apiKey) {
|
|
2130
|
+
throw new Error("Pimlico AA requires PIMLICO_API_KEY.");
|
|
2065
2131
|
}
|
|
2066
|
-
const
|
|
2067
|
-
|
|
2132
|
+
const execution = __spreadProps(__spreadValues({}, plan), {
|
|
2133
|
+
mode: effectiveMode,
|
|
2068
2134
|
fallbackToEoa: false
|
|
2069
2135
|
});
|
|
2070
2136
|
const ownerParams = getOwnerParams(owner);
|
|
@@ -2074,12 +2140,31 @@ async function createPimlicoAAState(options) {
|
|
|
2074
2140
|
if (ownerParams.kind === "unsupported_adapter") {
|
|
2075
2141
|
return getUnsupportedAdapterState(execution, ownerParams.adapter);
|
|
2076
2142
|
}
|
|
2143
|
+
if (owner.kind === "direct") {
|
|
2144
|
+
try {
|
|
2145
|
+
return await createPimlicoDirectState({
|
|
2146
|
+
resolved: execution,
|
|
2147
|
+
chain,
|
|
2148
|
+
privateKey: owner.privateKey,
|
|
2149
|
+
rpcUrl: options.rpcUrl,
|
|
2150
|
+
apiKey,
|
|
2151
|
+
mode: effectiveMode
|
|
2152
|
+
});
|
|
2153
|
+
} catch (error) {
|
|
2154
|
+
return {
|
|
2155
|
+
resolved: execution,
|
|
2156
|
+
account: null,
|
|
2157
|
+
pending: false,
|
|
2158
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2077
2162
|
try {
|
|
2078
2163
|
const { createPimlicoSmartAccount } = await import("@getpara/aa-pimlico");
|
|
2079
2164
|
const smartAccount = await createPimlicoSmartAccount(__spreadProps(__spreadValues({}, ownerParams.ownerParams), {
|
|
2080
2165
|
apiKey,
|
|
2081
2166
|
chain,
|
|
2082
|
-
rpcUrl,
|
|
2167
|
+
rpcUrl: options.rpcUrl,
|
|
2083
2168
|
mode: execution.mode
|
|
2084
2169
|
}));
|
|
2085
2170
|
if (!smartAccount) {
|
|
@@ -2105,6 +2190,95 @@ async function createPimlicoAAState(options) {
|
|
|
2105
2190
|
};
|
|
2106
2191
|
}
|
|
2107
2192
|
}
|
|
2193
|
+
function buildPimlicoRpcUrl(chain, apiKey) {
|
|
2194
|
+
const slug = chain.name.toLowerCase().replace(/\s+/g, "-");
|
|
2195
|
+
return `https://api.pimlico.io/v2/${slug}/rpc?apikey=${apiKey}`;
|
|
2196
|
+
}
|
|
2197
|
+
async function createPimlicoDirectState(params) {
|
|
2198
|
+
const { createSmartAccountClient } = await import("permissionless");
|
|
2199
|
+
const { toSimpleSmartAccount } = await import("permissionless/accounts");
|
|
2200
|
+
const { createPimlicoClient } = await import("permissionless/clients/pimlico");
|
|
2201
|
+
const { createPublicClient, http } = await import("viem");
|
|
2202
|
+
const { entryPoint07Address } = await import("viem/account-abstraction");
|
|
2203
|
+
const signer = privateKeyToAccount3(params.privateKey);
|
|
2204
|
+
const signerAddress = signer.address;
|
|
2205
|
+
const pimlicoRpcUrl = buildPimlicoRpcUrl(params.chain, params.apiKey);
|
|
2206
|
+
pimDebug("4337:start", {
|
|
2207
|
+
signerAddress,
|
|
2208
|
+
chainId: params.chain.id,
|
|
2209
|
+
pimlicoRpcUrl: pimlicoRpcUrl.replace(params.apiKey, "***")
|
|
2210
|
+
});
|
|
2211
|
+
const publicClient = createPublicClient({
|
|
2212
|
+
chain: params.chain,
|
|
2213
|
+
transport: http(params.rpcUrl)
|
|
2214
|
+
});
|
|
2215
|
+
const paymasterClient = createPimlicoClient({
|
|
2216
|
+
entryPoint: { address: entryPoint07Address, version: "0.7" },
|
|
2217
|
+
transport: http(pimlicoRpcUrl)
|
|
2218
|
+
});
|
|
2219
|
+
const smartAccount = await toSimpleSmartAccount({
|
|
2220
|
+
client: publicClient,
|
|
2221
|
+
owner: signer,
|
|
2222
|
+
entryPoint: { address: entryPoint07Address, version: "0.7" }
|
|
2223
|
+
});
|
|
2224
|
+
const accountAddress = smartAccount.address;
|
|
2225
|
+
pimDebug("4337:account-created", {
|
|
2226
|
+
signerAddress,
|
|
2227
|
+
accountAddress
|
|
2228
|
+
});
|
|
2229
|
+
const smartAccountClient = createSmartAccountClient({
|
|
2230
|
+
account: smartAccount,
|
|
2231
|
+
chain: params.chain,
|
|
2232
|
+
paymaster: paymasterClient,
|
|
2233
|
+
bundlerTransport: http(pimlicoRpcUrl),
|
|
2234
|
+
userOperation: {
|
|
2235
|
+
estimateFeesPerGas: async () => {
|
|
2236
|
+
const gasPrice = await paymasterClient.getUserOperationGasPrice();
|
|
2237
|
+
return gasPrice.fast;
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
});
|
|
2241
|
+
const sendCalls = async (calls) => {
|
|
2242
|
+
pimDebug("4337:send:start", {
|
|
2243
|
+
accountAddress,
|
|
2244
|
+
chainId: params.chain.id,
|
|
2245
|
+
callCount: calls.length
|
|
2246
|
+
});
|
|
2247
|
+
const hash = await smartAccountClient.sendTransaction({
|
|
2248
|
+
account: smartAccount,
|
|
2249
|
+
calls: calls.map((c) => {
|
|
2250
|
+
var _a;
|
|
2251
|
+
return {
|
|
2252
|
+
to: c.to,
|
|
2253
|
+
value: c.value,
|
|
2254
|
+
data: (_a = c.data) != null ? _a : "0x"
|
|
2255
|
+
};
|
|
2256
|
+
})
|
|
2257
|
+
});
|
|
2258
|
+
pimDebug("4337:send:userOpHash", { hash });
|
|
2259
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
2260
|
+
hash
|
|
2261
|
+
});
|
|
2262
|
+
pimDebug("4337:send:confirmed", {
|
|
2263
|
+
transactionHash: receipt.transactionHash,
|
|
2264
|
+
status: receipt.status
|
|
2265
|
+
});
|
|
2266
|
+
return { transactionHash: receipt.transactionHash };
|
|
2267
|
+
};
|
|
2268
|
+
const account = {
|
|
2269
|
+
provider: "pimlico",
|
|
2270
|
+
mode: "4337",
|
|
2271
|
+
AAAddress: accountAddress,
|
|
2272
|
+
sendTransaction: async (call) => sendCalls([call]),
|
|
2273
|
+
sendBatchTransaction: async (calls) => sendCalls(calls)
|
|
2274
|
+
};
|
|
2275
|
+
return {
|
|
2276
|
+
resolved: params.resolved,
|
|
2277
|
+
account,
|
|
2278
|
+
pending: false,
|
|
2279
|
+
error: null
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2108
2282
|
|
|
2109
2283
|
// src/aa/create.ts
|
|
2110
2284
|
async function createAAProviderState(options) {
|
|
@@ -2117,7 +2291,8 @@ async function createAAProviderState(options) {
|
|
|
2117
2291
|
mode: options.mode,
|
|
2118
2292
|
apiKey: options.apiKey,
|
|
2119
2293
|
gasPolicyId: options.gasPolicyId,
|
|
2120
|
-
sponsored: options.sponsored
|
|
2294
|
+
sponsored: options.sponsored,
|
|
2295
|
+
proxyBaseUrl: options.proxyBaseUrl
|
|
2121
2296
|
});
|
|
2122
2297
|
}
|
|
2123
2298
|
return createPimlicoAAState({
|
|
@@ -2148,16 +2323,12 @@ export {
|
|
|
2148
2323
|
isAlchemySponsorshipLimitError,
|
|
2149
2324
|
isAsyncCallback,
|
|
2150
2325
|
isInlineCall,
|
|
2151
|
-
isProviderConfigured,
|
|
2152
2326
|
isSystemError,
|
|
2153
2327
|
isSystemNotice,
|
|
2154
2328
|
normalizeEip712Payload,
|
|
2155
2329
|
normalizeTxPayload,
|
|
2156
|
-
parseAAConfig,
|
|
2157
|
-
readEnv,
|
|
2158
|
-
resolveAlchemyConfig,
|
|
2159
|
-
resolveDefaultProvider,
|
|
2160
2330
|
resolvePimlicoConfig,
|
|
2331
|
+
toAAWalletCall,
|
|
2161
2332
|
toViemSignTypedDataArgs,
|
|
2162
2333
|
unwrapSystemEvent
|
|
2163
2334
|
};
|