@smartagentkit/sdk 0.1.2 → 0.1.3
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/index.d.mts +29 -7
- package/dist/index.d.ts +29 -7
- package/dist/index.js +320 -155
- package/dist/index.mjs +324 -157
- package/package.json +1 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -86,6 +86,7 @@ var ENTRYPOINT_V07 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
|
|
|
86
86
|
var SAFE_7579_MODULE = "0x7579EE8307284F293B1927136486880611F20002";
|
|
87
87
|
var SAFE_7579_LAUNCHPAD = "0x7579011aB74c46090561ea277Ba79D510c6C00ff";
|
|
88
88
|
var RHINESTONE_ATTESTER = "0x000000333034E9f539ce08819E12c1b8Cb29084d";
|
|
89
|
+
var SMART_SESSIONS_VALIDATOR = "0x00000000002B0eCfbD0496EE71e01257dA0E37DE";
|
|
89
90
|
var ATTESTERS_THRESHOLD = 1;
|
|
90
91
|
var WINDOW_1_HOUR = 3600;
|
|
91
92
|
var WINDOW_1_DAY = 86400;
|
|
@@ -223,15 +224,6 @@ var MODULE_ONINSTALL_ABI = [
|
|
|
223
224
|
stateMutability: "nonpayable"
|
|
224
225
|
}
|
|
225
226
|
];
|
|
226
|
-
var SET_TRUSTED_FORWARDER_ABI = [
|
|
227
|
-
{
|
|
228
|
-
name: "setTrustedForwarder",
|
|
229
|
-
type: "function",
|
|
230
|
-
inputs: [{ name: "forwarder", type: "address" }],
|
|
231
|
-
outputs: [],
|
|
232
|
-
stateMutability: "nonpayable"
|
|
233
|
-
}
|
|
234
|
-
];
|
|
235
227
|
var HOOK_MULTIPLEXER_ABI = [
|
|
236
228
|
{
|
|
237
229
|
name: "addHook",
|
|
@@ -258,119 +250,6 @@ var MODULE_ADDRESSES = {
|
|
|
258
250
|
// Will be populated after deployment
|
|
259
251
|
};
|
|
260
252
|
|
|
261
|
-
// src/presets.ts
|
|
262
|
-
var PRESETS = {
|
|
263
|
-
/**
|
|
264
|
-
* DeFi Trader preset:
|
|
265
|
-
* - Daily spending limit on ETH and stablecoins
|
|
266
|
-
* - Allowlist of approved DEX contracts
|
|
267
|
-
* - Emergency pause with owner as guardian
|
|
268
|
-
*/
|
|
269
|
-
"defi-trader": (owner, params = {}) => [
|
|
270
|
-
{
|
|
271
|
-
type: "spending-limit",
|
|
272
|
-
limits: [
|
|
273
|
-
{
|
|
274
|
-
token: NATIVE_TOKEN,
|
|
275
|
-
limit: params.dailyEthLimit ?? (0, import_viem.parseEther)("1"),
|
|
276
|
-
window: WINDOW_1_DAY
|
|
277
|
-
},
|
|
278
|
-
...params.stablecoinLimits ?? []
|
|
279
|
-
]
|
|
280
|
-
},
|
|
281
|
-
// Only include allowlist if specific DEXes are provided;
|
|
282
|
-
// an empty allowlist in "allow" mode would block all transactions.
|
|
283
|
-
...params.allowedDexes?.length ? [
|
|
284
|
-
{
|
|
285
|
-
type: "allowlist",
|
|
286
|
-
mode: "allow",
|
|
287
|
-
targets: params.allowedDexes.map((addr) => ({
|
|
288
|
-
address: addr,
|
|
289
|
-
selector: "0x00000000"
|
|
290
|
-
}))
|
|
291
|
-
}
|
|
292
|
-
] : [],
|
|
293
|
-
{
|
|
294
|
-
type: "emergency-pause",
|
|
295
|
-
guardian: params.guardian ?? owner,
|
|
296
|
-
autoUnpauseAfter: WINDOW_1_DAY
|
|
297
|
-
}
|
|
298
|
-
],
|
|
299
|
-
/**
|
|
300
|
-
* Treasury Agent preset:
|
|
301
|
-
* - Lower spending limits with longer windows
|
|
302
|
-
* - Emergency pause (manual only)
|
|
303
|
-
*/
|
|
304
|
-
"treasury-agent": (owner, params = {}) => [
|
|
305
|
-
{
|
|
306
|
-
type: "spending-limit",
|
|
307
|
-
limits: [
|
|
308
|
-
{
|
|
309
|
-
token: NATIVE_TOKEN,
|
|
310
|
-
limit: params.weeklyEthLimit ?? (0, import_viem.parseEther)("5"),
|
|
311
|
-
window: WINDOW_1_WEEK
|
|
312
|
-
}
|
|
313
|
-
]
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
type: "emergency-pause",
|
|
317
|
-
guardian: params.guardian ?? owner,
|
|
318
|
-
autoUnpauseAfter: 0
|
|
319
|
-
}
|
|
320
|
-
],
|
|
321
|
-
/**
|
|
322
|
-
* Payment Agent preset:
|
|
323
|
-
* - Strict spending limits
|
|
324
|
-
* - Allowlist of approved recipients only
|
|
325
|
-
* - Emergency pause
|
|
326
|
-
*/
|
|
327
|
-
"payment-agent": (owner, params = {}) => [
|
|
328
|
-
{
|
|
329
|
-
type: "spending-limit",
|
|
330
|
-
limits: [
|
|
331
|
-
{
|
|
332
|
-
token: NATIVE_TOKEN,
|
|
333
|
-
limit: params.dailyLimit ?? (0, import_viem.parseEther)("0.1"),
|
|
334
|
-
window: WINDOW_1_DAY
|
|
335
|
-
}
|
|
336
|
-
]
|
|
337
|
-
},
|
|
338
|
-
// Only include allowlist if specific recipients are provided;
|
|
339
|
-
// an empty allowlist in "allow" mode would block all transactions.
|
|
340
|
-
...params.approvedRecipients?.length ? [
|
|
341
|
-
{
|
|
342
|
-
type: "allowlist",
|
|
343
|
-
mode: "allow",
|
|
344
|
-
targets: params.approvedRecipients.map(
|
|
345
|
-
(addr) => ({
|
|
346
|
-
address: addr
|
|
347
|
-
})
|
|
348
|
-
)
|
|
349
|
-
}
|
|
350
|
-
] : [],
|
|
351
|
-
{
|
|
352
|
-
type: "emergency-pause",
|
|
353
|
-
guardian: params.guardian ?? owner,
|
|
354
|
-
autoUnpauseAfter: 3600
|
|
355
|
-
}
|
|
356
|
-
],
|
|
357
|
-
/**
|
|
358
|
-
* Minimal preset:
|
|
359
|
-
* - Just emergency pause
|
|
360
|
-
* - For agents that need maximum flexibility with a kill switch
|
|
361
|
-
*/
|
|
362
|
-
minimal: (owner, params = {}) => [
|
|
363
|
-
{
|
|
364
|
-
type: "emergency-pause",
|
|
365
|
-
guardian: params.guardian ?? owner,
|
|
366
|
-
autoUnpauseAfter: 0
|
|
367
|
-
}
|
|
368
|
-
]
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
// src/policies.ts
|
|
372
|
-
var import_viem2 = require("viem");
|
|
373
|
-
|
|
374
253
|
// src/errors.ts
|
|
375
254
|
var SmartAgentKitError = class extends Error {
|
|
376
255
|
constructor(message, options) {
|
|
@@ -421,7 +300,174 @@ var SessionError = class extends SmartAgentKitError {
|
|
|
421
300
|
}
|
|
422
301
|
};
|
|
423
302
|
|
|
303
|
+
// src/presets.ts
|
|
304
|
+
function validatePresetParams(presetName, params, spec) {
|
|
305
|
+
for (const [key, expectedType] of Object.entries(spec)) {
|
|
306
|
+
if (params[key] === void 0) continue;
|
|
307
|
+
const value = params[key];
|
|
308
|
+
switch (expectedType) {
|
|
309
|
+
case "bigint":
|
|
310
|
+
if (typeof value !== "bigint") {
|
|
311
|
+
throw new PolicyConfigError(
|
|
312
|
+
`Preset "${presetName}": parameter "${key}" must be a bigint, got ${typeof value}`
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
case "Address":
|
|
317
|
+
if (typeof value !== "string" || !(0, import_viem.isAddress)(value)) {
|
|
318
|
+
throw new PolicyConfigError(
|
|
319
|
+
`Preset "${presetName}": parameter "${key}" must be a valid Ethereum address`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
break;
|
|
323
|
+
case "Address[]":
|
|
324
|
+
if (!Array.isArray(value) || !value.every((v) => typeof v === "string" && (0, import_viem.isAddress)(v))) {
|
|
325
|
+
throw new PolicyConfigError(
|
|
326
|
+
`Preset "${presetName}": parameter "${key}" must be an array of valid Ethereum addresses`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
var PRESETS = {
|
|
334
|
+
/**
|
|
335
|
+
* DeFi Trader preset:
|
|
336
|
+
* - Daily spending limit on ETH and stablecoins
|
|
337
|
+
* - Allowlist of approved DEX contracts
|
|
338
|
+
* - Emergency pause with owner as guardian
|
|
339
|
+
*/
|
|
340
|
+
"defi-trader": (owner, params = {}) => {
|
|
341
|
+
validatePresetParams("defi-trader", params, {
|
|
342
|
+
dailyEthLimit: "bigint",
|
|
343
|
+
guardian: "Address",
|
|
344
|
+
allowedDexes: "Address[]"
|
|
345
|
+
});
|
|
346
|
+
return [
|
|
347
|
+
{
|
|
348
|
+
type: "spending-limit",
|
|
349
|
+
limits: [
|
|
350
|
+
{
|
|
351
|
+
token: NATIVE_TOKEN,
|
|
352
|
+
limit: params.dailyEthLimit ?? (0, import_viem.parseEther)("1"),
|
|
353
|
+
window: WINDOW_1_DAY
|
|
354
|
+
},
|
|
355
|
+
...params.stablecoinLimits ?? []
|
|
356
|
+
]
|
|
357
|
+
},
|
|
358
|
+
// Only include allowlist if specific DEXes are provided;
|
|
359
|
+
// an empty allowlist in "allow" mode would block all transactions.
|
|
360
|
+
...params.allowedDexes?.length ? [
|
|
361
|
+
{
|
|
362
|
+
type: "allowlist",
|
|
363
|
+
mode: "allow",
|
|
364
|
+
targets: params.allowedDexes.map((addr) => ({
|
|
365
|
+
address: addr
|
|
366
|
+
// Omit selector to use the wildcard (0x431e2cf5) — allows all
|
|
367
|
+
// function calls, not just ETH transfers. 0x00000000 is NOT a
|
|
368
|
+
// wildcard; it only matches empty calldata.
|
|
369
|
+
}))
|
|
370
|
+
}
|
|
371
|
+
] : [],
|
|
372
|
+
{
|
|
373
|
+
type: "emergency-pause",
|
|
374
|
+
guardian: params.guardian ?? owner,
|
|
375
|
+
autoUnpauseAfter: WINDOW_1_DAY
|
|
376
|
+
}
|
|
377
|
+
];
|
|
378
|
+
},
|
|
379
|
+
/**
|
|
380
|
+
* Treasury Agent preset:
|
|
381
|
+
* - Lower spending limits with longer windows
|
|
382
|
+
* - Emergency pause (manual only)
|
|
383
|
+
*/
|
|
384
|
+
"treasury-agent": (owner, params = {}) => {
|
|
385
|
+
validatePresetParams("treasury-agent", params, {
|
|
386
|
+
weeklyEthLimit: "bigint",
|
|
387
|
+
guardian: "Address"
|
|
388
|
+
});
|
|
389
|
+
return [
|
|
390
|
+
{
|
|
391
|
+
type: "spending-limit",
|
|
392
|
+
limits: [
|
|
393
|
+
{
|
|
394
|
+
token: NATIVE_TOKEN,
|
|
395
|
+
limit: params.weeklyEthLimit ?? (0, import_viem.parseEther)("5"),
|
|
396
|
+
window: WINDOW_1_WEEK
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
type: "emergency-pause",
|
|
402
|
+
guardian: params.guardian ?? owner,
|
|
403
|
+
autoUnpauseAfter: 0
|
|
404
|
+
}
|
|
405
|
+
];
|
|
406
|
+
},
|
|
407
|
+
/**
|
|
408
|
+
* Payment Agent preset:
|
|
409
|
+
* - Strict spending limits
|
|
410
|
+
* - Allowlist of approved recipients only
|
|
411
|
+
* - Emergency pause
|
|
412
|
+
*/
|
|
413
|
+
"payment-agent": (owner, params = {}) => {
|
|
414
|
+
validatePresetParams("payment-agent", params, {
|
|
415
|
+
dailyLimit: "bigint",
|
|
416
|
+
guardian: "Address",
|
|
417
|
+
approvedRecipients: "Address[]"
|
|
418
|
+
});
|
|
419
|
+
return [
|
|
420
|
+
{
|
|
421
|
+
type: "spending-limit",
|
|
422
|
+
limits: [
|
|
423
|
+
{
|
|
424
|
+
token: NATIVE_TOKEN,
|
|
425
|
+
limit: params.dailyLimit ?? (0, import_viem.parseEther)("0.1"),
|
|
426
|
+
window: WINDOW_1_DAY
|
|
427
|
+
}
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
// Only include allowlist if specific recipients are provided;
|
|
431
|
+
// an empty allowlist in "allow" mode would block all transactions.
|
|
432
|
+
...params.approvedRecipients?.length ? [
|
|
433
|
+
{
|
|
434
|
+
type: "allowlist",
|
|
435
|
+
mode: "allow",
|
|
436
|
+
targets: params.approvedRecipients.map(
|
|
437
|
+
(addr) => ({
|
|
438
|
+
address: addr
|
|
439
|
+
})
|
|
440
|
+
)
|
|
441
|
+
}
|
|
442
|
+
] : [],
|
|
443
|
+
{
|
|
444
|
+
type: "emergency-pause",
|
|
445
|
+
guardian: params.guardian ?? owner,
|
|
446
|
+
autoUnpauseAfter: 3600
|
|
447
|
+
}
|
|
448
|
+
];
|
|
449
|
+
},
|
|
450
|
+
/**
|
|
451
|
+
* Minimal preset:
|
|
452
|
+
* - Just emergency pause
|
|
453
|
+
* - For agents that need maximum flexibility with a kill switch
|
|
454
|
+
*/
|
|
455
|
+
minimal: (owner, params = {}) => {
|
|
456
|
+
validatePresetParams("minimal", params, {
|
|
457
|
+
guardian: "Address"
|
|
458
|
+
});
|
|
459
|
+
return [
|
|
460
|
+
{
|
|
461
|
+
type: "emergency-pause",
|
|
462
|
+
guardian: params.guardian ?? owner,
|
|
463
|
+
autoUnpauseAfter: 0
|
|
464
|
+
}
|
|
465
|
+
];
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
424
469
|
// src/policies.ts
|
|
470
|
+
var import_viem2 = require("viem");
|
|
425
471
|
function encodePolicyInitData(policy, moduleAddresses, trustedForwarder = "0x0000000000000000000000000000000000000000") {
|
|
426
472
|
const zeroAddress = "0x0000000000000000000000000000000000000000";
|
|
427
473
|
switch (policy.type) {
|
|
@@ -536,11 +582,11 @@ var base_sepolia_default = {
|
|
|
536
582
|
safe7579Launchpad: "0x7579011aB74c46090561ea277Ba79D510c6C00ff",
|
|
537
583
|
rhinestoneAttester: "0x000000333034E9f539ce08819E12c1b8Cb29084d",
|
|
538
584
|
hookMultiPlexer: "0xF6782ed057F95f334D04F0Af1Af4D14fb84DE549",
|
|
539
|
-
spendingLimitHook: "
|
|
540
|
-
allowlistHook: "
|
|
541
|
-
emergencyPauseHook: "
|
|
542
|
-
automationExecutor: "
|
|
543
|
-
moduleSetupHelper: "
|
|
585
|
+
spendingLimitHook: "0xd67a5E6784A66Ddf4C09EA7bbf81Ab89532624E4",
|
|
586
|
+
allowlistHook: "0x7899b03386A3874393A3769D637977d947A9Fc66",
|
|
587
|
+
emergencyPauseHook: "0xAc0cE5672aED1Bfe5549b885f883a770Acd8cAE3",
|
|
588
|
+
automationExecutor: "0x795DB663b70bAe110C10694DF3f5D801b76E2b20",
|
|
589
|
+
moduleSetupHelper: "0xcBb12Eb2CF324B1C34160F72E037589CEEC35Fa0"
|
|
544
590
|
};
|
|
545
591
|
|
|
546
592
|
// src/deployments/sepolia.json
|
|
@@ -701,6 +747,11 @@ function getRemoveAction(permissionId) {
|
|
|
701
747
|
// src/client.ts
|
|
702
748
|
function resolveAccount(key) {
|
|
703
749
|
if (typeof key === "string") {
|
|
750
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
|
|
751
|
+
throw new WalletCreationError(
|
|
752
|
+
"Invalid private key format. Expected a 0x-prefixed 32-byte hex string."
|
|
753
|
+
);
|
|
754
|
+
}
|
|
704
755
|
return (0, import_accounts.privateKeyToAccount)(key);
|
|
705
756
|
}
|
|
706
757
|
return (0, import_accounts.mnemonicToAccount)(key.mnemonic, {
|
|
@@ -751,7 +802,7 @@ var SmartAgentKitClient = class {
|
|
|
751
802
|
const ownerAccount = resolveAccount(ownerKey);
|
|
752
803
|
if (ownerAccount.address.toLowerCase() !== params.owner.toLowerCase()) {
|
|
753
804
|
throw new WalletCreationError(
|
|
754
|
-
|
|
805
|
+
"Owner address does not match the provided signing key. Verify that the private key or mnemonic corresponds to the specified owner address."
|
|
755
806
|
);
|
|
756
807
|
}
|
|
757
808
|
const hookModule = (0, import_module_sdk3.getHookMultiPlexer)({
|
|
@@ -808,7 +859,7 @@ var SmartAgentKitClient = class {
|
|
|
808
859
|
} catch (error) {
|
|
809
860
|
if (error instanceof WalletCreationError) throw error;
|
|
810
861
|
throw new WalletCreationError(
|
|
811
|
-
|
|
862
|
+
"Wallet deployment failed. Check your RPC/bundler configuration and that the owner key is correct.",
|
|
812
863
|
error
|
|
813
864
|
);
|
|
814
865
|
}
|
|
@@ -862,7 +913,13 @@ var SmartAgentKitClient = class {
|
|
|
862
913
|
* the smart account via Smart Sessions. The session is scoped to
|
|
863
914
|
* specific target contracts, function selectors, and time window.
|
|
864
915
|
*
|
|
865
|
-
* @returns The session key address
|
|
916
|
+
* @returns The session key address and permission ID.
|
|
917
|
+
*
|
|
918
|
+
* SECURITY: The session private key is intentionally NOT returned or stored
|
|
919
|
+
* by the SDK. The caller should use the `sessionKey` address to identify
|
|
920
|
+
* the session on-chain, and manage key material externally via a secure
|
|
921
|
+
* key management system. To use a pre-generated key pair, provide the
|
|
922
|
+
* session key address in `params.sessionKey`.
|
|
866
923
|
*/
|
|
867
924
|
async createSession(wallet, params, ownerKey) {
|
|
868
925
|
const client = this.getWalletClient(wallet.address);
|
|
@@ -915,7 +972,6 @@ var SmartAgentKitClient = class {
|
|
|
915
972
|
walletSessions.push({
|
|
916
973
|
permissionId,
|
|
917
974
|
sessionKeyAddress: sessionAccount.address,
|
|
918
|
-
sessionKeyPrivateKey: sessionPrivateKey,
|
|
919
975
|
expiresAt: params.expiresAt,
|
|
920
976
|
actions: params.actions.map((a) => ({
|
|
921
977
|
target: a.target,
|
|
@@ -925,13 +981,12 @@ var SmartAgentKitClient = class {
|
|
|
925
981
|
this.sessions.set(wallet.address, walletSessions);
|
|
926
982
|
return {
|
|
927
983
|
sessionKey: sessionAccount.address,
|
|
928
|
-
privateKey: sessionPrivateKey,
|
|
929
984
|
permissionId
|
|
930
985
|
};
|
|
931
986
|
} catch (error) {
|
|
932
987
|
if (error instanceof SessionError) throw error;
|
|
933
988
|
throw new SessionError(
|
|
934
|
-
|
|
989
|
+
"Session creation failed. Check that the wallet is deployed and the owner key is correct."
|
|
935
990
|
);
|
|
936
991
|
}
|
|
937
992
|
}
|
|
@@ -952,7 +1007,7 @@ var SmartAgentKitClient = class {
|
|
|
952
1007
|
);
|
|
953
1008
|
} catch (error) {
|
|
954
1009
|
throw new SessionError(
|
|
955
|
-
|
|
1010
|
+
"Session revocation failed. Check the permission ID and wallet connection."
|
|
956
1011
|
);
|
|
957
1012
|
}
|
|
958
1013
|
}
|
|
@@ -976,6 +1031,7 @@ var SmartAgentKitClient = class {
|
|
|
976
1031
|
* Hooks (spending limits, allowlist, pause) are enforced on-chain.
|
|
977
1032
|
*/
|
|
978
1033
|
async execute(wallet, params) {
|
|
1034
|
+
this.validateTransaction(params, wallet.address);
|
|
979
1035
|
const client = this.getWalletClient(wallet.address);
|
|
980
1036
|
try {
|
|
981
1037
|
const hash = await client.sendTransaction({
|
|
@@ -989,8 +1045,9 @@ var SmartAgentKitClient = class {
|
|
|
989
1045
|
});
|
|
990
1046
|
return hash;
|
|
991
1047
|
} catch (error) {
|
|
1048
|
+
if (error instanceof ExecutionError) throw error;
|
|
992
1049
|
throw new ExecutionError(
|
|
993
|
-
|
|
1050
|
+
"Transaction failed. Check that the target, value, and calldata are correct.",
|
|
994
1051
|
error
|
|
995
1052
|
);
|
|
996
1053
|
}
|
|
@@ -1000,6 +1057,9 @@ var SmartAgentKitClient = class {
|
|
|
1000
1057
|
* All calls are encoded into a single UserOperation with batch mode.
|
|
1001
1058
|
*/
|
|
1002
1059
|
async executeBatch(wallet, params) {
|
|
1060
|
+
for (const call of params.calls) {
|
|
1061
|
+
this.validateTransaction(call, wallet.address);
|
|
1062
|
+
}
|
|
1003
1063
|
const client = this.getWalletClient(wallet.address);
|
|
1004
1064
|
try {
|
|
1005
1065
|
const calls = params.calls.map((call) => ({
|
|
@@ -1012,8 +1072,9 @@ var SmartAgentKitClient = class {
|
|
|
1012
1072
|
});
|
|
1013
1073
|
return hash;
|
|
1014
1074
|
} catch (error) {
|
|
1075
|
+
if (error instanceof ExecutionError) throw error;
|
|
1015
1076
|
throw new ExecutionError(
|
|
1016
|
-
|
|
1077
|
+
"Batch transaction failed. Check that all targets, values, and calldata are correct.",
|
|
1017
1078
|
error
|
|
1018
1079
|
);
|
|
1019
1080
|
}
|
|
@@ -1116,10 +1177,58 @@ var SmartAgentKitClient = class {
|
|
|
1116
1177
|
}
|
|
1117
1178
|
// ─── Private Helpers ──────────────────────────────────────────
|
|
1118
1179
|
resolvePolicies(params) {
|
|
1180
|
+
let policies;
|
|
1119
1181
|
if (params.preset) {
|
|
1120
|
-
|
|
1182
|
+
policies = PRESETS[params.preset](params.owner, params.presetParams);
|
|
1183
|
+
} else {
|
|
1184
|
+
policies = params.policies ?? [];
|
|
1121
1185
|
}
|
|
1122
|
-
|
|
1186
|
+
if (policies.length > 0 && this.config.moduleAddresses) {
|
|
1187
|
+
const moduleAddresses = this.config.moduleAddresses;
|
|
1188
|
+
const infrastructureAddresses = [];
|
|
1189
|
+
if (moduleAddresses.spendingLimitHook) {
|
|
1190
|
+
infrastructureAddresses.push(moduleAddresses.spendingLimitHook);
|
|
1191
|
+
}
|
|
1192
|
+
if (moduleAddresses.allowlistHook) {
|
|
1193
|
+
infrastructureAddresses.push(moduleAddresses.allowlistHook);
|
|
1194
|
+
}
|
|
1195
|
+
if (moduleAddresses.emergencyPauseHook) {
|
|
1196
|
+
infrastructureAddresses.push(moduleAddresses.emergencyPauseHook);
|
|
1197
|
+
}
|
|
1198
|
+
if (moduleAddresses.automationExecutor) {
|
|
1199
|
+
infrastructureAddresses.push(moduleAddresses.automationExecutor);
|
|
1200
|
+
}
|
|
1201
|
+
infrastructureAddresses.push(HOOK_MULTIPLEXER_ADDRESS);
|
|
1202
|
+
infrastructureAddresses.push(SMART_SESSIONS_VALIDATOR);
|
|
1203
|
+
let hasAllowlist = false;
|
|
1204
|
+
for (const policy of policies) {
|
|
1205
|
+
if (policy.type === "allowlist") {
|
|
1206
|
+
hasAllowlist = true;
|
|
1207
|
+
const existing = new Set(
|
|
1208
|
+
(policy.protectedAddresses ?? []).map((a) => a.toLowerCase())
|
|
1209
|
+
);
|
|
1210
|
+
const merged = [...policy.protectedAddresses ?? []];
|
|
1211
|
+
for (const addr of infrastructureAddresses) {
|
|
1212
|
+
if (!existing.has(addr.toLowerCase())) {
|
|
1213
|
+
merged.push(addr);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
policy.protectedAddresses = merged;
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
const hasHooks = policies.some(
|
|
1220
|
+
(p) => p.type === "spending-limit" || p.type === "emergency-pause"
|
|
1221
|
+
);
|
|
1222
|
+
if (hasHooks && !hasAllowlist) {
|
|
1223
|
+
policies.push({
|
|
1224
|
+
type: "allowlist",
|
|
1225
|
+
mode: "block",
|
|
1226
|
+
targets: [],
|
|
1227
|
+
protectedAddresses: infrastructureAddresses
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
return policies;
|
|
1123
1232
|
}
|
|
1124
1233
|
requireModuleAddresses(policies) {
|
|
1125
1234
|
if (policies.length === 0) return void 0;
|
|
@@ -1177,7 +1286,7 @@ var SmartAgentKitClient = class {
|
|
|
1177
1286
|
switch (policy.type) {
|
|
1178
1287
|
case "spending-limit": {
|
|
1179
1288
|
const hookAddress = moduleAddresses.spendingLimitHook;
|
|
1180
|
-
const initData = encodeSpendingLimitInitData(policy);
|
|
1289
|
+
const initData = encodeSpendingLimitInitData(policy, hookMultiPlexerAddress);
|
|
1181
1290
|
this.pushSubHookInitCalls(
|
|
1182
1291
|
calls,
|
|
1183
1292
|
hookAddress,
|
|
@@ -1188,7 +1297,7 @@ var SmartAgentKitClient = class {
|
|
|
1188
1297
|
}
|
|
1189
1298
|
case "allowlist": {
|
|
1190
1299
|
const hookAddress = moduleAddresses.allowlistHook;
|
|
1191
|
-
const initData = encodeAllowlistInitData(policy);
|
|
1300
|
+
const initData = encodeAllowlistInitData(policy, hookMultiPlexerAddress);
|
|
1192
1301
|
this.pushSubHookInitCalls(
|
|
1193
1302
|
calls,
|
|
1194
1303
|
hookAddress,
|
|
@@ -1199,7 +1308,7 @@ var SmartAgentKitClient = class {
|
|
|
1199
1308
|
}
|
|
1200
1309
|
case "emergency-pause": {
|
|
1201
1310
|
const hookAddress = moduleAddresses.emergencyPauseHook;
|
|
1202
|
-
const initData = encodeEmergencyPauseInitData(policy);
|
|
1311
|
+
const initData = encodeEmergencyPauseInitData(policy, hookMultiPlexerAddress);
|
|
1203
1312
|
this.pushSubHookInitCalls(
|
|
1204
1313
|
calls,
|
|
1205
1314
|
hookAddress,
|
|
@@ -1218,10 +1327,13 @@ var SmartAgentKitClient = class {
|
|
|
1218
1327
|
});
|
|
1219
1328
|
}
|
|
1220
1329
|
/**
|
|
1221
|
-
* Push the
|
|
1222
|
-
* 1. onInstall(initData) on the sub-hook
|
|
1223
|
-
* 2.
|
|
1224
|
-
*
|
|
1330
|
+
* Push the 2 calls needed to initialize a sub-hook:
|
|
1331
|
+
* 1. onInstall(initData) on the sub-hook — sets trusted forwarder from init data
|
|
1332
|
+
* 2. addHook(hookAddr, GLOBAL) on the HookMultiPlexer
|
|
1333
|
+
*
|
|
1334
|
+
* Note: The trusted forwarder is now set during onInstall via the encoded init data
|
|
1335
|
+
* (passed as the first parameter). A separate setTrustedForwarder call is no longer
|
|
1336
|
+
* needed, reducing gas cost and batch size.
|
|
1225
1337
|
*/
|
|
1226
1338
|
pushSubHookInitCalls(calls, hookAddress, initData, hookMultiPlexerAddress) {
|
|
1227
1339
|
calls.push({
|
|
@@ -1233,15 +1345,6 @@ var SmartAgentKitClient = class {
|
|
|
1233
1345
|
args: [initData]
|
|
1234
1346
|
})
|
|
1235
1347
|
});
|
|
1236
|
-
calls.push({
|
|
1237
|
-
to: hookAddress,
|
|
1238
|
-
value: 0n,
|
|
1239
|
-
data: (0, import_viem4.encodeFunctionData)({
|
|
1240
|
-
abi: SET_TRUSTED_FORWARDER_ABI,
|
|
1241
|
-
functionName: "setTrustedForwarder",
|
|
1242
|
-
args: [hookMultiPlexerAddress]
|
|
1243
|
-
})
|
|
1244
|
-
});
|
|
1245
1348
|
calls.push({
|
|
1246
1349
|
to: hookMultiPlexerAddress,
|
|
1247
1350
|
value: 0n,
|
|
@@ -1296,6 +1399,69 @@ var SmartAgentKitClient = class {
|
|
|
1296
1399
|
}
|
|
1297
1400
|
});
|
|
1298
1401
|
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Collect all known infrastructure addresses that must never be
|
|
1404
|
+
* targeted by agent-initiated transactions. This prevents an AI agent
|
|
1405
|
+
* from calling hook admin functions (setGuardian, clearTrustedForwarder,
|
|
1406
|
+
* removeSpendingLimit, removeHook, etc.) to weaken its own policy constraints.
|
|
1407
|
+
*/
|
|
1408
|
+
getProtectedAddresses() {
|
|
1409
|
+
const addresses = /* @__PURE__ */ new Set();
|
|
1410
|
+
addresses.add(ENTRYPOINT_V07.toLowerCase());
|
|
1411
|
+
addresses.add(HOOK_MULTIPLEXER_ADDRESS.toLowerCase());
|
|
1412
|
+
addresses.add(SAFE_7579_MODULE.toLowerCase());
|
|
1413
|
+
addresses.add(SAFE_7579_LAUNCHPAD.toLowerCase());
|
|
1414
|
+
addresses.add(SMART_SESSIONS_VALIDATOR.toLowerCase());
|
|
1415
|
+
const moduleAddresses = this.config.moduleAddresses;
|
|
1416
|
+
if (moduleAddresses) {
|
|
1417
|
+
if (moduleAddresses.spendingLimitHook) {
|
|
1418
|
+
addresses.add(moduleAddresses.spendingLimitHook.toLowerCase());
|
|
1419
|
+
}
|
|
1420
|
+
if (moduleAddresses.allowlistHook) {
|
|
1421
|
+
addresses.add(moduleAddresses.allowlistHook.toLowerCase());
|
|
1422
|
+
}
|
|
1423
|
+
if (moduleAddresses.emergencyPauseHook) {
|
|
1424
|
+
addresses.add(moduleAddresses.emergencyPauseHook.toLowerCase());
|
|
1425
|
+
}
|
|
1426
|
+
if (moduleAddresses.automationExecutor) {
|
|
1427
|
+
addresses.add(moduleAddresses.automationExecutor.toLowerCase());
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
return addresses;
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Validate a transaction before submission. Blocks calls to infrastructure
|
|
1434
|
+
* addresses and validates input parameters.
|
|
1435
|
+
*
|
|
1436
|
+
* @throws ExecutionError if the transaction targets a protected address
|
|
1437
|
+
* or has invalid parameters.
|
|
1438
|
+
*/
|
|
1439
|
+
validateTransaction(params, walletAddress) {
|
|
1440
|
+
if (!(0, import_viem4.isAddress)(params.target)) {
|
|
1441
|
+
throw new ExecutionError(
|
|
1442
|
+
`Invalid target address: "${params.target}". Expected a 0x-prefixed 20-byte hex address.`
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
const protectedAddresses = this.getProtectedAddresses();
|
|
1446
|
+
if (protectedAddresses.has(params.target.toLowerCase())) {
|
|
1447
|
+
throw new ExecutionError(
|
|
1448
|
+
`Transaction blocked: target ${params.target} is a protected infrastructure contract. Agent wallets cannot call hook, multiplexer, or EntryPoint contracts directly.`
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
if (walletAddress && params.target.toLowerCase() === walletAddress.toLowerCase()) {
|
|
1452
|
+
throw new ExecutionError(
|
|
1453
|
+
`Transaction blocked: target ${params.target} is the wallet's own address. Self-calls could be used to uninstall security modules.`
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
if (params.value !== void 0 && params.value < 0n) {
|
|
1457
|
+
throw new ExecutionError("Transaction value cannot be negative.");
|
|
1458
|
+
}
|
|
1459
|
+
if (params.data && params.data !== "0x" && !(0, import_viem4.isHex)(params.data)) {
|
|
1460
|
+
throw new ExecutionError(
|
|
1461
|
+
`Invalid calldata: "${params.data}". Expected a 0x-prefixed hex string.`
|
|
1462
|
+
);
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1299
1465
|
getWalletClient(walletAddress) {
|
|
1300
1466
|
const client = this.walletClients.get(walletAddress);
|
|
1301
1467
|
if (!client) {
|
|
@@ -1351,4 +1517,3 @@ var SmartAgentKitClient = class {
|
|
|
1351
1517
|
getRemoveSessionAction,
|
|
1352
1518
|
getSmartSessionsModule
|
|
1353
1519
|
});
|
|
1354
|
-
//# sourceMappingURL=index.js.map
|