@dev.sail.money/sailor 0.0.2-23 → 0.0.2-27
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/AGENTS.md +1 -2
- package/README.md +62 -11
- package/examples/permissions/BoundedSupply_AaveV3_Arbitrum.sol +6 -8
- package/examples/permissions/SailCalldata.sol +118 -0
- package/package.json +9 -3
- package/packages/cli/dist/index.cjs +326 -116
- package/packages/cli/dist/server.cjs +586 -1401
- package/packages/sdk/dist/chains.d.ts +12 -0
- package/packages/sdk/dist/chains.d.ts.map +1 -0
- package/packages/sdk/dist/chains.js +88 -0
- package/packages/sdk/dist/chains.js.map +1 -0
- package/packages/sdk/dist/index.d.ts +2 -1
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +2 -1
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +1 -1
- package/packages/sdk/dist/intelligence.js +1 -1
- package/packages/sdk/dist/lifi.d.ts +17 -0
- package/packages/sdk/dist/lifi.d.ts.map +1 -1
- package/packages/sdk/dist/lifi.js +24 -0
- package/packages/sdk/dist/lifi.js.map +1 -1
- package/packages/sdk/dist/types.d.ts +17 -1
- package/packages/sdk/dist/types.d.ts.map +1 -1
- package/packages/sdk/package.json +28 -0
- package/packages/ui/dist/assets/{add-BcGCle88.js → add-qTuQMFTK.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-8Jcfw5Qj.js → all-wallets-C-2_6Yfv.js} +1 -1
- package/packages/ui/dist/assets/{app-store-R1-af7b6.js → app-store-DIz363Ij.js} +1 -1
- package/packages/ui/dist/assets/{apple-Cxitz1aK.js → apple-Bm2XNMO1.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-n-1aGCMa.js → arrow-bottom-D7B-UpVg.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-BGQ9w6zi.js → arrow-bottom-circle-XB0ks3C3.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-BngH26cQ.js → arrow-left-_d9tAksG.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-Bd1vyPNZ.js → arrow-right-By10t6nk.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-nst6Ttr2.js → arrow-top-CrLIWHvo.js} +1 -1
- package/packages/ui/dist/assets/{bank-3aeQOng_.js → bank-DZC26LyI.js} +1 -1
- package/packages/ui/dist/assets/{basic-Ds-ESc-H.js → basic-C2XYdmOJ.js} +1 -1
- package/packages/ui/dist/assets/{browser-COcw6X9p.js → browser-URMwBp02.js} +1 -1
- package/packages/ui/dist/assets/{card-B8clsijS.js → card-DI1X7fa2.js} +1 -1
- package/packages/ui/dist/assets/{ccip-SgLYYQWq.js → ccip-CkI0EKXG.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-CxpPWG40.js → checkmark-DRPP3O33.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-3THr8VIu.js → checkmark-bold-BXlTXuID.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-HfWcF1bE.js → chevron-bottom-BtIA5-Zw.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-CkXbcOst.js → chevron-left-CR6HwOU6.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-Bt7ATlLQ.js → chevron-right-DubfEKW-.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-BZc4xycM.js → chevron-top-BrZ5ZZx1.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-IT1ftwJy.js → chrome-store-DdtEbnZQ.js} +1 -1
- package/packages/ui/dist/assets/{clock-DpBvmJiH.js → clock-CbGzJbXx.js} +1 -1
- package/packages/ui/dist/assets/{close-BoRwHijk.js → close-BdZW5KIv.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-Dba1nosr.js → coinPlaceholder-BXu1Nsdu.js} +1 -1
- package/packages/ui/dist/assets/{compass-D4QnmoWi.js → compass-CZQzEYcb.js} +1 -1
- package/packages/ui/dist/assets/{copy-iBRvR2f1.js → copy-fCcrYd5O.js} +1 -1
- package/packages/ui/dist/assets/{core-B0JxSbAV.js → core-B_rlQlCa.js} +3 -3
- package/packages/ui/dist/assets/cursor-CNWux1oe.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-Djp2Lulv.js → cursor-transparent-BvuhytdN.js} +1 -1
- package/packages/ui/dist/assets/{desktop-DF6t43QS.js → desktop-AwX0UzWw.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-BUeUrh3r.js → disconnect-B2DnHNge.js} +1 -1
- package/packages/ui/dist/assets/{discord-DWtvIwBI.js → discord-CcFyxhBQ.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-CrPMVPiO.js → etherscan-D5kNPWk4.js} +1 -1
- package/packages/ui/dist/assets/{events-DC84dMPF.js → events-C8ePWdzE.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-9IcrwUru.js → exclamation-triangle-DyQ_1Efw.js} +1 -1
- package/packages/ui/dist/assets/{extension-_qe-89Jo.js → extension-jz2s06tW.js} +1 -1
- package/packages/ui/dist/assets/{external-link-Bsar6cmv.js → external-link-2ybQxumz.js} +1 -1
- package/packages/ui/dist/assets/{facebook-CZnM2tIe.js → facebook-DS8jxA10.js} +1 -1
- package/packages/ui/dist/assets/{fallback-BOfZ_bwu.js → fallback-B9fs84IX.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-DyBlkt7c.js → farcaster-BBJafyOu.js} +1 -1
- package/packages/ui/dist/assets/{filters-DwCepBxH.js → filters-CNeaqp_S.js} +1 -1
- package/packages/ui/dist/assets/{github-DgFcdJPt.js → github-Bc07zhCy.js} +1 -1
- package/packages/ui/dist/assets/{google-Csj-pWAm.js → google-v8uzPHNZ.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-CF8XrZBx.js → help-circle-DxtX1OZF.js} +1 -1
- package/packages/ui/dist/assets/{id-YqFg_Hnr.js → id-Br98ANoH.js} +1 -1
- package/packages/ui/dist/assets/{image-DvX7Dg9U.js → image-Bmk8NyWu.js} +1 -1
- package/packages/ui/dist/assets/{index-DsS2DJdh.js → index-C3xXe8Pu.js} +1 -1
- package/packages/ui/dist/assets/{index-Da0fOMbp.js → index-C8u3uWA-.js} +1 -1
- package/packages/ui/dist/assets/{index-BiN726SD.js → index-D8e304bv.js} +1 -1
- package/packages/ui/dist/assets/{index-3OLndEW6.js → index-DK4KEqZ6.js} +3 -3
- package/packages/ui/dist/assets/{index-BR_6qS4k.js → index-noDAXths.js} +1 -1
- package/packages/ui/dist/assets/index-tz2OP5vg.js +1775 -0
- package/packages/ui/dist/assets/{index.es-BiIWW5o1.js → index.es-DO70eR0a.js} +4 -4
- package/packages/ui/dist/assets/{info-zvmQXfcd.js → info-Dm75IcvR.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-poBAGMBs.js → info-circle-COqN3U18.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-Dce_oD8K.js → lightbulb-oXBKSpqT.js} +1 -1
- package/packages/ui/dist/assets/{mail-dmvvhqN6.js → mail-CzH77S-9.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-BnCx3I3r.js → metamask-sdk-kTTPRXnX.js} +1 -1
- package/packages/ui/dist/assets/{mobile-B8JxvnR1.js → mobile-DC8p7uWG.js} +1 -1
- package/packages/ui/dist/assets/{more-BwL7SLTo.js → more-CW76Ufwh.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-BGXRLaM_.js → network-placeholder-C-jgFto6.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-YKLlOwZU.js → nftPlaceholder-CMNOse1o.js} +1 -1
- package/packages/ui/dist/assets/{off-BdCZJUYq.js → off-BXAtst7s.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-D9i4CKzP.js → parseSignature-huIOIOFv.js} +1 -1
- package/packages/ui/dist/assets/{play-store-3UXzYs09.js → play-store-CAA_V4_P.js} +1 -1
- package/packages/ui/dist/assets/{plus-42VUC7wg.js → plus-o-2XxIRf.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-W99JyxAx.js → qr-code-BucbLbnn.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-B2t10e4m.js → recycle-horizontal-CzM8G600.js} +1 -1
- package/packages/ui/dist/assets/{refresh-DEFqVlG3.js → refresh-UBxc9Ujg.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-BpYt7vTo.js → reown-logo-DouNSg_O.js} +1 -1
- package/packages/ui/dist/assets/{search-C38Hy_cf.js → search-B9_0X948.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-IKD5pd64.js → secp256k1-CnLx1wuv.js} +1 -1
- package/packages/ui/dist/assets/{send-gSwkftFg.js → send-D2ETNZ0F.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-C1XbgPr5.js → swapHorizontal-6R0tJDBj.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-CtEf5r93.js → swapHorizontalBold-YzWWnx8n.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-CHP_nvzn.js → swapHorizontalMedium-DD4yeAY1.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-Crnco-Af.js → swapHorizontalRoundedBold-DmL4h2Mk.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-Ozkl0BQE.js → swapVertical-DWUQf-aB.js} +1 -1
- package/packages/ui/dist/assets/{telegram-BdfzLFDW.js → telegram-BWYqex9D.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-H2XRHPIG.js → three-dots-kuxAOnjJ.js} +1 -1
- package/packages/ui/dist/assets/{twitch-DvbgB-BL.js → twitch-Cqjm9Lmi.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-BBsTYQzn.js → twitterIcon-qeJ4RH6T.js} +1 -1
- package/packages/ui/dist/assets/{verify-3A_7IJxL.js → verify-C2pfbtI7.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-B4sP0yi_.js → verify-filled-DxEdt6vx.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-Bfua7kiP.js → w3m-modal-Dm1gaw9i.js} +1 -1
- package/packages/ui/dist/assets/{wallet-BbJ989Xh.js → wallet-B7p1_8EB.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-CQ2v8t-c.js → wallet-placeholder-BY8k3n1-.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-BuShZt17.js → walletconnect-Bg6lRwqy.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-DMs8QNCr.js → warning-circle-DqLCpUJ0.js} +1 -1
- package/packages/ui/dist/assets/{x-DzP75KD1.js → x-WtAqjAcW.js} +1 -1
- package/packages/ui/dist/index.html +1 -1
- package/templates/custom-mandate/README.md +31 -0
- package/templates/custom-mandate/mandates/BoundedCallPermission.sol +8 -2
- package/templates/custom-mandate/mandates/SailCalldata.sol +118 -0
- package/templates/default/AGENTS.md +51 -2
- package/templates/default/examples/dca/agent.ts +1 -1
- package/templates/default/examples/dca/mandate.ts +1 -1
- package/templates/default/src/agent.ts +1 -1
- package/templates/default/tsconfig.json +5 -2
- package/templates/lifi-permissions/README.md +1 -1
- package/packages/ui/dist/assets/cursor-D3cYdnOt.js +0 -3
- package/packages/ui/dist/assets/index-yQSvDbVa.js +0 -1775
|
@@ -35206,7 +35206,7 @@ var {
|
|
|
35206
35206
|
Help
|
|
35207
35207
|
} = import_index.default;
|
|
35208
35208
|
|
|
35209
|
-
// ../
|
|
35209
|
+
// ../sdk/src/chains.ts
|
|
35210
35210
|
var chains = {
|
|
35211
35211
|
// Ethereum mainnet
|
|
35212
35212
|
1: {
|
|
@@ -35282,15 +35282,17 @@ var chains = {
|
|
|
35282
35282
|
function getChain(chainId) {
|
|
35283
35283
|
const config = chains[chainId];
|
|
35284
35284
|
if (!config) {
|
|
35285
|
-
throw new Error(
|
|
35285
|
+
throw new Error(
|
|
35286
|
+
`Chain ${chainId} is not supported. Supported chains: 1 (Ethereum), 8453 (Base), 42161 (Arbitrum), 130 (Unichain), 84532 (Base Sepolia), 11155111 (Eth Sepolia).`
|
|
35287
|
+
);
|
|
35286
35288
|
}
|
|
35287
35289
|
return config;
|
|
35288
35290
|
}
|
|
35289
35291
|
|
|
35290
|
-
// ../sdk/
|
|
35292
|
+
// ../sdk/src/client.ts
|
|
35291
35293
|
init_esm2();
|
|
35292
35294
|
|
|
35293
|
-
// ../sdk/
|
|
35295
|
+
// ../sdk/src/abis/SailKernel.ts
|
|
35294
35296
|
var SailKernelAbi = [
|
|
35295
35297
|
// ── Account instantiation ────────────────────────────────────────────────
|
|
35296
35298
|
{
|
|
@@ -35595,7 +35597,7 @@ var SailKernelAbi = [
|
|
|
35595
35597
|
}
|
|
35596
35598
|
];
|
|
35597
35599
|
|
|
35598
|
-
// ../sdk/
|
|
35600
|
+
// ../sdk/src/capabilities.ts
|
|
35599
35601
|
init_esm2();
|
|
35600
35602
|
var DISPATCH_TYPE_STRINGS = {
|
|
35601
35603
|
conjunctive: "Dispatch(address account,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)",
|
|
@@ -35640,7 +35642,9 @@ function fromDispatchTypehash(kernel, dispatchTypehash, registerPermissionTypeha
|
|
|
35640
35642
|
} else if (dispatchTypehash === DISPATCH_TYPEHASHES.selective) {
|
|
35641
35643
|
dispatchModel = "selective";
|
|
35642
35644
|
} else {
|
|
35643
|
-
throw new Error(
|
|
35645
|
+
throw new Error(
|
|
35646
|
+
`Unrecognized kernel DISPATCH_TYPEHASH ${dispatchTypehash} for ${kernel}. The SDK cannot safely sign dispatches for this kernel version. Known: conjunctive=${DISPATCH_TYPEHASHES.conjunctive}, selective=${DISPATCH_TYPEHASHES.selective}.`
|
|
35647
|
+
);
|
|
35644
35648
|
}
|
|
35645
35649
|
let registerPermissionHasDeadline = dispatchModel === "selective";
|
|
35646
35650
|
if (registerPermissionTypehash === REGISTER_PERMISSION_TYPEHASHES.withDeadline) {
|
|
@@ -35665,8 +35669,7 @@ async function detectKernelCapabilities(publicClient, kernel, opts) {
|
|
|
35665
35669
|
const key = cacheKey2(chainId, kernel);
|
|
35666
35670
|
if (!opts?.force) {
|
|
35667
35671
|
const hit = cache.get(key);
|
|
35668
|
-
if (hit)
|
|
35669
|
-
return hit;
|
|
35672
|
+
if (hit) return hit;
|
|
35670
35673
|
}
|
|
35671
35674
|
let dispatchTypehash;
|
|
35672
35675
|
let registerPermissionTypehash;
|
|
@@ -35688,17 +35691,29 @@ async function detectKernelCapabilities(publicClient, kernel, opts) {
|
|
|
35688
35691
|
}
|
|
35689
35692
|
let caps;
|
|
35690
35693
|
if (dispatchTypehash) {
|
|
35691
|
-
caps = fromDispatchTypehash(
|
|
35694
|
+
caps = fromDispatchTypehash(
|
|
35695
|
+
kernel,
|
|
35696
|
+
dispatchTypehash,
|
|
35697
|
+
registerPermissionTypehash,
|
|
35698
|
+
"onchain-typehash"
|
|
35699
|
+
);
|
|
35692
35700
|
} else if (opts?.staticModel) {
|
|
35693
|
-
caps = fromDispatchTypehash(
|
|
35701
|
+
caps = fromDispatchTypehash(
|
|
35702
|
+
kernel,
|
|
35703
|
+
DISPATCH_TYPEHASHES[opts.staticModel],
|
|
35704
|
+
void 0,
|
|
35705
|
+
"static-hint"
|
|
35706
|
+
);
|
|
35694
35707
|
} else {
|
|
35695
|
-
throw new Error(
|
|
35708
|
+
throw new Error(
|
|
35709
|
+
`Could not read DISPATCH_TYPEHASH from kernel ${kernel}, and no staticModel hint was given. Pass opts.staticModel ('conjunctive' | 'selective') to proceed without on-chain detection.`
|
|
35710
|
+
);
|
|
35696
35711
|
}
|
|
35697
35712
|
cache.set(key, caps);
|
|
35698
35713
|
return caps;
|
|
35699
35714
|
}
|
|
35700
35715
|
|
|
35701
|
-
// ../sdk/
|
|
35716
|
+
// ../sdk/src/deployments.ts
|
|
35702
35717
|
var CREATE2_KERNEL = "0x02ABC18B65A328de2e749F56ba79ACF2718a6659";
|
|
35703
35718
|
var CREATE2_GOVERNANCE = "0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC";
|
|
35704
35719
|
var CREATE2_TIMELOCK = "0xE48Ba8DB6d748adafD13155c3590f62e58a77f56";
|
|
@@ -35851,7 +35866,7 @@ function getSailDeployment(chainId) {
|
|
|
35851
35866
|
return deployment;
|
|
35852
35867
|
}
|
|
35853
35868
|
|
|
35854
|
-
// ../sdk/
|
|
35869
|
+
// ../sdk/src/errors.ts
|
|
35855
35870
|
init_esm2();
|
|
35856
35871
|
var KERNEL_ERROR_SIGNATURES = [
|
|
35857
35872
|
"error AccountAlreadyRegistered(address account)",
|
|
@@ -35930,14 +35945,12 @@ async function decode2(data) {
|
|
|
35930
35945
|
}
|
|
35931
35946
|
}
|
|
35932
35947
|
function decodeKernelError(data) {
|
|
35933
|
-
if (!data || data === "0x")
|
|
35934
|
-
return Promise.resolve(null);
|
|
35948
|
+
if (!data || data === "0x") return Promise.resolve(null);
|
|
35935
35949
|
return decode2(data);
|
|
35936
35950
|
}
|
|
35937
35951
|
async function explainKernelRevert(err) {
|
|
35938
35952
|
const data = extractRevertData(err);
|
|
35939
|
-
if (!data)
|
|
35940
|
-
return null;
|
|
35953
|
+
if (!data) return null;
|
|
35941
35954
|
return decodeKernelError(data);
|
|
35942
35955
|
}
|
|
35943
35956
|
function extractRevertData(err) {
|
|
@@ -35967,7 +35980,7 @@ function extractRevertData(err) {
|
|
|
35967
35980
|
return null;
|
|
35968
35981
|
}
|
|
35969
35982
|
|
|
35970
|
-
// ../sdk/
|
|
35983
|
+
// ../sdk/src/eip712.ts
|
|
35971
35984
|
init_esm2();
|
|
35972
35985
|
function sailKernelDomain(args) {
|
|
35973
35986
|
return {
|
|
@@ -36021,12 +36034,16 @@ async function buildDispatchSignature(params) {
|
|
|
36021
36034
|
const dataHash = keccak256(call2.data);
|
|
36022
36035
|
const selective = caps.dispatchModel === "selective";
|
|
36023
36036
|
const message = selective ? { account: account2, permission, target: call2.target, value: call2.value, dataHash, nonce, deadline } : { account: account2, target: call2.target, value: call2.value, dataHash, nonce, deadline };
|
|
36024
|
-
const signature = await manager.signTyped(
|
|
36025
|
-
|
|
36026
|
-
|
|
36027
|
-
|
|
36028
|
-
|
|
36029
|
-
|
|
36037
|
+
const signature = await manager.signTyped(
|
|
36038
|
+
sailKernelDomain({ chainId, kernel }),
|
|
36039
|
+
{
|
|
36040
|
+
primaryType: "Dispatch",
|
|
36041
|
+
types: {
|
|
36042
|
+
Dispatch: DISPATCH_EIP712_FIELDS[caps.dispatchModel]
|
|
36043
|
+
}
|
|
36044
|
+
},
|
|
36045
|
+
message
|
|
36046
|
+
);
|
|
36030
36047
|
return { signature, nonce, deadline, dispatchModel: caps.dispatchModel };
|
|
36031
36048
|
}
|
|
36032
36049
|
var REGISTER_PERMISSION_TYPES = {
|
|
@@ -36105,7 +36122,7 @@ function buildRegisterPermissionsBatchTypedData(args) {
|
|
|
36105
36122
|
};
|
|
36106
36123
|
}
|
|
36107
36124
|
|
|
36108
|
-
// ../sdk/
|
|
36125
|
+
// ../sdk/src/lifi.ts
|
|
36109
36126
|
init_esm2();
|
|
36110
36127
|
var LIFI_QUOTE_URL = "https://li.quest/v1/quote";
|
|
36111
36128
|
var LIFI_ROUTERS = {
|
|
@@ -36144,7 +36161,9 @@ async function fetchLifiQuote(params) {
|
|
|
36144
36161
|
const quote = await res.json();
|
|
36145
36162
|
const tx = quote.transactionRequest;
|
|
36146
36163
|
if (!tx?.to || !tx?.data) {
|
|
36147
|
-
throw new Error(
|
|
36164
|
+
throw new Error(
|
|
36165
|
+
"LiFi quote returned no usable transactionRequest: " + JSON.stringify(quote).slice(0, 400)
|
|
36166
|
+
);
|
|
36148
36167
|
}
|
|
36149
36168
|
return {
|
|
36150
36169
|
target: tx.to,
|
|
@@ -36155,7 +36174,7 @@ async function fetchLifiQuote(params) {
|
|
|
36155
36174
|
};
|
|
36156
36175
|
}
|
|
36157
36176
|
|
|
36158
|
-
// ../sdk/
|
|
36177
|
+
// ../sdk/src/client.ts
|
|
36159
36178
|
function notImplemented() {
|
|
36160
36179
|
throw new Error("not implemented");
|
|
36161
36180
|
}
|
|
@@ -36199,17 +36218,13 @@ var CONJUNCTIVE_DISPATCH_ABI = [
|
|
|
36199
36218
|
async function enrichKernelRevert(err) {
|
|
36200
36219
|
const decoded = await explainKernelRevert(err);
|
|
36201
36220
|
const base2 = err instanceof Error ? err : new Error(String(err));
|
|
36202
|
-
if (!decoded)
|
|
36203
|
-
return base2;
|
|
36221
|
+
if (!decoded) return base2;
|
|
36204
36222
|
const wrapped = new Error(`Kernel reverted: ${decoded.message}`);
|
|
36205
36223
|
wrapped.cause = base2;
|
|
36206
36224
|
wrapped.kernelError = decoded;
|
|
36207
36225
|
return wrapped;
|
|
36208
36226
|
}
|
|
36209
36227
|
var KernelNamespace = class {
|
|
36210
|
-
publicClient;
|
|
36211
|
-
config;
|
|
36212
|
-
walletClient;
|
|
36213
36228
|
constructor(publicClient, config, walletClient) {
|
|
36214
36229
|
this.publicClient = publicClient;
|
|
36215
36230
|
this.config = config;
|
|
@@ -36218,13 +36233,17 @@ var KernelNamespace = class {
|
|
|
36218
36233
|
requireKernel() {
|
|
36219
36234
|
const kernel = this.config.kernel;
|
|
36220
36235
|
if (!kernel) {
|
|
36221
|
-
throw new Error(
|
|
36236
|
+
throw new Error(
|
|
36237
|
+
"SailKernel address not configured \u2014 set `kernel` in SailorClientConfig."
|
|
36238
|
+
);
|
|
36222
36239
|
}
|
|
36223
36240
|
return kernel;
|
|
36224
36241
|
}
|
|
36225
36242
|
requireSigner() {
|
|
36226
36243
|
if (!this.walletClient) {
|
|
36227
|
-
throw new Error(
|
|
36244
|
+
throw new Error(
|
|
36245
|
+
"No signer attached \u2014 call client.withSigner(walletClient) before write operations."
|
|
36246
|
+
);
|
|
36228
36247
|
}
|
|
36229
36248
|
return this.walletClient;
|
|
36230
36249
|
}
|
|
@@ -36247,7 +36266,9 @@ var AccountNamespace = class extends KernelNamespace {
|
|
|
36247
36266
|
const kernel = this.requireKernel();
|
|
36248
36267
|
const signer = this.requireSigner();
|
|
36249
36268
|
if (!params.safeFactory || !params.safeSingleton || !params.safeInitializer) {
|
|
36250
|
-
throw new Error(
|
|
36269
|
+
throw new Error(
|
|
36270
|
+
"createAccount requires safeFactory, safeSingleton, and safeInitializer."
|
|
36271
|
+
);
|
|
36251
36272
|
}
|
|
36252
36273
|
const txHash = await signer.writeContract({
|
|
36253
36274
|
address: kernel,
|
|
@@ -36308,17 +36329,21 @@ var MandateNamespace = class extends KernelNamespace {
|
|
|
36308
36329
|
functionName: "signerNonces",
|
|
36309
36330
|
args: [safe]
|
|
36310
36331
|
});
|
|
36311
|
-
const sig = await signer.signTyped(
|
|
36312
|
-
|
|
36313
|
-
|
|
36314
|
-
|
|
36315
|
-
|
|
36316
|
-
|
|
36317
|
-
|
|
36318
|
-
|
|
36319
|
-
|
|
36320
|
-
|
|
36321
|
-
|
|
36332
|
+
const sig = await signer.signTyped(
|
|
36333
|
+
sailKernelDomain({ chainId: this.config.chainId, kernel }),
|
|
36334
|
+
{
|
|
36335
|
+
primaryType: "RegisterPermissions",
|
|
36336
|
+
types: {
|
|
36337
|
+
RegisterPermissions: [
|
|
36338
|
+
{ name: "account", type: "address" },
|
|
36339
|
+
{ name: "permissions", type: "address[]" },
|
|
36340
|
+
{ name: "nonce", type: "uint256" },
|
|
36341
|
+
{ name: "deadline", type: "uint256" }
|
|
36342
|
+
]
|
|
36343
|
+
}
|
|
36344
|
+
},
|
|
36345
|
+
{ account: safe, permissions, nonce, deadline }
|
|
36346
|
+
);
|
|
36322
36347
|
await wallet.writeContract({
|
|
36323
36348
|
address: kernel,
|
|
36324
36349
|
abi: SailKernelAbi,
|
|
@@ -36337,7 +36362,9 @@ var MandateNamespace = class extends KernelNamespace {
|
|
|
36337
36362
|
return notImplemented();
|
|
36338
36363
|
}
|
|
36339
36364
|
deployAndAttachClone(_safe, _impl, _initData, _salt, _signer) {
|
|
36340
|
-
throw new Error(
|
|
36365
|
+
throw new Error(
|
|
36366
|
+
"deployAndAttachClone is not yet implemented in the SDK.\nUse `sailor mandate attach --address <impl>` to attach a clone template via the factory."
|
|
36367
|
+
);
|
|
36341
36368
|
}
|
|
36342
36369
|
async list(safe) {
|
|
36343
36370
|
const kernel = this.requireKernel();
|
|
@@ -36407,11 +36434,12 @@ var DispatchNamespace = class extends KernelNamespace {
|
|
|
36407
36434
|
let latest = 0n;
|
|
36408
36435
|
for (let i = 0; i < tries; i++) {
|
|
36409
36436
|
latest = await this.readManagerNonce(kernel, safe);
|
|
36410
|
-
if (latest >= expected)
|
|
36411
|
-
return latest;
|
|
36437
|
+
if (latest >= expected) return latest;
|
|
36412
36438
|
await delay(1e3);
|
|
36413
36439
|
}
|
|
36414
|
-
throw new Error(
|
|
36440
|
+
throw new Error(
|
|
36441
|
+
`Manager nonce for ${safe} did not reach ${expected} after ${tries}s (last seen ${latest}). The prior dispatch may not have mined, or the RPC endpoint is lagging. Retry, or pass an explicit nonce via options.nonce.`
|
|
36442
|
+
);
|
|
36415
36443
|
}
|
|
36416
36444
|
/**
|
|
36417
36445
|
* Determine the nonce to sign with. Honors an explicit `options.nonce`
|
|
@@ -36420,8 +36448,7 @@ var DispatchNamespace = class extends KernelNamespace {
|
|
|
36420
36448
|
* dispatch on this account) before reading the live value.
|
|
36421
36449
|
*/
|
|
36422
36450
|
async resolveNonce(kernel, safe, options) {
|
|
36423
|
-
if (options?.nonce !== void 0)
|
|
36424
|
-
return options.nonce;
|
|
36451
|
+
if (options?.nonce !== void 0) return options.nonce;
|
|
36425
36452
|
const expected = options?.awaitNonce ?? this.nextNonce.get(this.nonceKey(kernel, safe));
|
|
36426
36453
|
if (expected !== void 0) {
|
|
36427
36454
|
return this.waitForManagerNonce(kernel, safe, expected);
|
|
@@ -36513,7 +36540,9 @@ var DispatchNamespace = class extends KernelNamespace {
|
|
|
36513
36540
|
const deadline = defaultDeadline();
|
|
36514
36541
|
const caps = await this.capabilities();
|
|
36515
36542
|
if (caps.dispatchModel === "conjunctive") {
|
|
36516
|
-
throw new Error(
|
|
36543
|
+
throw new Error(
|
|
36544
|
+
`Batch dispatch is not supported by the conjunctive kernel at ${kernel} (it has no dispatchBatch). Submit calls individually via dispatch.single, ensuring the manager nonce advances between them.`
|
|
36545
|
+
);
|
|
36517
36546
|
}
|
|
36518
36547
|
const nonce = await this.publicClient.readContract({
|
|
36519
36548
|
address: kernel,
|
|
@@ -36521,19 +36550,25 @@ var DispatchNamespace = class extends KernelNamespace {
|
|
|
36521
36550
|
functionName: "batchNonces",
|
|
36522
36551
|
args: [safe]
|
|
36523
36552
|
});
|
|
36524
|
-
const callsHash = keccak256(
|
|
36525
|
-
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36530
|
-
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36534
|
-
|
|
36535
|
-
|
|
36536
|
-
|
|
36553
|
+
const callsHash = keccak256(
|
|
36554
|
+
encodeAbiParameters([{ type: "tuple[]", components: CALL_COMPONENTS }], [calls])
|
|
36555
|
+
);
|
|
36556
|
+
const managerSig = await manager.signTyped(
|
|
36557
|
+
sailKernelDomain({ chainId: this.config.chainId, kernel }),
|
|
36558
|
+
{
|
|
36559
|
+
primaryType: "DispatchBatch",
|
|
36560
|
+
types: {
|
|
36561
|
+
DispatchBatch: [
|
|
36562
|
+
{ name: "account", type: "address" },
|
|
36563
|
+
{ name: "permission", type: "address" },
|
|
36564
|
+
{ name: "callsHash", type: "bytes32" },
|
|
36565
|
+
{ name: "nonce", type: "uint256" },
|
|
36566
|
+
{ name: "deadline", type: "uint256" }
|
|
36567
|
+
]
|
|
36568
|
+
}
|
|
36569
|
+
},
|
|
36570
|
+
{ account: safe, permission, callsHash, nonce, deadline }
|
|
36571
|
+
);
|
|
36537
36572
|
let txHash;
|
|
36538
36573
|
try {
|
|
36539
36574
|
txHash = await wallet.writeContract({
|
|
@@ -36558,7 +36593,9 @@ var DispatchNamespace = class extends KernelNamespace {
|
|
|
36558
36593
|
const kernel = this.requireKernel();
|
|
36559
36594
|
const caps = await this.capabilities();
|
|
36560
36595
|
if (caps.dispatchModel === "conjunctive") {
|
|
36561
|
-
throw new Error(
|
|
36596
|
+
throw new Error(
|
|
36597
|
+
`Dry-run preview is not supported by the conjunctive kernel at ${kernel} (it has no previewBatch view). Validate calls off-chain against each registered permission's evaluate() logic, or simulate the dispatch.single tx instead.`
|
|
36598
|
+
);
|
|
36562
36599
|
}
|
|
36563
36600
|
const [approved, reason] = await this.publicClient.readContract({
|
|
36564
36601
|
address: kernel,
|
|
@@ -36570,7 +36607,6 @@ var DispatchNamespace = class extends KernelNamespace {
|
|
|
36570
36607
|
}
|
|
36571
36608
|
};
|
|
36572
36609
|
var StrategyNamespace = class extends KernelNamespace {
|
|
36573
|
-
dispatch;
|
|
36574
36610
|
constructor(publicClient, config, dispatch, walletClient) {
|
|
36575
36611
|
super(publicClient, config, walletClient);
|
|
36576
36612
|
this.dispatch = dispatch;
|
|
@@ -36588,13 +36624,17 @@ var StrategyNamespace = class extends KernelNamespace {
|
|
|
36588
36624
|
const slippage = params.slippage ?? DEFAULT_SLIPPAGE;
|
|
36589
36625
|
const router = params.router ?? LIFI_ROUTERS[this.config.chainId];
|
|
36590
36626
|
if (!router) {
|
|
36591
|
-
throw new Error(
|
|
36627
|
+
throw new Error(
|
|
36628
|
+
`No LiFi router known for chain ${this.config.chainId}. Pass params.router explicitly.`
|
|
36629
|
+
);
|
|
36592
36630
|
}
|
|
36593
36631
|
const caps = await this.capabilities();
|
|
36594
36632
|
const swapPermission = params.swapPermission ?? router;
|
|
36595
36633
|
const approvePermission = params.approvePermission ?? params.swapPermission ?? router;
|
|
36596
36634
|
if (caps.dispatchModel === "selective" && !params.swapPermission) {
|
|
36597
|
-
throw new Error(
|
|
36635
|
+
throw new Error(
|
|
36636
|
+
"This kernel uses the selective dispatch model \u2014 params.swapPermission is required (the permission that authorizes the swap)."
|
|
36637
|
+
);
|
|
36598
36638
|
}
|
|
36599
36639
|
const quote = await fetchLifiQuote({
|
|
36600
36640
|
chainId: this.config.chainId,
|
|
@@ -36614,9 +36654,19 @@ var StrategyNamespace = class extends KernelNamespace {
|
|
|
36614
36654
|
let approve;
|
|
36615
36655
|
if (allowance < params.amount) {
|
|
36616
36656
|
const approveAmount = params.approveAmount ?? params.amount;
|
|
36617
|
-
approve = await this.dispatch.single(
|
|
36657
|
+
approve = await this.dispatch.single(
|
|
36658
|
+
safe,
|
|
36659
|
+
approvePermission,
|
|
36660
|
+
{ target: params.from, value: 0n, data: encodeApprove(router, approveAmount) },
|
|
36661
|
+
manager
|
|
36662
|
+
);
|
|
36618
36663
|
}
|
|
36619
|
-
const swap = await this.dispatch.single(
|
|
36664
|
+
const swap = await this.dispatch.single(
|
|
36665
|
+
safe,
|
|
36666
|
+
swapPermission,
|
|
36667
|
+
{ target: quote.target, value: quote.value, data: quote.data },
|
|
36668
|
+
manager
|
|
36669
|
+
);
|
|
36620
36670
|
return {
|
|
36621
36671
|
swap,
|
|
36622
36672
|
approve,
|
|
@@ -36736,7 +36786,7 @@ var SailorClient = class _SailorClient {
|
|
|
36736
36786
|
}
|
|
36737
36787
|
};
|
|
36738
36788
|
|
|
36739
|
-
// ../sdk/
|
|
36789
|
+
// ../sdk/src/keyring.ts
|
|
36740
36790
|
var import_node_crypto = require("node:crypto");
|
|
36741
36791
|
var import_node_fs = require("node:fs");
|
|
36742
36792
|
init_esm2();
|
|
@@ -37418,7 +37468,7 @@ function mnemonicToAccount(mnemonic, { passphrase, ...hdKeyOpts } = {}) {
|
|
|
37418
37468
|
return hdKeyToAccount(HDKey.fromMasterSeed(seed), hdKeyOpts);
|
|
37419
37469
|
}
|
|
37420
37470
|
|
|
37421
|
-
// ../sdk/
|
|
37471
|
+
// ../sdk/src/keyring.ts
|
|
37422
37472
|
var SCRYPT_N = 1 << 18;
|
|
37423
37473
|
var SCRYPT_R = 8;
|
|
37424
37474
|
var SCRYPT_P = 1;
|
|
@@ -37436,11 +37486,16 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37436
37486
|
this.address = account2.address;
|
|
37437
37487
|
this.privateKey = options.privateKey;
|
|
37438
37488
|
} else if (options.type === "mnemonic") {
|
|
37439
|
-
const account2 = mnemonicToAccount(
|
|
37489
|
+
const account2 = mnemonicToAccount(
|
|
37490
|
+
options.mnemonic,
|
|
37491
|
+
options.derivationPath ? { path: options.derivationPath } : void 0
|
|
37492
|
+
);
|
|
37440
37493
|
this.account = account2;
|
|
37441
37494
|
this.address = account2.address;
|
|
37442
37495
|
} else {
|
|
37443
|
-
throw new Error(
|
|
37496
|
+
throw new Error(
|
|
37497
|
+
"keystore decryption not implemented \u2014 use type: 'privateKey' or type: 'mnemonic' instead"
|
|
37498
|
+
);
|
|
37444
37499
|
}
|
|
37445
37500
|
}
|
|
37446
37501
|
/** Returns a lightweight signer stub for read-only contexts where the key is not available. */
|
|
@@ -37470,7 +37525,9 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37470
37525
|
}
|
|
37471
37526
|
const { n, r, p, dklen, salt } = crypto3.kdfparams;
|
|
37472
37527
|
if (n < 1 << 14) {
|
|
37473
|
-
throw new Error(
|
|
37528
|
+
throw new Error(
|
|
37529
|
+
`Keystore scrypt N=${n} is below the minimum accepted value (16384). Refusing to decrypt.`
|
|
37530
|
+
);
|
|
37474
37531
|
}
|
|
37475
37532
|
if (r < 8) {
|
|
37476
37533
|
throw new Error(`Keystore scrypt r=${r} is below the minimum accepted value (8).`);
|
|
@@ -37488,7 +37545,11 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37488
37545
|
if (computedMac.length !== storedMac.length || !(0, import_node_crypto.timingSafeEqual)(computedMac, storedMac)) {
|
|
37489
37546
|
throw new Error("Invalid password or corrupt keystore");
|
|
37490
37547
|
}
|
|
37491
|
-
const decipher = (0, import_node_crypto.createDecipheriv)(
|
|
37548
|
+
const decipher = (0, import_node_crypto.createDecipheriv)(
|
|
37549
|
+
"aes-128-ctr",
|
|
37550
|
+
derived.subarray(0, 16),
|
|
37551
|
+
Buffer.from(crypto3.cipherparams.iv, "hex")
|
|
37552
|
+
);
|
|
37492
37553
|
const pkBytes = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
37493
37554
|
return _LocalKeyring.fromPrivateKey(`0x${pkBytes.toString("hex")}`);
|
|
37494
37555
|
}
|
|
@@ -37526,7 +37587,9 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37526
37587
|
/** Exports the private key as an encrypted keystore JSON (scrypt + aes-128-ctr, geth v3). */
|
|
37527
37588
|
async exportKeystore(password) {
|
|
37528
37589
|
if (!this.privateKey) {
|
|
37529
|
-
throw new Error(
|
|
37590
|
+
throw new Error(
|
|
37591
|
+
"Private key unavailable \u2014 only privateKey/generated keyrings can be exported"
|
|
37592
|
+
);
|
|
37530
37593
|
}
|
|
37531
37594
|
const salt = (0, import_node_crypto.randomBytes)(32);
|
|
37532
37595
|
const derived = (0, import_node_crypto.scryptSync)(password, salt, SCRYPT_DKLEN, {
|
|
@@ -37563,7 +37626,7 @@ var LocalKeyring = class _LocalKeyring {
|
|
|
37563
37626
|
}
|
|
37564
37627
|
};
|
|
37565
37628
|
|
|
37566
|
-
// ../sdk/
|
|
37629
|
+
// ../sdk/src/abis/SailGovernance.ts
|
|
37567
37630
|
var SailGovernanceAbi = [
|
|
37568
37631
|
{
|
|
37569
37632
|
type: "function",
|
|
@@ -37609,7 +37672,7 @@ var SailGovernanceAbi = [
|
|
|
37609
37672
|
}
|
|
37610
37673
|
];
|
|
37611
37674
|
|
|
37612
|
-
// ../sdk/
|
|
37675
|
+
// ../sdk/src/safe.ts
|
|
37613
37676
|
init_esm2();
|
|
37614
37677
|
var setManagerAbi = [
|
|
37615
37678
|
{
|
|
@@ -37699,7 +37762,10 @@ function buildSafeSetupInitializer(params) {
|
|
|
37699
37762
|
});
|
|
37700
37763
|
}
|
|
37701
37764
|
function buildApprovedHashSignature(owner2) {
|
|
37702
|
-
return encodePacked(
|
|
37765
|
+
return encodePacked(
|
|
37766
|
+
["bytes32", "bytes32", "uint8"],
|
|
37767
|
+
[pad(owner2, { size: 32 }), pad("0x", { size: 32 }), 1]
|
|
37768
|
+
);
|
|
37703
37769
|
}
|
|
37704
37770
|
var safeProxyFactoryAbi = [
|
|
37705
37771
|
{
|
|
@@ -37712,11 +37778,15 @@ var safeProxyFactoryAbi = [
|
|
|
37712
37778
|
];
|
|
37713
37779
|
function computeSafeProxyAddress(params) {
|
|
37714
37780
|
const { initializer, saltNonce, proxyCreationCode } = params;
|
|
37715
|
-
const initCodeHash = keccak256(
|
|
37716
|
-
|
|
37717
|
-
|
|
37718
|
-
|
|
37719
|
-
|
|
37781
|
+
const initCodeHash = keccak256(
|
|
37782
|
+
concat([
|
|
37783
|
+
proxyCreationCode,
|
|
37784
|
+
encodeAbiParameters([{ type: "address" }], [SAFE_V141.singletonL2])
|
|
37785
|
+
])
|
|
37786
|
+
);
|
|
37787
|
+
const salt = keccak256(
|
|
37788
|
+
encodePacked(["bytes32", "uint256"], [keccak256(initializer), saltNonce])
|
|
37789
|
+
);
|
|
37720
37790
|
return getCreate2Address({
|
|
37721
37791
|
from: SAFE_V141.proxyFactory,
|
|
37722
37792
|
salt,
|
|
@@ -37725,13 +37795,20 @@ function computeSafeProxyAddress(params) {
|
|
|
37725
37795
|
}
|
|
37726
37796
|
function computeKernelBoundSalt(params) {
|
|
37727
37797
|
const { saltNonce, deployer, permissionSigner, manager, feePolicy } = params;
|
|
37728
|
-
return BigInt(
|
|
37729
|
-
|
|
37730
|
-
|
|
37731
|
-
|
|
37732
|
-
|
|
37733
|
-
|
|
37734
|
-
|
|
37798
|
+
return BigInt(
|
|
37799
|
+
keccak256(
|
|
37800
|
+
encodeAbiParameters(
|
|
37801
|
+
[
|
|
37802
|
+
{ type: "uint256" },
|
|
37803
|
+
{ type: "address" },
|
|
37804
|
+
{ type: "address" },
|
|
37805
|
+
{ type: "address" },
|
|
37806
|
+
{ type: "address" }
|
|
37807
|
+
],
|
|
37808
|
+
[saltNonce, deployer, permissionSigner, manager, feePolicy]
|
|
37809
|
+
)
|
|
37810
|
+
)
|
|
37811
|
+
);
|
|
37735
37812
|
}
|
|
37736
37813
|
function computeSailSmaAddress(params) {
|
|
37737
37814
|
const boundSalt = computeKernelBoundSalt(params);
|
|
@@ -37778,7 +37855,7 @@ function buildSetManagerExecTransaction(params) {
|
|
|
37778
37855
|
return { to: params.safe, data };
|
|
37779
37856
|
}
|
|
37780
37857
|
|
|
37781
|
-
// ../sdk/
|
|
37858
|
+
// ../sdk/src/discovery.ts
|
|
37782
37859
|
var SAFE_TX_SERVICE_SLUGS = {
|
|
37783
37860
|
1: "eth",
|
|
37784
37861
|
100: "gno",
|
|
@@ -37806,7 +37883,7 @@ async function discoverSafesForOwner(owner2, chainId) {
|
|
|
37806
37883
|
return data.safes ?? [];
|
|
37807
37884
|
}
|
|
37808
37885
|
|
|
37809
|
-
// ../sdk/
|
|
37886
|
+
// ../sdk/src/fees.ts
|
|
37810
37887
|
function min(a, b) {
|
|
37811
37888
|
return a < b ? a : b;
|
|
37812
37889
|
}
|
|
@@ -37842,7 +37919,7 @@ async function estimatePermissionFee(publicClient, governance, permission) {
|
|
|
37842
37919
|
}
|
|
37843
37920
|
}
|
|
37844
37921
|
|
|
37845
|
-
// ../sdk/
|
|
37922
|
+
// ../sdk/src/intelligence.ts
|
|
37846
37923
|
var SAIL_INTELLIGENCE_BASE_URL = "https://api.sail.money";
|
|
37847
37924
|
var SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";
|
|
37848
37925
|
|
|
@@ -39907,11 +39984,29 @@ init_esm2();
|
|
|
39907
39984
|
async function checkContractExists(pc, address) {
|
|
39908
39985
|
try {
|
|
39909
39986
|
const code = await pc.getCode({ address });
|
|
39910
|
-
|
|
39987
|
+
const hasCode = !!code && code !== "0x";
|
|
39988
|
+
return { address, hasCode, bytecode: hasCode ? code : void 0 };
|
|
39911
39989
|
} catch (err) {
|
|
39912
39990
|
return { address, hasCode: false, error: err.message.split("\n")[0] };
|
|
39913
39991
|
}
|
|
39914
39992
|
}
|
|
39993
|
+
function checkSelectorRoutes(calldata, bytecode) {
|
|
39994
|
+
if (calldata.length < 10) {
|
|
39995
|
+
return { selector: "", routes: null, reason: "calldata shorter than 4 bytes \u2014 no selector" };
|
|
39996
|
+
}
|
|
39997
|
+
const selector = calldata.slice(2, 10).toLowerCase();
|
|
39998
|
+
const body = bytecode.slice(2).toLowerCase();
|
|
39999
|
+
if (body.length < 100) {
|
|
40000
|
+
return { selector, routes: null, reason: "proxy or minimal contract \u2014 routing not determinable from bytecode" };
|
|
40001
|
+
}
|
|
40002
|
+
if (body.includes("360894a13ba1a321")) {
|
|
40003
|
+
return { selector, routes: null, reason: "EIP-1967 proxy detected \u2014 routing is in the implementation contract" };
|
|
40004
|
+
}
|
|
40005
|
+
if (body.includes("a3f0ad74e5423aeb")) {
|
|
40006
|
+
return { selector, routes: null, reason: "EIP-1967 beacon proxy detected \u2014 routing is in the beacon implementation" };
|
|
40007
|
+
}
|
|
40008
|
+
return { selector, routes: body.includes(selector) };
|
|
40009
|
+
}
|
|
39915
40010
|
|
|
39916
40011
|
// src/lib/permission-resolver.ts
|
|
39917
40012
|
var IPERMISSION_ABI = [
|
|
@@ -40783,14 +40878,48 @@ var MandateStore = class {
|
|
|
40783
40878
|
(m) => m.address.toLowerCase() === needle || m.name === addressOrName
|
|
40784
40879
|
);
|
|
40785
40880
|
}
|
|
40786
|
-
/**
|
|
40881
|
+
/**
|
|
40882
|
+
* Append a newly deployed mandate (replacing any prior record at the same address).
|
|
40883
|
+
* When another mandate with the same name already exists on the same chain, the
|
|
40884
|
+
* incoming mandate's name is suffixed with `[2]`, `[3]`, … to keep names unique.
|
|
40885
|
+
*/
|
|
40787
40886
|
add(mandate2) {
|
|
40788
40887
|
const data = this.read();
|
|
40789
40888
|
data.mandates = data.mandates.filter(
|
|
40790
40889
|
(m) => m.address.toLowerCase() !== mandate2.address.toLowerCase()
|
|
40791
40890
|
);
|
|
40891
|
+
const baseName = mandate2.name;
|
|
40892
|
+
const sameName = (m) => m.name === mandate2.name && m.chainId === mandate2.chainId;
|
|
40893
|
+
if (data.mandates.some(sameName)) {
|
|
40894
|
+
let n = 2;
|
|
40895
|
+
while (data.mandates.some((m) => m.name === `${baseName}[${n}]` && m.chainId === mandate2.chainId)) {
|
|
40896
|
+
n++;
|
|
40897
|
+
}
|
|
40898
|
+
mandate2 = { ...mandate2, name: `${baseName}[${n}]` };
|
|
40899
|
+
}
|
|
40792
40900
|
data.mandates.push(mandate2);
|
|
40793
40901
|
this.write(data);
|
|
40902
|
+
return mandate2;
|
|
40903
|
+
}
|
|
40904
|
+
/** Update mutable metadata fields on a tracked mandate (name, sourcePath, artifactPath). */
|
|
40905
|
+
update(addressOrName, patch) {
|
|
40906
|
+
const data = this.read();
|
|
40907
|
+
const needle = addressOrName.toLowerCase();
|
|
40908
|
+
const mandate2 = data.mandates.find(
|
|
40909
|
+
(m) => m.address.toLowerCase() === needle || m.name === addressOrName
|
|
40910
|
+
);
|
|
40911
|
+
if (!mandate2) throw new Error(`No tracked mandate found for: ${addressOrName}`);
|
|
40912
|
+
if (patch.name !== void 0 && patch.name !== mandate2.name) {
|
|
40913
|
+
const conflict = data.mandates.find(
|
|
40914
|
+
(m) => m.name === patch.name && m.chainId === mandate2.chainId && m.address.toLowerCase() !== mandate2.address.toLowerCase()
|
|
40915
|
+
);
|
|
40916
|
+
if (conflict) throw new Error(`Name "${patch.name}" is already used by ${conflict.address} on chain ${mandate2.chainId}`);
|
|
40917
|
+
mandate2.name = patch.name;
|
|
40918
|
+
}
|
|
40919
|
+
if (patch.sourcePath !== void 0) mandate2.sourcePath = patch.sourcePath;
|
|
40920
|
+
if (patch.artifactPath !== void 0) mandate2.artifactPath = patch.artifactPath;
|
|
40921
|
+
this.write(data);
|
|
40922
|
+
return mandate2;
|
|
40794
40923
|
}
|
|
40795
40924
|
/** Record that a tracked mandate was attached to an SMA. */
|
|
40796
40925
|
recordAttachment(address, attachment) {
|
|
@@ -41405,7 +41534,18 @@ async function runDeploy(project, channel, options) {
|
|
|
41405
41534
|
);
|
|
41406
41535
|
}
|
|
41407
41536
|
const { abi: abi2, bytecode, contractName, artifactPath } = resolveArtifact(options);
|
|
41408
|
-
|
|
41537
|
+
let argsJson;
|
|
41538
|
+
if (options.argsFile) {
|
|
41539
|
+
const argsFilePath = (0, import_node_path9.resolve)(options.argsFile);
|
|
41540
|
+
try {
|
|
41541
|
+
argsJson = (0, import_node_fs10.readFileSync)(argsFilePath, "utf8").trim();
|
|
41542
|
+
} catch {
|
|
41543
|
+
throw new Error(`Cannot read --args-file: ${argsFilePath}`);
|
|
41544
|
+
}
|
|
41545
|
+
} else {
|
|
41546
|
+
argsJson = options.args;
|
|
41547
|
+
}
|
|
41548
|
+
const args = coerceConstructorArgs(abi2, argsJson);
|
|
41409
41549
|
const deployData = encodeDeployData({ abi: abi2, bytecode, args });
|
|
41410
41550
|
const chainId = project.chainId;
|
|
41411
41551
|
const publicClient = publicClientFor(project);
|
|
@@ -41428,7 +41568,10 @@ async function runDeploy(project, channel, options) {
|
|
|
41428
41568
|
data: deployData,
|
|
41429
41569
|
details: [
|
|
41430
41570
|
{ label: "Contract", value: contractName },
|
|
41431
|
-
{
|
|
41571
|
+
{
|
|
41572
|
+
label: options.argsFile ? "Constructor args (from file)" : "Constructor args",
|
|
41573
|
+
value: argsJson ? argsJson : "(none)"
|
|
41574
|
+
}
|
|
41432
41575
|
]
|
|
41433
41576
|
});
|
|
41434
41577
|
if (response.status === "rejected") {
|
|
@@ -41454,13 +41597,13 @@ async function runDeploy(project, channel, options) {
|
|
|
41454
41597
|
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41455
41598
|
};
|
|
41456
41599
|
const store = new MandateStore();
|
|
41457
|
-
store.add(record);
|
|
41458
|
-
say(() => console.log("Tracked in .sail/state/mandates.json"));
|
|
41600
|
+
const stored = store.add(record);
|
|
41601
|
+
say(() => console.log("Tracked in .sail/state/mandates.json" + (stored.name !== record.name ? ` as "${stored.name}"` : "")));
|
|
41459
41602
|
appendActivity({
|
|
41460
41603
|
ts: nowIso(),
|
|
41461
41604
|
actor: "owner",
|
|
41462
41605
|
type: "mandate_deployed",
|
|
41463
|
-
name:
|
|
41606
|
+
name: stored.name,
|
|
41464
41607
|
address: deployed,
|
|
41465
41608
|
txHash: response.txHash,
|
|
41466
41609
|
chainId
|
|
@@ -41474,7 +41617,7 @@ async function runDeploy(project, channel, options) {
|
|
|
41474
41617
|
publicClient,
|
|
41475
41618
|
sma,
|
|
41476
41619
|
deployed,
|
|
41477
|
-
|
|
41620
|
+
stored.name,
|
|
41478
41621
|
json
|
|
41479
41622
|
);
|
|
41480
41623
|
store.recordAttachment(deployed, { sma, txHash: attachTxHash });
|
|
@@ -41489,7 +41632,7 @@ Register it later with: sailor mandate attach --address ${deployed} --sma <SMA>`
|
|
|
41489
41632
|
emit(json, () => {
|
|
41490
41633
|
}, {
|
|
41491
41634
|
status: "ok",
|
|
41492
|
-
mandate: { name:
|
|
41635
|
+
mandate: { name: stored.name, address: deployed, txHash: response.txHash, chainId },
|
|
41493
41636
|
attached: options.attach ? { sma: getAddress(options.sma), txHash: attachTxHash } : null
|
|
41494
41637
|
});
|
|
41495
41638
|
}
|
|
@@ -41751,7 +41894,7 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
41751
41894
|
}
|
|
41752
41895
|
say(() => console.log("\u2713", `Deployed + registered ${spec.label} at ${clone}`));
|
|
41753
41896
|
const store = new MandateStore();
|
|
41754
|
-
store.add({
|
|
41897
|
+
const storedClone = store.add({
|
|
41755
41898
|
name: label,
|
|
41756
41899
|
address: clone,
|
|
41757
41900
|
txHash,
|
|
@@ -41764,7 +41907,7 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
41764
41907
|
actor: "agent",
|
|
41765
41908
|
type: "permission_registered",
|
|
41766
41909
|
permission: clone,
|
|
41767
|
-
name:
|
|
41910
|
+
name: storedClone.name,
|
|
41768
41911
|
sma,
|
|
41769
41912
|
txHash,
|
|
41770
41913
|
chainId: project.chainId
|
|
@@ -42085,6 +42228,21 @@ function mandateContractsList() {
|
|
|
42085
42228
|
}
|
|
42086
42229
|
}
|
|
42087
42230
|
}
|
|
42231
|
+
function mandateUpdate(options) {
|
|
42232
|
+
const { address, name, sourcePath, artifactPath, json } = options;
|
|
42233
|
+
if (!name && !sourcePath && !artifactPath) {
|
|
42234
|
+
throw new Error("Provide at least one of --name, --source-path, or --artifact-path");
|
|
42235
|
+
}
|
|
42236
|
+
const store = new MandateStore();
|
|
42237
|
+
const updated = store.update(address, { name, sourcePath, artifactPath });
|
|
42238
|
+
emit(!!json, () => {
|
|
42239
|
+
const changes = [];
|
|
42240
|
+
if (name) changes.push(`name \u2192 ${updated.name}`);
|
|
42241
|
+
if (sourcePath) changes.push(`sourcePath \u2192 ${updated.sourcePath}`);
|
|
42242
|
+
if (artifactPath) changes.push(`artifactPath \u2192 ${updated.artifactPath}`);
|
|
42243
|
+
console.log(`Updated ${updated.address}: ${changes.join(", ")}`);
|
|
42244
|
+
}, { status: "ok", mandate: updated });
|
|
42245
|
+
}
|
|
42088
42246
|
function resolveArtifact(options) {
|
|
42089
42247
|
let artifactPath = options.artifact;
|
|
42090
42248
|
let contractName = options.contract ?? options.name ?? "";
|
|
@@ -42094,7 +42252,7 @@ function resolveArtifact(options) {
|
|
|
42094
42252
|
}
|
|
42095
42253
|
const resolved = (0, import_node_path9.resolve)(artifactPath);
|
|
42096
42254
|
const projectRoot = (0, import_node_path9.resolve)(process.cwd());
|
|
42097
|
-
if (!resolved.startsWith(projectRoot +
|
|
42255
|
+
if (!resolved.startsWith(projectRoot + import_node_path9.sep) && resolved !== projectRoot) {
|
|
42098
42256
|
throw new Error(
|
|
42099
42257
|
`Artifact path must be inside the project directory.
|
|
42100
42258
|
Resolved: ${resolved}`
|
|
@@ -42539,6 +42697,7 @@ async function mandateSimulate(options) {
|
|
|
42539
42697
|
checkContractExists(pc, c.target)
|
|
42540
42698
|
]);
|
|
42541
42699
|
const result = probe.accepted ? "pass" : "fail";
|
|
42700
|
+
const selectorCheck = codeCheck.hasCode && codeCheck.bytecode ? checkSelectorRoutes(c.data, codeCheck.bytecode) : { selector: "", routes: null, reason: codeCheck.hasCode ? "bytecode unavailable" : void 0 };
|
|
42542
42701
|
return {
|
|
42543
42702
|
index: i,
|
|
42544
42703
|
label: c.label,
|
|
@@ -42550,7 +42709,10 @@ async function mandateSimulate(options) {
|
|
|
42550
42709
|
expect: c.expect ?? null,
|
|
42551
42710
|
match: c.expect ? c.expect === result : null,
|
|
42552
42711
|
targetHasCode: codeCheck.hasCode,
|
|
42553
|
-
targetCheckError: codeCheck.error
|
|
42712
|
+
targetCheckError: codeCheck.error,
|
|
42713
|
+
selectorRoutes: selectorCheck.routes,
|
|
42714
|
+
selector: selectorCheck.selector,
|
|
42715
|
+
selectorRoutesReason: selectorCheck.reason
|
|
42554
42716
|
};
|
|
42555
42717
|
})
|
|
42556
42718
|
);
|
|
@@ -42581,7 +42743,10 @@ async function mandateSimulate(options) {
|
|
|
42581
42743
|
expect: r.expect,
|
|
42582
42744
|
match: r.match,
|
|
42583
42745
|
targetHasCode: r.targetHasCode,
|
|
42584
|
-
targetCheckError: r.targetCheckError
|
|
42746
|
+
targetCheckError: r.targetCheckError,
|
|
42747
|
+
selector: r.selector,
|
|
42748
|
+
selectorRoutes: r.selectorRoutes,
|
|
42749
|
+
selectorRoutesReason: r.selectorRoutesReason
|
|
42585
42750
|
})),
|
|
42586
42751
|
mismatches: mismatches.length,
|
|
42587
42752
|
noCodeTargets: noCodeTargets.map((r) => r.target),
|
|
@@ -42607,7 +42772,9 @@ async function mandateSimulate(options) {
|
|
|
42607
42772
|
const expectStr = r.expect === null ? "" : r.match ? ` expected ${r.expect} \u2713 MATCH` : ` expected ${r.expect} \u2717 MISMATCH`;
|
|
42608
42773
|
console.log(`[${r.index + 1}] ${verdict} ${r.label}${expectStr}`);
|
|
42609
42774
|
const codeNote = r.targetCheckError ? `\u26A0 could not verify contract code (${r.targetCheckError})` : r.targetHasCode ? "\u2713 contract present" : `\u26A0 NO contract code on chain ${chainId} \u2014 this call would fail on-chain regardless of the permission`;
|
|
42775
|
+
const selectorNote = r.selectorRoutes === true ? `\u2713 selector 0x${r.selector} routes` : r.selectorRoutes === false ? `\u26A0 selector 0x${r.selector} NOT found in bytecode \u2014 call would likely revert with unknown selector` : r.selectorRoutesReason ? `~ selector check skipped (${r.selectorRoutesReason})` : null;
|
|
42610
42776
|
console.log(` target ${r.target} ${codeNote}`);
|
|
42777
|
+
if (selectorNote) console.log(` ${selectorNote}`);
|
|
42611
42778
|
if (r.reverted && r.revertReason) {
|
|
42612
42779
|
console.log(` evaluate() reverted: ${r.revertReason}`);
|
|
42613
42780
|
}
|
|
@@ -43225,13 +43392,30 @@ function isProcessAlive(pid) {
|
|
|
43225
43392
|
// src/commands/run.ts
|
|
43226
43393
|
var DEFAULT_INTERVAL_SEC = 60;
|
|
43227
43394
|
var sleep2 = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
43228
|
-
var
|
|
43395
|
+
var ERC20_READ_ABI = [
|
|
43229
43396
|
{
|
|
43230
43397
|
type: "function",
|
|
43231
43398
|
name: "balanceOf",
|
|
43232
43399
|
stateMutability: "view",
|
|
43233
43400
|
inputs: [{ name: "account", type: "address" }],
|
|
43234
43401
|
outputs: [{ name: "", type: "uint256" }]
|
|
43402
|
+
},
|
|
43403
|
+
{
|
|
43404
|
+
type: "function",
|
|
43405
|
+
name: "allowance",
|
|
43406
|
+
stateMutability: "view",
|
|
43407
|
+
inputs: [
|
|
43408
|
+
{ name: "owner", type: "address" },
|
|
43409
|
+
{ name: "spender", type: "address" }
|
|
43410
|
+
],
|
|
43411
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
43412
|
+
},
|
|
43413
|
+
{
|
|
43414
|
+
type: "function",
|
|
43415
|
+
name: "decimals",
|
|
43416
|
+
stateMutability: "view",
|
|
43417
|
+
inputs: [],
|
|
43418
|
+
outputs: [{ name: "", type: "uint8" }]
|
|
43235
43419
|
}
|
|
43236
43420
|
];
|
|
43237
43421
|
function loadAgentData(filePath) {
|
|
@@ -43251,7 +43435,8 @@ async function loadAgent() {
|
|
|
43251
43435
|
let mod2;
|
|
43252
43436
|
if (abs.endsWith(".ts")) {
|
|
43253
43437
|
const { tsImport } = await import("tsx/esm/api");
|
|
43254
|
-
|
|
43438
|
+
const absUrl = (0, import_node_url.pathToFileURL)(abs).href;
|
|
43439
|
+
mod2 = await tsImport(absUrl, absUrl);
|
|
43255
43440
|
} else {
|
|
43256
43441
|
mod2 = await import((0, import_node_url.pathToFileURL)(abs).href);
|
|
43257
43442
|
}
|
|
@@ -43378,11 +43563,30 @@ Configure the chain in @sail/chains or set KERNEL_ADDRESS in .sail/.env.local.`
|
|
|
43378
43563
|
}
|
|
43379
43564
|
return publicClient.readContract({
|
|
43380
43565
|
address: token,
|
|
43381
|
-
abi:
|
|
43566
|
+
abi: ERC20_READ_ABI,
|
|
43382
43567
|
functionName: "balanceOf",
|
|
43383
43568
|
args: [accountAddr]
|
|
43384
43569
|
});
|
|
43385
43570
|
};
|
|
43571
|
+
const readAllowance = (token, owner2, spender) => publicClient.readContract({
|
|
43572
|
+
address: token,
|
|
43573
|
+
abi: ERC20_READ_ABI,
|
|
43574
|
+
functionName: "allowance",
|
|
43575
|
+
args: [owner2, spender]
|
|
43576
|
+
});
|
|
43577
|
+
const decimalsCache = /* @__PURE__ */ new Map();
|
|
43578
|
+
const readDecimals = async (token) => {
|
|
43579
|
+
const key = getAddress(token);
|
|
43580
|
+
const cached = decimalsCache.get(key);
|
|
43581
|
+
if (cached !== void 0) return cached;
|
|
43582
|
+
const d = await publicClient.readContract({
|
|
43583
|
+
address: token,
|
|
43584
|
+
abi: ERC20_READ_ABI,
|
|
43585
|
+
functionName: "decimals"
|
|
43586
|
+
});
|
|
43587
|
+
decimalsCache.set(key, d);
|
|
43588
|
+
return d;
|
|
43589
|
+
};
|
|
43386
43590
|
async function runTick() {
|
|
43387
43591
|
appendActivity({ ts: nowIso(), actor: "agent", type: "tick_start" });
|
|
43388
43592
|
let blockInfo = { number: 0n, timestamp: 0n };
|
|
@@ -43412,10 +43616,15 @@ Configure the chain in @sail/chains or set KERNEL_ADDRESS in .sail/.env.local.`
|
|
|
43412
43616
|
dispatch: execClient.dispatch,
|
|
43413
43617
|
strategy: execClient.strategy
|
|
43414
43618
|
}),
|
|
43619
|
+
publicClient,
|
|
43415
43620
|
manager: agentManager,
|
|
43416
43621
|
log,
|
|
43417
43622
|
data: agentData,
|
|
43418
|
-
read: {
|
|
43623
|
+
read: {
|
|
43624
|
+
balance: readBalance,
|
|
43625
|
+
allowance: readAllowance,
|
|
43626
|
+
decimals: readDecimals
|
|
43627
|
+
}
|
|
43419
43628
|
};
|
|
43420
43629
|
let dispatches;
|
|
43421
43630
|
try {
|
|
@@ -44040,7 +44249,7 @@ account.command("rotate-signer").description("Rotate the SMA's delegated signer
|
|
|
44040
44249
|
var mandate = program2.command("mandate").description("Manage mandates");
|
|
44041
44250
|
mandate.command("prepare").description("Prepare a mandate draft for review and signing in the UI (MetaMask)").action(action(mandatePrepare));
|
|
44042
44251
|
mandate.command("sign").description("Review and confirm the permissions authorized for your SMA").option("--yes", "Skip the confirmation prompt (for non-interactive / CI use)").action(actionWith(mandateSign));
|
|
44043
|
-
mandate.command("deploy").description("Deploy a Foundry-compiled permission contract via the browser signing UI").option("--artifact <path>", "Path to the Foundry artifact JSON (out/<Name>.sol/<Name>.json)").option("--contract <name>", "Contract name; resolves to <out>/<name>.sol/<name>.json").option("--out <dir>", "Foundry output directory", "out").option("--name <label>", "Label to track this permission under (defaults to contract name)").option("--args <json>", `Constructor args as
|
|
44252
|
+
mandate.command("deploy").description("Deploy a Foundry-compiled permission contract via the browser signing UI").option("--artifact <path>", "Path to the Foundry artifact JSON (out/<Name>.sol/<Name>.json)").option("--contract <name>", "Contract name; resolves to <out>/<name>.sol/<name>.json").option("--out <dir>", "Foundry output directory", "out").option("--name <label>", "Label to track this permission under (defaults to contract name)").option("--args <json>", `Constructor args as JSON array. Bash: '["0x..","1"]'. PowerShell: '[\\"0x..\\",\\"1\\"]'. Use --args-file to avoid quoting.`).option("--args-file <path>", "Path to a JSON file containing constructor args array (recommended on PowerShell)").option("--build", "Run `forge build` before deploying").option("--attach", "After deploy, register the permission on --sma").option("--sma <address>", "SMA to register on (required with --attach)").option("--json", "Emit machine-readable JSON").action(actionWith(mandateDeploy));
|
|
44044
44253
|
mandate.command("attach").description("Register an already-deployed permission on an SMA (EIP-712 RegisterPermission)").requiredOption("--address <mandateOrName>", "Permission address, or a name tracked locally").requiredOption("--sma <address>", "SMA to register the permission on").option("--label <label>", "Human-readable label shown in the signing UI").option("--json", "Emit machine-readable JSON").action(actionWith(mandateAttach));
|
|
44045
44254
|
mandate.command("deploy-clone").description("Deploy + register a standalone clone permission (e.g. boundedApprove) via the signing UI").requiredOption("--template <key>", "Standalone clone template key (e.g. boundedApprove)").requiredOption("--sma <address>", "SMA to deploy the clone for and register it on").option("--tokens <csv>", "Comma-separated allowed token addresses").option("--spenders <csv>", "Comma-separated allowed spender addresses").option("--max <amount>", "Max amount per tx in base units (default: uint256 max)").option("--label <label>", "Human-readable label to track this permission under").option("--json", "Emit machine-readable JSON").action(actionWith(mandateDeployClone));
|
|
44046
44255
|
mandate.command("revoke").description("Revoke permission(s) from an SMA (EIP-712 RevokePermissions, owner-authorized)").option("--address <permissionOrName>", "Permission address, or a name tracked locally").requiredOption("--sma <address>", "Safe (SMA) to revoke the permission(s) from").option("--all", "Revoke every permission currently registered on the SMA").option("--json", "Output JSON").action(actionWith(mandateRevoke));
|
|
@@ -44048,6 +44257,7 @@ mandate.command("templates").description("Show how to author your own permission
|
|
|
44048
44257
|
mandate.command("simulate").description(
|
|
44049
44258
|
"Probe a permission against sample calls off-chain (eth_call, NO gas) \u2014 prove it accepts the calls you want and rejects the ones you don't, before authorizing on-chain"
|
|
44050
44259
|
).requiredOption("--address <permissionOrName>", "Permission to probe (address or tracked name)").option("--sma <address>", "SMA to probe as (ctx.account; defaults to .sail/account.json)").option("--target <address>", "Inline single call: target contract address").option("--calldata <hex>", "Inline single call: 0x-prefixed calldata").option("--value <wei>", "Inline single call: ETH value in wei (default 0)").option("--expect <pass|fail>", "Inline single call: expected outcome (sets non-zero exit on mismatch)").option("--label <text>", "Inline single call: human-readable label").option("--calls <file>", "Batch: JSON array of { target, calldata, value?, expect?, label? }").option("--json", "Emit machine-readable JSON").action(actionWith(mandateSimulate));
|
|
44260
|
+
mandate.command("update").description("Update metadata for a tracked permission contract (rename, source path, artifact path)").requiredOption("--address <mandateOrName>", "Permission address or tracked name to update").option("--name <label>", "New tracking label (must be unique within the same chain)").option("--source-path <path>", "Update the relative path to the Solidity source file").option("--artifact-path <path>", "Update the relative path to the Foundry artifact JSON").option("--json", "Emit machine-readable JSON").action(actionWith(mandateUpdate));
|
|
44051
44261
|
mandate.command("list").description("List permission contracts deployed from this project").action(action(async () => mandateContractsList()));
|
|
44052
44262
|
program2.command("onboard").description("Set up an SMA, register a permission, confirm the agent is operational").option("--sma <address>", "Use a specific SMA address instead of prompting").option("--new-sma", "Create a new SMA via SailKernel").option("--salt <n>", "CREATE2 salt for deterministic Safe address (default: 0; use 0 for first SMA, increment for subsequent)").option("--template <kindOrAddress>", "Register this permission contract (kind, label, or address)").option("--skip-mandate", "Skip the permission registration step").option("--json", "Emit machine-readable JSON (implies non-interactive)").action(actionWith(onboard));
|
|
44053
44263
|
var station = program2.command("station").description("Manage the persistent signing station (browser signing daemon)");
|