@dev.sail.money/sailor 0.0.2-19 → 0.0.2-21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/examples/permissions/BoundedApproveAndCallBatch.sol +179 -0
- package/examples/permissions/BoundedBet_Limitless_Base.sol +8 -7
- package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +13 -13
- package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +50 -39
- package/examples/permissions/BoundedStake_Venice_Base.sol +85 -0
- package/examples/permissions/BoundedSupply_AaveV3_Arbitrum.sol +84 -0
- package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +11 -9
- package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +10 -8
- package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +6 -6
- package/examples/permissions/BoundedVault_ERC4626_Base.sol +97 -0
- package/examples/permissions/README.md +29 -2
- package/examples/permissions/interfaces/IBatchPermission.sol +38 -0
- package/package.json +1 -1
- package/packages/cli/dist/index.cjs +1172 -588
- package/packages/cli/dist/server.cjs +139 -948
- package/packages/sdk/dist/index.d.ts +1 -1
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +1 -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/safe.d.ts +83 -0
- package/packages/sdk/dist/safe.d.ts.map +1 -1
- package/packages/sdk/dist/safe.js +92 -1
- package/packages/sdk/dist/safe.js.map +1 -1
- package/packages/ui/dist/assets/Arc-VDBY7LNS-BChRXCXW.js +1 -0
- package/packages/ui/dist/assets/Brave-BRAKJXDS-mq-Xo37j.js +1 -0
- package/packages/ui/dist/assets/Browser-76IHF3Y2-BMhRaC5Z.js +1 -0
- package/packages/ui/dist/assets/Chrome-65Q5P54Y-DR9MQEVr.js +1 -0
- package/packages/ui/dist/assets/Edge-XSPUTORV-DEoZslQE.js +1 -0
- package/packages/ui/dist/assets/Firefox-AAHGJQIP-Bp_Hm04m.js +1 -0
- package/packages/ui/dist/assets/Linux-OO4TNCLJ-B0aw93n9.js +1 -0
- package/packages/ui/dist/assets/Macos-MW4AE7LN-Vvm8Drw3.js +1 -0
- package/packages/ui/dist/assets/Opera-KQZLSACL-Cwv5MDFy.js +1 -0
- package/packages/ui/dist/assets/Safari-ZPL37GXR-C4Ggg6rz.js +1 -0
- package/packages/ui/dist/assets/Windows-PPTHQER6-BlyV2p7Y.js +1 -0
- package/packages/ui/dist/assets/add-BzRDG6go.js +15 -0
- package/packages/ui/dist/assets/all-wallets-C6juL2cm.js +6 -0
- package/packages/ui/dist/assets/apechain-SX5YFU6N-q5qBv-mp.js +1 -0
- package/packages/ui/dist/assets/app-store-DSJ1ow5G.js +17 -0
- package/packages/ui/dist/assets/apple-CUEgIX9k.js +18 -0
- package/packages/ui/dist/assets/ar_AR-LIPSOZP5-BQrIDibT.js +1519 -0
- package/packages/ui/dist/assets/arbitrum-WURIBY6W-CqVkHBr5.js +1 -0
- package/packages/ui/dist/assets/arrow-bottom-BOhBj1Je.js +8 -0
- package/packages/ui/dist/assets/arrow-bottom-circle-C4CzuHiR.js +11 -0
- package/packages/ui/dist/assets/arrow-left-BTD8zZ12.js +8 -0
- package/packages/ui/dist/assets/arrow-right-qcOukPwm.js +8 -0
- package/packages/ui/dist/assets/arrow-top-C0f2945G.js +8 -0
- package/packages/ui/dist/assets/assets-Q6ZU7ZJ5-P8HioiAD.js +1 -0
- package/packages/ui/dist/assets/avalanche-KOMJD3XY-Dsn_JPR4.js +1 -0
- package/packages/ui/dist/assets/bank-BSWzLP3R.js +14 -0
- package/packages/ui/dist/assets/base-OAXLRA4F-CoYTVIiL.js +1 -0
- package/packages/ui/dist/assets/base-QS6CYWIN-CsjdbWCf.js +1 -0
- package/packages/ui/dist/assets/basic-DGTBsmnG.js +2128 -0
- package/packages/ui/dist/assets/berachain-NJECWIVC-DumxnFvf.js +1 -0
- package/packages/ui/dist/assets/blast-V555OVXZ-BbhJh1tj.js +1 -0
- package/packages/ui/dist/assets/browser-DJNepafc.js +14 -0
- package/packages/ui/dist/assets/bsc-N647EYR2-B2nLKXWV.js +1 -0
- package/packages/ui/dist/assets/card-u08LJx43.js +14 -0
- package/packages/ui/dist/assets/ccip-DcWZjG37.js +1 -0
- package/packages/ui/dist/assets/celo-GEP4TUHG-CenIBYLU.js +1 -0
- package/packages/ui/dist/assets/checkmark-DVD-obDl.js +11 -0
- package/packages/ui/dist/assets/checkmark-bold-CSXDqIAx.js +8 -0
- package/packages/ui/dist/assets/chevron-bottom-Be7f0gi2.js +8 -0
- package/packages/ui/dist/assets/chevron-left-v8cgKRhQ.js +8 -0
- package/packages/ui/dist/assets/chevron-right-B0ux2X-3.js +8 -0
- package/packages/ui/dist/assets/chevron-top-De-a8tmA.js +8 -0
- package/packages/ui/dist/assets/chrome-store-BIIIRGPA.js +61 -0
- package/packages/ui/dist/assets/clock-8d5kvRPQ.js +8 -0
- package/packages/ui/dist/assets/close-BSSJkFv0.js +8 -0
- package/packages/ui/dist/assets/coinPlaceholder-CLJaQiUO.js +8 -0
- package/packages/ui/dist/assets/compass-CR1zP0b-.js +8 -0
- package/packages/ui/dist/assets/connect-UA7M4XW6-IY3X6Bmr.js +1 -0
- package/packages/ui/dist/assets/copy-CGkuIFo6.js +15 -0
- package/packages/ui/dist/assets/core-ea860JM2.js +907 -0
- package/packages/ui/dist/assets/create-FASO7PVG-D_rvSpre.js +1 -0
- package/packages/ui/dist/assets/cronos-HJPAQTAE-BEOvlOC4.js +1 -0
- package/packages/ui/dist/assets/cursor-DCRoxgSY.js +3 -0
- package/packages/ui/dist/assets/cursor-transparent-C8s5LY_P.js +12 -0
- package/packages/ui/dist/assets/de_DE-YE3KOFHU-BRt5ztUe.js +1519 -0
- package/packages/ui/dist/assets/degen-FQQ4XGHB-CeHTs88l.js +1 -0
- package/packages/ui/dist/assets/desktop-CQyixryE.js +9 -0
- package/packages/ui/dist/assets/disconnect-Ct0234l0.js +8 -0
- package/packages/ui/dist/assets/discord-haYPGMDl.js +17 -0
- package/packages/ui/dist/assets/es_419-7LMPU7G4-DH7rM0yQ.js +1519 -0
- package/packages/ui/dist/assets/ethereum-RGGVA4PY-SWGOlkuk.js +1 -0
- package/packages/ui/dist/assets/etherscan-BTLrS1KK.js +6 -0
- package/packages/ui/dist/assets/events-wdo_D3Zy.js +1 -0
- package/packages/ui/dist/assets/exclamation-triangle-CMlYpOat.js +4 -0
- package/packages/ui/dist/assets/extension-CNGBCbo8.js +8 -0
- package/packages/ui/dist/assets/external-link-DmYJSKcL.js +8 -0
- package/packages/ui/dist/assets/facebook-F0iMVTem.js +26 -0
- package/packages/ui/dist/assets/fallback-BqeFDEuW.js +1 -0
- package/packages/ui/dist/assets/farcaster-CYr9I6UA.js +12 -0
- package/packages/ui/dist/assets/filters-CxE97nqU.js +8 -0
- package/packages/ui/dist/assets/flow-5FQJFCTK-CUie2reO.js +1 -0
- package/packages/ui/dist/assets/fr_FR-VBJP3ZLL-B-_ocunw.js +1519 -0
- package/packages/ui/dist/assets/github-CjRht-Wv.js +18 -0
- package/packages/ui/dist/assets/gnosis-37ZC4RBL-B137OtHZ.js +1 -0
- package/packages/ui/dist/assets/google-3G0o4pR9.js +18 -0
- package/packages/ui/dist/assets/gravity-J5YQHTYH-Bj6B0uod.js +1 -0
- package/packages/ui/dist/assets/hardhat-TX56IT5N-CV1FY-wE.js +1 -0
- package/packages/ui/dist/assets/help-circle-C5gNChqZ.js +12 -0
- package/packages/ui/dist/assets/hi_IN-WBVD5XYI-D73g2UFs.js +1519 -0
- package/packages/ui/dist/assets/hyperevm-VKPAA4SA-CHwraEsx.js +1 -0
- package/packages/ui/dist/assets/id-C6_zK0Tb.js +12 -0
- package/packages/ui/dist/assets/id_ID-SBYANJ7G-Cjpa4ay6.js +1519 -0
- package/packages/ui/dist/assets/image-DsU8Irlu.js +4 -0
- package/packages/ui/dist/assets/index-BCb0Nju4.js +1775 -0
- package/packages/ui/dist/assets/index-CjvcQefO.js +1 -0
- package/packages/ui/dist/assets/index-D1lgDFZV.js +16 -0
- package/packages/ui/dist/assets/index-DDKDa0s2.css +1 -0
- package/packages/ui/dist/assets/index-DQ44LBvq.js +395 -0
- package/packages/ui/dist/assets/index-Drc17uEc.js +1 -0
- package/packages/ui/dist/assets/index-c8ZmMTds.js +1 -0
- package/packages/ui/dist/assets/index.es-BhDQmlR4.js +26 -0
- package/packages/ui/dist/assets/info-CAKKH6T2.js +3 -0
- package/packages/ui/dist/assets/info-circle-CHV1idfy.js +12 -0
- package/packages/ui/dist/assets/ink-FZMYZWHG-62p-5IK5.js +1 -0
- package/packages/ui/dist/assets/ja_JP-ZRMWJV3I-DXbifiMm.js +1519 -0
- package/packages/ui/dist/assets/kaia-65D2U3PU-JmuLQ4gC.js +1 -0
- package/packages/ui/dist/assets/ko_KR-FR54RFUG-upinSHjQ.js +1519 -0
- package/packages/ui/dist/assets/lightbulb-ew10LUMl.js +3 -0
- package/packages/ui/dist/assets/linea-QRMVQ5DY-DuI3vv0d.js +1 -0
- package/packages/ui/dist/assets/login-UP3DZBGS-Db_wM5oQ.js +1 -0
- package/packages/ui/dist/assets/mail-CACYeWXj.js +8 -0
- package/packages/ui/dist/assets/manta-SI27YFEJ-CpVOKa06.js +1 -0
- package/packages/ui/dist/assets/mantle-CKIUT334-DR2WgqzU.js +1 -0
- package/packages/ui/dist/assets/metaMaskWallet-EI6MED72-D5HFOsnz.js +1 -0
- package/packages/ui/dist/assets/metamask-sdk-BUYu4RDE.js +542 -0
- package/packages/ui/dist/assets/mobile-DX601q1y.js +9 -0
- package/packages/ui/dist/assets/monad-4KWC6TSS-DVXSkpiz.js +1 -0
- package/packages/ui/dist/assets/more-CQGeX45N.js +11 -0
- package/packages/ui/dist/assets/ms_MY-EZSGYYYQ-4cPLK-3L.js +1519 -0
- package/packages/ui/dist/assets/native-CJ5et6AR.js +1 -0
- package/packages/ui/dist/assets/network-placeholder-BQw8E4X-.js +14 -0
- package/packages/ui/dist/assets/nftPlaceholder-CifJ2CzA.js +8 -0
- package/packages/ui/dist/assets/off-B6oUArCZ.js +8 -0
- package/packages/ui/dist/assets/optimism-HAF2GUT7-ec6Nqxs9.js +1 -0
- package/packages/ui/dist/assets/parseSignature-DjWIdHkx.js +1 -0
- package/packages/ui/dist/assets/play-store-Kq51oh3r.js +32 -0
- package/packages/ui/dist/assets/plus-BxZxVpff.js +13 -0
- package/packages/ui/dist/assets/polygon-WW6ZI7PM-DXlmm4L1.js +1 -0
- package/packages/ui/dist/assets/pt_BR-JQFQ3P4L-DOHfdcA2.js +1519 -0
- package/packages/ui/dist/assets/qr-code-CSBFpyhP.js +6 -0
- package/packages/ui/dist/assets/rainbowWallet-O26YNBMX-DUhYus-9.js +1 -0
- package/packages/ui/dist/assets/recycle-horizontal-D0HyLkot.js +9 -0
- package/packages/ui/dist/assets/refresh-BAQo228i.js +8 -0
- package/packages/ui/dist/assets/refresh-S4T5V5GX-CwqIaaxK.js +1 -0
- package/packages/ui/dist/assets/reown-logo-DeUbwRp6.js +12 -0
- package/packages/ui/dist/assets/ronin-EMCPYXZT-N-QBHZdV.js +1 -0
- package/packages/ui/dist/assets/ru_RU-Z42UEJBP-Cvb2oWxQ.js +1519 -0
- package/packages/ui/dist/assets/safeWallet-5MNKTR5Z-D-5imDLD.js +1 -0
- package/packages/ui/dist/assets/sanko-RHQYXGM5-OX010CbN.js +1 -0
- package/packages/ui/dist/assets/scan-4UYSQ56Q-CjMz6-XC.js +1 -0
- package/packages/ui/dist/assets/scroll-5OBGQVOV-DJFECiai.js +1 -0
- package/packages/ui/dist/assets/search-C8Sd0Mpz.js +8 -0
- package/packages/ui/dist/assets/secp256k1-BujG3JoP.js +1 -0
- package/packages/ui/dist/assets/send-B0JwUp6Q.js +15 -0
- package/packages/ui/dist/assets/sign-A7IJEUT5-CGsRnPrd.js +1 -0
- package/packages/ui/dist/assets/superposition-HG6MMR2Y-bRkgatRO.js +1 -0
- package/packages/ui/dist/assets/swapHorizontal-B2k5yDqc.js +8 -0
- package/packages/ui/dist/assets/swapHorizontalBold-yQqq0yPi.js +8 -0
- package/packages/ui/dist/assets/swapHorizontalMedium-NafYmdDj.js +16 -0
- package/packages/ui/dist/assets/swapHorizontalRoundedBold-BUn0GwEK.js +8 -0
- package/packages/ui/dist/assets/swapVertical-Be1m6suD.js +8 -0
- package/packages/ui/dist/assets/telegram-D-u7QHT5.js +16 -0
- package/packages/ui/dist/assets/th_TH-4YB4VSB2-BUipNP-V.js +1519 -0
- package/packages/ui/dist/assets/three-dots-B6Y4DFOR.js +5 -0
- package/packages/ui/dist/assets/tr_TR-5FKHPPIO-D5jTpIm9.js +1519 -0
- package/packages/ui/dist/assets/twitch-DSy1rhWQ.js +18 -0
- package/packages/ui/dist/assets/twitterIcon-tac1plSa.js +6 -0
- package/packages/ui/dist/assets/uk_UA-ZD4IBC52-DgnQrpzl.js +1519 -0
- package/packages/ui/dist/assets/unichain-C5BWO2ZY-BfguYsnu.js +1 -0
- package/packages/ui/dist/assets/verify-6MylluBY.js +8 -0
- package/packages/ui/dist/assets/verify-filled-CZc0otb8.js +8 -0
- package/packages/ui/dist/assets/vi_VN-5EVRZKLY-x078672g.js +1519 -0
- package/packages/ui/dist/assets/w3m-modal-DbT03Pyz.js +642 -0
- package/packages/ui/dist/assets/wallet-473-ObZE.js +8 -0
- package/packages/ui/dist/assets/wallet-placeholder-B9h3WvTk.js +14 -0
- package/packages/ui/dist/assets/walletConnectWallet-YHWKVTDY-D3lyiczV.js +1 -0
- package/packages/ui/dist/assets/walletconnect-5GHIf5FR.js +30 -0
- package/packages/ui/dist/assets/warning-circle-8A009Dx3.js +12 -0
- package/packages/ui/dist/assets/x-B4jK8e8X.js +12 -0
- package/packages/ui/dist/assets/xdc-KJ3TDBYO-DNV6zchh.js +1 -0
- package/packages/ui/dist/assets/zetachain-TLDS5IPW-Udhyw16T.js +1 -0
- package/packages/ui/dist/assets/zh_CN-4XK5YJPR-Bt6Yz5Ek.js +1519 -0
- package/packages/ui/dist/assets/zh_HK-N4YN2WSI-Cvzl1V16.js +1519 -0
- package/packages/ui/dist/assets/zh_TW-CNCRXH6Z-BNelatfN.js +1519 -0
- package/packages/ui/dist/assets/zksync-DH7HK5U4-Dt4usFw6.js +1 -0
- package/packages/ui/dist/assets/zora-FYL5H3IO-iB4wygST.js +1 -0
- package/packages/ui/dist/index.html +14 -0
- package/templates/default/AGENTS.md +18 -1
|
@@ -35278,11 +35278,6 @@ function getChain(chainId) {
|
|
|
35278
35278
|
return config;
|
|
35279
35279
|
}
|
|
35280
35280
|
|
|
35281
|
-
// src/lib/io.ts
|
|
35282
|
-
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
35283
|
-
var import_node_path = __toESM(require("node:path"), 1);
|
|
35284
|
-
var import_node_readline = require("node:readline");
|
|
35285
|
-
|
|
35286
35281
|
// ../sdk/dist/client.js
|
|
35287
35282
|
init_esm2();
|
|
35288
35283
|
|
|
@@ -37727,6 +37722,46 @@ function buildSafeSetupInitializer(params) {
|
|
|
37727
37722
|
function buildApprovedHashSignature(owner2) {
|
|
37728
37723
|
return encodePacked(["bytes32", "bytes32", "uint8"], [pad(owner2, { size: 32 }), pad("0x", { size: 32 }), 1]);
|
|
37729
37724
|
}
|
|
37725
|
+
var safeProxyFactoryAbi = [
|
|
37726
|
+
{
|
|
37727
|
+
type: "function",
|
|
37728
|
+
name: "proxyCreationCode",
|
|
37729
|
+
stateMutability: "pure",
|
|
37730
|
+
inputs: [],
|
|
37731
|
+
outputs: [{ name: "", type: "bytes" }]
|
|
37732
|
+
}
|
|
37733
|
+
];
|
|
37734
|
+
function computeSafeProxyAddress(params) {
|
|
37735
|
+
const { initializer, saltNonce, proxyCreationCode } = params;
|
|
37736
|
+
const initCodeHash = keccak256(concat([
|
|
37737
|
+
proxyCreationCode,
|
|
37738
|
+
encodeAbiParameters([{ type: "address" }], [SAFE_V141.singletonL2])
|
|
37739
|
+
]));
|
|
37740
|
+
const salt = keccak256(encodePacked(["bytes32", "uint256"], [keccak256(initializer), saltNonce]));
|
|
37741
|
+
return getCreate2Address({
|
|
37742
|
+
from: SAFE_V141.proxyFactory,
|
|
37743
|
+
salt,
|
|
37744
|
+
bytecodeHash: initCodeHash
|
|
37745
|
+
});
|
|
37746
|
+
}
|
|
37747
|
+
function computeKernelBoundSalt(params) {
|
|
37748
|
+
const { saltNonce, deployer, permissionSigner, manager, feePolicy } = params;
|
|
37749
|
+
return BigInt(keccak256(encodeAbiParameters([
|
|
37750
|
+
{ type: "uint256" },
|
|
37751
|
+
{ type: "address" },
|
|
37752
|
+
{ type: "address" },
|
|
37753
|
+
{ type: "address" },
|
|
37754
|
+
{ type: "address" }
|
|
37755
|
+
], [saltNonce, deployer, permissionSigner, manager, feePolicy])));
|
|
37756
|
+
}
|
|
37757
|
+
function computeSailSmaAddress(params) {
|
|
37758
|
+
const boundSalt = computeKernelBoundSalt(params);
|
|
37759
|
+
return computeSafeProxyAddress({
|
|
37760
|
+
initializer: params.initializer,
|
|
37761
|
+
saltNonce: boundSalt,
|
|
37762
|
+
proxyCreationCode: params.proxyCreationCode
|
|
37763
|
+
});
|
|
37764
|
+
}
|
|
37730
37765
|
function encodeSetManager(newManager) {
|
|
37731
37766
|
return encodeFunctionData({
|
|
37732
37767
|
abi: setManagerAbi,
|
|
@@ -37832,195 +37867,551 @@ async function estimatePermissionFee(publicClient, governance, permission) {
|
|
|
37832
37867
|
var SAIL_INTELLIGENCE_BASE_URL = "https://api.sail.money";
|
|
37833
37868
|
var SAIL_INTELLIGENCE_DOCS_URL = "https://api.sail.money/docs";
|
|
37834
37869
|
|
|
37835
|
-
// src/
|
|
37870
|
+
// src/commands/account.ts
|
|
37836
37871
|
init_esm2();
|
|
37837
|
-
|
|
37838
|
-
|
|
37839
|
-
|
|
37840
|
-
|
|
37841
|
-
|
|
37842
|
-
|
|
37843
|
-
|
|
37844
|
-
|
|
37845
|
-
|
|
37846
|
-
|
|
37847
|
-
|
|
37872
|
+
|
|
37873
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/contracts.js
|
|
37874
|
+
var contracts = {
|
|
37875
|
+
gasPriceOracle: { address: "0x420000000000000000000000000000000000000F" },
|
|
37876
|
+
l1Block: { address: "0x4200000000000000000000000000000000000015" },
|
|
37877
|
+
l2CrossDomainMessenger: {
|
|
37878
|
+
address: "0x4200000000000000000000000000000000000007"
|
|
37879
|
+
},
|
|
37880
|
+
l2Erc721Bridge: { address: "0x4200000000000000000000000000000000000014" },
|
|
37881
|
+
l2StandardBridge: { address: "0x4200000000000000000000000000000000000010" },
|
|
37882
|
+
l2ToL1MessagePasser: {
|
|
37883
|
+
address: "0x4200000000000000000000000000000000000016"
|
|
37848
37884
|
}
|
|
37885
|
+
};
|
|
37886
|
+
|
|
37887
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/formatters.js
|
|
37888
|
+
init_fromHex();
|
|
37889
|
+
init_block2();
|
|
37890
|
+
init_transaction2();
|
|
37891
|
+
init_transactionReceipt();
|
|
37892
|
+
var formatters = {
|
|
37893
|
+
block: /* @__PURE__ */ defineBlock({
|
|
37894
|
+
format(args) {
|
|
37895
|
+
const transactions = args.transactions?.map((transaction) => {
|
|
37896
|
+
if (typeof transaction === "string")
|
|
37897
|
+
return transaction;
|
|
37898
|
+
const formatted = formatTransaction(transaction);
|
|
37899
|
+
if (formatted.typeHex === "0x7e") {
|
|
37900
|
+
formatted.isSystemTx = transaction.isSystemTx;
|
|
37901
|
+
formatted.mint = transaction.mint ? hexToBigInt(transaction.mint) : void 0;
|
|
37902
|
+
formatted.sourceHash = transaction.sourceHash;
|
|
37903
|
+
formatted.type = "deposit";
|
|
37904
|
+
}
|
|
37905
|
+
return formatted;
|
|
37906
|
+
});
|
|
37907
|
+
return {
|
|
37908
|
+
transactions,
|
|
37909
|
+
stateRoot: args.stateRoot
|
|
37910
|
+
};
|
|
37911
|
+
}
|
|
37912
|
+
}),
|
|
37913
|
+
transaction: /* @__PURE__ */ defineTransaction({
|
|
37914
|
+
format(args) {
|
|
37915
|
+
const transaction = {};
|
|
37916
|
+
if (args.type === "0x7e") {
|
|
37917
|
+
transaction.isSystemTx = args.isSystemTx;
|
|
37918
|
+
transaction.mint = args.mint ? hexToBigInt(args.mint) : void 0;
|
|
37919
|
+
transaction.sourceHash = args.sourceHash;
|
|
37920
|
+
transaction.type = "deposit";
|
|
37921
|
+
}
|
|
37922
|
+
return transaction;
|
|
37923
|
+
}
|
|
37924
|
+
}),
|
|
37925
|
+
transactionReceipt: /* @__PURE__ */ defineTransactionReceipt({
|
|
37926
|
+
format(args) {
|
|
37927
|
+
return {
|
|
37928
|
+
l1GasPrice: args.l1GasPrice ? hexToBigInt(args.l1GasPrice) : null,
|
|
37929
|
+
l1GasUsed: args.l1GasUsed ? hexToBigInt(args.l1GasUsed) : null,
|
|
37930
|
+
l1Fee: args.l1Fee ? hexToBigInt(args.l1Fee) : null,
|
|
37931
|
+
l1FeeScalar: args.l1FeeScalar ? Number(args.l1FeeScalar) : null
|
|
37932
|
+
};
|
|
37933
|
+
}
|
|
37934
|
+
})
|
|
37935
|
+
};
|
|
37936
|
+
|
|
37937
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/serializers.js
|
|
37938
|
+
init_address();
|
|
37939
|
+
init_isAddress();
|
|
37940
|
+
init_concat();
|
|
37941
|
+
init_toHex();
|
|
37942
|
+
init_toRlp();
|
|
37943
|
+
init_serializeTransaction();
|
|
37944
|
+
function serializeTransaction2(transaction, signature) {
|
|
37945
|
+
if (isDeposit(transaction))
|
|
37946
|
+
return serializeTransactionDeposit(transaction);
|
|
37947
|
+
return serializeTransaction(transaction, signature);
|
|
37849
37948
|
}
|
|
37850
|
-
|
|
37851
|
-
|
|
37852
|
-
|
|
37853
|
-
|
|
37949
|
+
var serializers = {
|
|
37950
|
+
transaction: serializeTransaction2
|
|
37951
|
+
};
|
|
37952
|
+
function serializeTransactionDeposit(transaction) {
|
|
37953
|
+
assertTransactionDeposit(transaction);
|
|
37954
|
+
const { sourceHash, data, from: from14, gas, isSystemTx, mint, to, value } = transaction;
|
|
37955
|
+
const serializedTransaction = [
|
|
37956
|
+
sourceHash,
|
|
37957
|
+
from14,
|
|
37958
|
+
to ?? "0x",
|
|
37959
|
+
mint ? toHex(mint) : "0x",
|
|
37960
|
+
value ? toHex(value) : "0x",
|
|
37961
|
+
gas ? toHex(gas) : "0x",
|
|
37962
|
+
isSystemTx ? "0x1" : "0x",
|
|
37963
|
+
data ?? "0x"
|
|
37964
|
+
];
|
|
37965
|
+
return concatHex([
|
|
37966
|
+
"0x7e",
|
|
37967
|
+
toRlp(serializedTransaction)
|
|
37968
|
+
]);
|
|
37854
37969
|
}
|
|
37855
|
-
function
|
|
37856
|
-
|
|
37970
|
+
function isDeposit(transaction) {
|
|
37971
|
+
if (transaction.type === "deposit")
|
|
37972
|
+
return true;
|
|
37973
|
+
if (typeof transaction.sourceHash !== "undefined")
|
|
37974
|
+
return true;
|
|
37975
|
+
return false;
|
|
37857
37976
|
}
|
|
37858
|
-
function
|
|
37859
|
-
|
|
37977
|
+
function assertTransactionDeposit(transaction) {
|
|
37978
|
+
const { from: from14, to } = transaction;
|
|
37979
|
+
if (from14 && !isAddress(from14))
|
|
37980
|
+
throw new InvalidAddressError({ address: from14 });
|
|
37981
|
+
if (to && !isAddress(to))
|
|
37982
|
+
throw new InvalidAddressError({ address: to });
|
|
37860
37983
|
}
|
|
37861
|
-
|
|
37862
|
-
|
|
37863
|
-
|
|
37864
|
-
|
|
37865
|
-
|
|
37866
|
-
|
|
37867
|
-
|
|
37868
|
-
|
|
37869
|
-
|
|
37870
|
-
|
|
37871
|
-
|
|
37984
|
+
|
|
37985
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/chainConfig.js
|
|
37986
|
+
var chainConfig = {
|
|
37987
|
+
blockTime: 2e3,
|
|
37988
|
+
contracts,
|
|
37989
|
+
formatters,
|
|
37990
|
+
serializers
|
|
37991
|
+
};
|
|
37992
|
+
|
|
37993
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/arbitrum.js
|
|
37994
|
+
init_defineChain();
|
|
37995
|
+
var arbitrum = /* @__PURE__ */ defineChain({
|
|
37996
|
+
id: 42161,
|
|
37997
|
+
name: "Arbitrum One",
|
|
37998
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
37999
|
+
blockTime: 250,
|
|
38000
|
+
rpcUrls: {
|
|
38001
|
+
default: {
|
|
38002
|
+
http: ["https://arb1.arbitrum.io/rpc"]
|
|
37872
38003
|
}
|
|
37873
|
-
}
|
|
37874
|
-
|
|
37875
|
-
|
|
37876
|
-
|
|
37877
|
-
|
|
37878
|
-
|
|
37879
|
-
|
|
37880
|
-
|
|
37881
|
-
|
|
37882
|
-
|
|
37883
|
-
|
|
37884
|
-
|
|
37885
|
-
const key = line.slice(0, eq).trim();
|
|
37886
|
-
let value = line.slice(eq + 1).trim();
|
|
37887
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
37888
|
-
value = value.slice(1, -1);
|
|
38004
|
+
},
|
|
38005
|
+
blockExplorers: {
|
|
38006
|
+
default: {
|
|
38007
|
+
name: "Arbiscan",
|
|
38008
|
+
url: "https://arbiscan.io",
|
|
38009
|
+
apiUrl: "https://api.arbiscan.io/api"
|
|
38010
|
+
}
|
|
38011
|
+
},
|
|
38012
|
+
contracts: {
|
|
38013
|
+
multicall3: {
|
|
38014
|
+
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38015
|
+
blockCreated: 7654707
|
|
37889
38016
|
}
|
|
37890
|
-
out[key] = value;
|
|
37891
|
-
}
|
|
37892
|
-
return out;
|
|
37893
|
-
}
|
|
37894
|
-
function checksum4(address) {
|
|
37895
|
-
return getAddress(address);
|
|
37896
|
-
}
|
|
37897
|
-
function makeClient(chainId) {
|
|
37898
|
-
const env = parseEnvFile(sailPath(".env.local"));
|
|
37899
|
-
const rpcUrl = env["RPC_URL"] ?? process.env["RPC_URL"] ?? "http://localhost:8545";
|
|
37900
|
-
return new SailorClient({ rpcUrl, chainId });
|
|
37901
|
-
}
|
|
37902
|
-
var sharedRl = null;
|
|
37903
|
-
var muted = false;
|
|
37904
|
-
var lineQueue = [];
|
|
37905
|
-
var waiters = [];
|
|
37906
|
-
var inputClosed = false;
|
|
37907
|
-
function getRl() {
|
|
37908
|
-
if (sharedRl) return sharedRl;
|
|
37909
|
-
const isTty = process.stdin.isTTY === true;
|
|
37910
|
-
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stdout, terminal: isTty });
|
|
37911
|
-
if (isTty) {
|
|
37912
|
-
const muteable = rl;
|
|
37913
|
-
const original = muteable._writeToOutput.bind(rl);
|
|
37914
|
-
muteable._writeToOutput = (text) => {
|
|
37915
|
-
if (!muted) original(text);
|
|
37916
|
-
};
|
|
37917
38017
|
}
|
|
37918
|
-
|
|
37919
|
-
|
|
37920
|
-
|
|
37921
|
-
|
|
37922
|
-
|
|
37923
|
-
|
|
37924
|
-
|
|
37925
|
-
|
|
37926
|
-
|
|
37927
|
-
|
|
38018
|
+
});
|
|
38019
|
+
|
|
38020
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/base.js
|
|
38021
|
+
init_defineChain();
|
|
38022
|
+
var sourceId = 1;
|
|
38023
|
+
var base = /* @__PURE__ */ defineChain({
|
|
38024
|
+
...chainConfig,
|
|
38025
|
+
id: 8453,
|
|
38026
|
+
name: "Base",
|
|
38027
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
38028
|
+
rpcUrls: {
|
|
38029
|
+
default: {
|
|
38030
|
+
http: ["https://mainnet.base.org"]
|
|
37928
38031
|
}
|
|
37929
|
-
}
|
|
37930
|
-
|
|
37931
|
-
|
|
37932
|
-
|
|
37933
|
-
|
|
37934
|
-
|
|
37935
|
-
|
|
37936
|
-
|
|
37937
|
-
|
|
37938
|
-
|
|
37939
|
-
|
|
37940
|
-
|
|
37941
|
-
|
|
37942
|
-
|
|
37943
|
-
|
|
38032
|
+
},
|
|
38033
|
+
blockExplorers: {
|
|
38034
|
+
default: {
|
|
38035
|
+
name: "Basescan",
|
|
38036
|
+
url: "https://basescan.org",
|
|
38037
|
+
apiUrl: "https://api.basescan.org/api"
|
|
38038
|
+
}
|
|
38039
|
+
},
|
|
38040
|
+
contracts: {
|
|
38041
|
+
...chainConfig.contracts,
|
|
38042
|
+
disputeGameFactory: {
|
|
38043
|
+
[sourceId]: {
|
|
38044
|
+
address: "0x43edB88C4B80fDD2AdFF2412A7BebF9dF42cB40e"
|
|
38045
|
+
}
|
|
38046
|
+
},
|
|
38047
|
+
l2OutputOracle: {
|
|
38048
|
+
[sourceId]: {
|
|
38049
|
+
address: "0x56315b90c40730925ec5485cf004d835058518A0"
|
|
38050
|
+
}
|
|
38051
|
+
},
|
|
38052
|
+
multicall3: {
|
|
38053
|
+
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38054
|
+
blockCreated: 5022
|
|
38055
|
+
},
|
|
38056
|
+
portal: {
|
|
38057
|
+
[sourceId]: {
|
|
38058
|
+
address: "0x49048044D57e1C92A77f79988d21Fa8fAF74E97e",
|
|
38059
|
+
blockCreated: 17482143
|
|
38060
|
+
}
|
|
38061
|
+
},
|
|
38062
|
+
l1StandardBridge: {
|
|
38063
|
+
[sourceId]: {
|
|
38064
|
+
address: "0x3154Cf16ccdb4C6d922629664174b904d80F2C35",
|
|
38065
|
+
blockCreated: 17482143
|
|
38066
|
+
}
|
|
38067
|
+
}
|
|
38068
|
+
},
|
|
38069
|
+
sourceId
|
|
38070
|
+
});
|
|
38071
|
+
var basePreconf = /* @__PURE__ */ defineChain({
|
|
38072
|
+
...base,
|
|
38073
|
+
experimental_preconfirmationTime: 200,
|
|
38074
|
+
rpcUrls: {
|
|
38075
|
+
default: {
|
|
38076
|
+
http: ["https://mainnet-preconf.base.org"]
|
|
37944
38077
|
}
|
|
37945
|
-
});
|
|
37946
|
-
}
|
|
37947
|
-
function closePrompts() {
|
|
37948
|
-
if (sharedRl) {
|
|
37949
|
-
sharedRl.close();
|
|
37950
|
-
sharedRl = null;
|
|
37951
|
-
}
|
|
37952
|
-
}
|
|
37953
|
-
async function prompt(question, def) {
|
|
37954
|
-
const suffix = def !== void 0 ? ` (${def})` : "";
|
|
37955
|
-
const answer = await ask(`${question}${suffix}: `);
|
|
37956
|
-
const trimmed = answer.trim();
|
|
37957
|
-
return trimmed === "" && def !== void 0 ? def : trimmed;
|
|
37958
|
-
}
|
|
37959
|
-
async function confirm(question) {
|
|
37960
|
-
const answer = (await prompt(`${question} (y/N)`)).toLowerCase();
|
|
37961
|
-
return answer === "y" || answer === "yes";
|
|
37962
|
-
}
|
|
37963
|
-
async function promptAddress(label, def) {
|
|
37964
|
-
for (let attempt = 0; attempt < 5; attempt++) {
|
|
37965
|
-
const raw = await prompt(label, def);
|
|
37966
|
-
if (isAddress(raw)) return getAddress(raw);
|
|
37967
|
-
console.log(` "${raw}" is not a valid EVM address \u2014 try again.`);
|
|
37968
|
-
}
|
|
37969
|
-
throw new Error(`No valid address provided for: ${label}`);
|
|
37970
|
-
}
|
|
37971
|
-
async function promptHidden(question) {
|
|
37972
|
-
const isTty = process.stdin.isTTY === true;
|
|
37973
|
-
if (isTty) muted = true;
|
|
37974
|
-
const answer = await ask(`${question}: `);
|
|
37975
|
-
if (isTty) {
|
|
37976
|
-
muted = false;
|
|
37977
|
-
process.stdout.write("\n");
|
|
37978
38078
|
}
|
|
37979
|
-
|
|
37980
|
-
}
|
|
38079
|
+
});
|
|
37981
38080
|
|
|
37982
|
-
//
|
|
37983
|
-
|
|
37984
|
-
|
|
37985
|
-
|
|
37986
|
-
|
|
37987
|
-
|
|
37988
|
-
|
|
37989
|
-
|
|
37990
|
-
|
|
38081
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/baseSepolia.js
|
|
38082
|
+
init_defineChain();
|
|
38083
|
+
var sourceId2 = 11155111;
|
|
38084
|
+
var baseSepolia = /* @__PURE__ */ defineChain({
|
|
38085
|
+
...chainConfig,
|
|
38086
|
+
id: 84532,
|
|
38087
|
+
network: "base-sepolia",
|
|
38088
|
+
name: "Base Sepolia",
|
|
38089
|
+
nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 },
|
|
38090
|
+
rpcUrls: {
|
|
38091
|
+
default: {
|
|
38092
|
+
http: ["https://sepolia.base.org"]
|
|
38093
|
+
}
|
|
38094
|
+
},
|
|
38095
|
+
blockExplorers: {
|
|
38096
|
+
default: {
|
|
38097
|
+
name: "Basescan",
|
|
38098
|
+
url: "https://sepolia.basescan.org",
|
|
38099
|
+
apiUrl: "https://api-sepolia.basescan.org/api"
|
|
38100
|
+
}
|
|
38101
|
+
},
|
|
38102
|
+
contracts: {
|
|
38103
|
+
...chainConfig.contracts,
|
|
38104
|
+
disputeGameFactory: {
|
|
38105
|
+
[sourceId2]: {
|
|
38106
|
+
address: "0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1"
|
|
38107
|
+
}
|
|
38108
|
+
},
|
|
38109
|
+
l2OutputOracle: {
|
|
38110
|
+
[sourceId2]: {
|
|
38111
|
+
address: "0x84457ca9D0163FbC4bbfe4Dfbb20ba46e48DF254"
|
|
38112
|
+
}
|
|
38113
|
+
},
|
|
38114
|
+
portal: {
|
|
38115
|
+
[sourceId2]: {
|
|
38116
|
+
address: "0x49f53e41452c74589e85ca1677426ba426459e85",
|
|
38117
|
+
blockCreated: 4446677
|
|
38118
|
+
}
|
|
38119
|
+
},
|
|
38120
|
+
l1StandardBridge: {
|
|
38121
|
+
[sourceId2]: {
|
|
38122
|
+
address: "0xfd0Bf71F60660E2f608ed56e1659C450eB113120",
|
|
38123
|
+
blockCreated: 4446677
|
|
38124
|
+
}
|
|
38125
|
+
},
|
|
38126
|
+
multicall3: {
|
|
38127
|
+
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38128
|
+
blockCreated: 1059647
|
|
38129
|
+
}
|
|
38130
|
+
},
|
|
38131
|
+
testnet: true,
|
|
38132
|
+
sourceId: sourceId2
|
|
38133
|
+
});
|
|
38134
|
+
var baseSepoliaPreconf = /* @__PURE__ */ defineChain({
|
|
38135
|
+
...baseSepolia,
|
|
38136
|
+
experimental_preconfirmationTime: 200,
|
|
38137
|
+
rpcUrls: {
|
|
38138
|
+
default: {
|
|
38139
|
+
http: ["https://sepolia-preconf.base.org"]
|
|
38140
|
+
}
|
|
37991
38141
|
}
|
|
37992
|
-
|
|
37993
|
-
|
|
37994
|
-
|
|
37995
|
-
|
|
38142
|
+
});
|
|
38143
|
+
|
|
38144
|
+
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/unichain.js
|
|
38145
|
+
init_defineChain();
|
|
38146
|
+
var sourceId3 = 1;
|
|
38147
|
+
var unichain = /* @__PURE__ */ defineChain({
|
|
38148
|
+
...chainConfig,
|
|
38149
|
+
id: 130,
|
|
38150
|
+
name: "Unichain",
|
|
38151
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
38152
|
+
blockTime: 1e3,
|
|
38153
|
+
rpcUrls: {
|
|
38154
|
+
default: {
|
|
38155
|
+
http: ["https://mainnet.unichain.org/"]
|
|
38156
|
+
}
|
|
38157
|
+
},
|
|
38158
|
+
blockExplorers: {
|
|
38159
|
+
default: {
|
|
38160
|
+
name: "Uniscan",
|
|
38161
|
+
url: "https://uniscan.xyz",
|
|
38162
|
+
apiUrl: "https://api.uniscan.xyz/api"
|
|
38163
|
+
}
|
|
38164
|
+
},
|
|
38165
|
+
contracts: {
|
|
38166
|
+
...chainConfig.contracts,
|
|
38167
|
+
multicall3: {
|
|
38168
|
+
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38169
|
+
blockCreated: 0
|
|
38170
|
+
},
|
|
38171
|
+
disputeGameFactory: {
|
|
38172
|
+
[sourceId3]: {
|
|
38173
|
+
address: "0x2F12d621a16e2d3285929C9996f478508951dFe4"
|
|
38174
|
+
}
|
|
38175
|
+
},
|
|
38176
|
+
portal: {
|
|
38177
|
+
[sourceId3]: {
|
|
38178
|
+
address: "0x0bd48f6B86a26D3a217d0Fa6FfE2B491B956A7a2"
|
|
38179
|
+
}
|
|
38180
|
+
},
|
|
38181
|
+
l1StandardBridge: {
|
|
38182
|
+
[sourceId3]: {
|
|
38183
|
+
address: "0x81014F44b0a345033bB2b3B21C7a1A308B35fEeA"
|
|
38184
|
+
}
|
|
38185
|
+
}
|
|
38186
|
+
},
|
|
38187
|
+
sourceId: sourceId3
|
|
38188
|
+
});
|
|
38189
|
+
|
|
38190
|
+
// src/lib/io.ts
|
|
38191
|
+
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
38192
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
38193
|
+
var import_node_readline = require("node:readline");
|
|
38194
|
+
init_esm2();
|
|
38195
|
+
function sailDir() {
|
|
38196
|
+
return import_node_path.default.join(process.cwd(), ".sail");
|
|
37996
38197
|
}
|
|
37997
|
-
function
|
|
37998
|
-
return
|
|
38198
|
+
function sailPath(...segments) {
|
|
38199
|
+
return import_node_path.default.join(sailDir(), ...segments);
|
|
37999
38200
|
}
|
|
38000
|
-
function
|
|
38001
|
-
|
|
38002
|
-
return
|
|
38201
|
+
function readJsonFile(filePath) {
|
|
38202
|
+
try {
|
|
38203
|
+
return JSON.parse(import_node_fs2.default.readFileSync(filePath, "utf-8"));
|
|
38204
|
+
} catch {
|
|
38205
|
+
return null;
|
|
38003
38206
|
}
|
|
38004
|
-
return sailPath("keys", `${role}.json`);
|
|
38005
38207
|
}
|
|
38006
|
-
function
|
|
38007
|
-
|
|
38208
|
+
function writeJsonFile(filePath, data) {
|
|
38209
|
+
import_node_fs2.default.mkdirSync(import_node_path.default.dirname(filePath), { recursive: true });
|
|
38210
|
+
import_node_fs2.default.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}
|
|
38211
|
+
`);
|
|
38008
38212
|
}
|
|
38009
|
-
function
|
|
38010
|
-
|
|
38011
|
-
const perSma = keyPath(role, safe);
|
|
38012
|
-
if (fileExists(perSma)) return perSma;
|
|
38013
|
-
const legacy = legacyKeyPath(role, safe);
|
|
38014
|
-
if (fileExists(legacy)) return legacy;
|
|
38015
|
-
}
|
|
38016
|
-
return keyPath(role);
|
|
38213
|
+
function fileExists(filePath) {
|
|
38214
|
+
return import_node_fs2.default.existsSync(filePath);
|
|
38017
38215
|
}
|
|
38018
|
-
function
|
|
38019
|
-
return
|
|
38216
|
+
function nowIso() {
|
|
38217
|
+
return `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19)}Z`;
|
|
38020
38218
|
}
|
|
38021
|
-
|
|
38022
|
-
const
|
|
38023
|
-
|
|
38219
|
+
function appendActivity(event, baseSailDir = sailDir()) {
|
|
38220
|
+
const filePath = import_node_path.default.join(baseSailDir, "activity.jsonl");
|
|
38221
|
+
import_node_fs2.default.mkdirSync(import_node_path.default.dirname(filePath), { recursive: true });
|
|
38222
|
+
let tagged = event;
|
|
38223
|
+
if (!("safe" in event)) {
|
|
38224
|
+
try {
|
|
38225
|
+
const account2 = JSON.parse(
|
|
38226
|
+
import_node_fs2.default.readFileSync(import_node_path.default.join(baseSailDir, "account.json"), "utf-8")
|
|
38227
|
+
);
|
|
38228
|
+
if (account2?.safe) tagged = { ...event, safe: account2.safe };
|
|
38229
|
+
} catch {
|
|
38230
|
+
}
|
|
38231
|
+
}
|
|
38232
|
+
import_node_fs2.default.appendFileSync(filePath, `${JSON.stringify(tagged)}
|
|
38233
|
+
`);
|
|
38234
|
+
}
|
|
38235
|
+
function parseEnvFile(filePath) {
|
|
38236
|
+
const out = {};
|
|
38237
|
+
if (!import_node_fs2.default.existsSync(filePath)) return out;
|
|
38238
|
+
for (const rawLine of import_node_fs2.default.readFileSync(filePath, "utf-8").split("\n")) {
|
|
38239
|
+
const line = rawLine.trim();
|
|
38240
|
+
if (line === "" || line.startsWith("#")) continue;
|
|
38241
|
+
const eq = line.indexOf("=");
|
|
38242
|
+
if (eq < 0) continue;
|
|
38243
|
+
const key = line.slice(0, eq).trim();
|
|
38244
|
+
let value = line.slice(eq + 1).trim();
|
|
38245
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
38246
|
+
value = value.slice(1, -1);
|
|
38247
|
+
}
|
|
38248
|
+
out[key] = value;
|
|
38249
|
+
}
|
|
38250
|
+
return out;
|
|
38251
|
+
}
|
|
38252
|
+
function checksum4(address) {
|
|
38253
|
+
return getAddress(address);
|
|
38254
|
+
}
|
|
38255
|
+
function makeClient(chainId) {
|
|
38256
|
+
const env = parseEnvFile(sailPath(".env.local"));
|
|
38257
|
+
const rpcUrl = env["RPC_URL"] ?? process.env["RPC_URL"] ?? "http://localhost:8545";
|
|
38258
|
+
return new SailorClient({ rpcUrl, chainId });
|
|
38259
|
+
}
|
|
38260
|
+
var sharedRl = null;
|
|
38261
|
+
var muted = false;
|
|
38262
|
+
var lineQueue = [];
|
|
38263
|
+
var waiters = [];
|
|
38264
|
+
var inputClosed = false;
|
|
38265
|
+
function getRl() {
|
|
38266
|
+
if (sharedRl) return sharedRl;
|
|
38267
|
+
const isTty = process.stdin.isTTY === true;
|
|
38268
|
+
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stdout, terminal: isTty });
|
|
38269
|
+
if (isTty) {
|
|
38270
|
+
const muteable = rl;
|
|
38271
|
+
const original = muteable._writeToOutput.bind(rl);
|
|
38272
|
+
muteable._writeToOutput = (text) => {
|
|
38273
|
+
if (!muted) original(text);
|
|
38274
|
+
};
|
|
38275
|
+
}
|
|
38276
|
+
rl.on("line", (line) => {
|
|
38277
|
+
const waiter = waiters.shift();
|
|
38278
|
+
if (waiter) waiter(line);
|
|
38279
|
+
else lineQueue.push(line);
|
|
38280
|
+
});
|
|
38281
|
+
rl.on("close", () => {
|
|
38282
|
+
inputClosed = true;
|
|
38283
|
+
while (waiters.length > 0) {
|
|
38284
|
+
const waiter = waiters.shift();
|
|
38285
|
+
waiter?.("");
|
|
38286
|
+
}
|
|
38287
|
+
});
|
|
38288
|
+
sharedRl = rl;
|
|
38289
|
+
return rl;
|
|
38290
|
+
}
|
|
38291
|
+
function ask(query) {
|
|
38292
|
+
getRl();
|
|
38293
|
+
process.stdout.write(query);
|
|
38294
|
+
return new Promise((resolve3) => {
|
|
38295
|
+
const buffered = lineQueue.shift();
|
|
38296
|
+
if (buffered !== void 0) {
|
|
38297
|
+
resolve3(buffered);
|
|
38298
|
+
} else if (inputClosed) {
|
|
38299
|
+
resolve3("");
|
|
38300
|
+
} else {
|
|
38301
|
+
waiters.push(resolve3);
|
|
38302
|
+
}
|
|
38303
|
+
});
|
|
38304
|
+
}
|
|
38305
|
+
function closePrompts() {
|
|
38306
|
+
if (sharedRl) {
|
|
38307
|
+
sharedRl.close();
|
|
38308
|
+
sharedRl = null;
|
|
38309
|
+
}
|
|
38310
|
+
}
|
|
38311
|
+
async function prompt(question, def) {
|
|
38312
|
+
const suffix = def !== void 0 ? ` (${def})` : "";
|
|
38313
|
+
const answer = await ask(`${question}${suffix}: `);
|
|
38314
|
+
const trimmed = answer.trim();
|
|
38315
|
+
return trimmed === "" && def !== void 0 ? def : trimmed;
|
|
38316
|
+
}
|
|
38317
|
+
async function confirm(question) {
|
|
38318
|
+
const answer = (await prompt(`${question} (y/N)`)).toLowerCase();
|
|
38319
|
+
return answer === "y" || answer === "yes";
|
|
38320
|
+
}
|
|
38321
|
+
async function promptAddress(label, def) {
|
|
38322
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
38323
|
+
const raw = await prompt(label, def);
|
|
38324
|
+
if (isAddress(raw)) return getAddress(raw);
|
|
38325
|
+
console.log(` "${raw}" is not a valid EVM address \u2014 try again.`);
|
|
38326
|
+
}
|
|
38327
|
+
throw new Error(`No valid address provided for: ${label}`);
|
|
38328
|
+
}
|
|
38329
|
+
async function promptHidden(question) {
|
|
38330
|
+
const isTty = process.stdin.isTTY === true;
|
|
38331
|
+
if (isTty) muted = true;
|
|
38332
|
+
const answer = await ask(`${question}: `);
|
|
38333
|
+
if (isTty) {
|
|
38334
|
+
muted = false;
|
|
38335
|
+
process.stdout.write("\n");
|
|
38336
|
+
}
|
|
38337
|
+
return answer;
|
|
38338
|
+
}
|
|
38339
|
+
|
|
38340
|
+
// src/lib/chain.ts
|
|
38341
|
+
var CHAINS = {
|
|
38342
|
+
8453: base,
|
|
38343
|
+
84532: baseSepolia,
|
|
38344
|
+
42161: arbitrum,
|
|
38345
|
+
130: unichain
|
|
38346
|
+
};
|
|
38347
|
+
function getChainById(chainId) {
|
|
38348
|
+
const chain2 = CHAINS[chainId];
|
|
38349
|
+
if (!chain2) {
|
|
38350
|
+
throw new Error(
|
|
38351
|
+
`Unsupported chainId: ${chainId}. Supported: 8453 (Base), 84532 (Base Sepolia), 42161 (Arbitrum), 130 (Unichain)`
|
|
38352
|
+
);
|
|
38353
|
+
}
|
|
38354
|
+
return chain2;
|
|
38355
|
+
}
|
|
38356
|
+
var RPC_ENV_VARS = {
|
|
38357
|
+
8453: "BASE_RPC_URL",
|
|
38358
|
+
84532: "BASE_SEPOLIA_RPC_URL",
|
|
38359
|
+
42161: "ARBITRUM_RPC_URL",
|
|
38360
|
+
130: "UNICHAIN_RPC_URL"
|
|
38361
|
+
};
|
|
38362
|
+
function getRpcUrl(chainId) {
|
|
38363
|
+
const env = parseEnvFile(sailPath(".env.local"));
|
|
38364
|
+
const fromProject = env.RPC_URL;
|
|
38365
|
+
if (fromProject?.trim()) return fromProject.trim();
|
|
38366
|
+
const perChain = RPC_ENV_VARS[chainId];
|
|
38367
|
+
const fromPerChain = perChain ? process.env[perChain] : void 0;
|
|
38368
|
+
if (fromPerChain?.trim()) return fromPerChain.trim();
|
|
38369
|
+
const fromEnv = process.env.RPC_URL;
|
|
38370
|
+
return fromEnv?.trim() ? fromEnv.trim() : void 0;
|
|
38371
|
+
}
|
|
38372
|
+
|
|
38373
|
+
// src/lib/keys.ts
|
|
38374
|
+
var ROLES = ["manager", "permissionSigner"];
|
|
38375
|
+
function normalizeRole(input) {
|
|
38376
|
+
const n = input.trim().toLowerCase().replace(/[-_\s]/g, "");
|
|
38377
|
+
if (n === "manager" || n === "mgr" || n === "m" || n === "agent" || n === "agentwallet") {
|
|
38378
|
+
return "manager";
|
|
38379
|
+
}
|
|
38380
|
+
if (n === "permissionsigner" || n === "signer" || n === "ps" || n === "permission" || n === "mandatesigner" || n === "mandate") {
|
|
38381
|
+
return "permissionSigner";
|
|
38382
|
+
}
|
|
38383
|
+
return null;
|
|
38384
|
+
}
|
|
38385
|
+
function roleLabel(role) {
|
|
38386
|
+
return role === "manager" ? "agent wallet" : "mandate signer";
|
|
38387
|
+
}
|
|
38388
|
+
function safeHex(safe) {
|
|
38389
|
+
return safe.toLowerCase().replace(/^0x/, "").replace(/[^0-9a-f]/g, "");
|
|
38390
|
+
}
|
|
38391
|
+
function keyPath(role, safe) {
|
|
38392
|
+
if (safe) {
|
|
38393
|
+
return sailPath("keys", `${role}-0x${safeHex(safe)}.json`);
|
|
38394
|
+
}
|
|
38395
|
+
return sailPath("keys", `${role}.json`);
|
|
38396
|
+
}
|
|
38397
|
+
function legacyKeyPath(role, safe) {
|
|
38398
|
+
return sailPath("keys", `${role}-${safeHex(safe)}.json`);
|
|
38399
|
+
}
|
|
38400
|
+
function resolveKeyPath(role, safe) {
|
|
38401
|
+
if (safe) {
|
|
38402
|
+
const perSma = keyPath(role, safe);
|
|
38403
|
+
if (fileExists(perSma)) return perSma;
|
|
38404
|
+
const legacy = legacyKeyPath(role, safe);
|
|
38405
|
+
if (fileExists(legacy)) return legacy;
|
|
38406
|
+
}
|
|
38407
|
+
return keyPath(role);
|
|
38408
|
+
}
|
|
38409
|
+
function keyExists(role, safe) {
|
|
38410
|
+
return fileExists(resolveKeyPath(role, safe));
|
|
38411
|
+
}
|
|
38412
|
+
async function loadKeyring(role, safe) {
|
|
38413
|
+
const keystore = readJsonFile(resolveKeyPath(role, safe));
|
|
38414
|
+
if (!keystore) {
|
|
38024
38415
|
throw new Error(
|
|
38025
38416
|
`No ${roleLabel(role)} found.
|
|
38026
38417
|
Run "sailor keys generate" and choose "${roleLabel(role)}" first.`
|
|
@@ -38157,360 +38548,136 @@ SMA created. Address: ${stored.safe}`);
|
|
|
38157
38548
|
console.log(
|
|
38158
38549
|
"\nOn-chain account creation is not wired up in this build yet \u2014\nclient.account.create is a stub until SailKernel is deployed and the\nSDK is connected. Nothing was created on-chain."
|
|
38159
38550
|
);
|
|
38160
|
-
return;
|
|
38161
|
-
}
|
|
38162
|
-
throw err;
|
|
38163
|
-
}
|
|
38164
|
-
}
|
|
38165
|
-
|
|
38166
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/contracts.js
|
|
38167
|
-
var contracts = {
|
|
38168
|
-
gasPriceOracle: { address: "0x420000000000000000000000000000000000000F" },
|
|
38169
|
-
l1Block: { address: "0x4200000000000000000000000000000000000015" },
|
|
38170
|
-
l2CrossDomainMessenger: {
|
|
38171
|
-
address: "0x4200000000000000000000000000000000000007"
|
|
38172
|
-
},
|
|
38173
|
-
l2Erc721Bridge: { address: "0x4200000000000000000000000000000000000014" },
|
|
38174
|
-
l2StandardBridge: { address: "0x4200000000000000000000000000000000000010" },
|
|
38175
|
-
l2ToL1MessagePasser: {
|
|
38176
|
-
address: "0x4200000000000000000000000000000000000016"
|
|
38177
|
-
}
|
|
38178
|
-
};
|
|
38179
|
-
|
|
38180
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/formatters.js
|
|
38181
|
-
init_fromHex();
|
|
38182
|
-
init_block2();
|
|
38183
|
-
init_transaction2();
|
|
38184
|
-
init_transactionReceipt();
|
|
38185
|
-
var formatters = {
|
|
38186
|
-
block: /* @__PURE__ */ defineBlock({
|
|
38187
|
-
format(args) {
|
|
38188
|
-
const transactions = args.transactions?.map((transaction) => {
|
|
38189
|
-
if (typeof transaction === "string")
|
|
38190
|
-
return transaction;
|
|
38191
|
-
const formatted = formatTransaction(transaction);
|
|
38192
|
-
if (formatted.typeHex === "0x7e") {
|
|
38193
|
-
formatted.isSystemTx = transaction.isSystemTx;
|
|
38194
|
-
formatted.mint = transaction.mint ? hexToBigInt(transaction.mint) : void 0;
|
|
38195
|
-
formatted.sourceHash = transaction.sourceHash;
|
|
38196
|
-
formatted.type = "deposit";
|
|
38197
|
-
}
|
|
38198
|
-
return formatted;
|
|
38199
|
-
});
|
|
38200
|
-
return {
|
|
38201
|
-
transactions,
|
|
38202
|
-
stateRoot: args.stateRoot
|
|
38203
|
-
};
|
|
38204
|
-
}
|
|
38205
|
-
}),
|
|
38206
|
-
transaction: /* @__PURE__ */ defineTransaction({
|
|
38207
|
-
format(args) {
|
|
38208
|
-
const transaction = {};
|
|
38209
|
-
if (args.type === "0x7e") {
|
|
38210
|
-
transaction.isSystemTx = args.isSystemTx;
|
|
38211
|
-
transaction.mint = args.mint ? hexToBigInt(args.mint) : void 0;
|
|
38212
|
-
transaction.sourceHash = args.sourceHash;
|
|
38213
|
-
transaction.type = "deposit";
|
|
38214
|
-
}
|
|
38215
|
-
return transaction;
|
|
38216
|
-
}
|
|
38217
|
-
}),
|
|
38218
|
-
transactionReceipt: /* @__PURE__ */ defineTransactionReceipt({
|
|
38219
|
-
format(args) {
|
|
38220
|
-
return {
|
|
38221
|
-
l1GasPrice: args.l1GasPrice ? hexToBigInt(args.l1GasPrice) : null,
|
|
38222
|
-
l1GasUsed: args.l1GasUsed ? hexToBigInt(args.l1GasUsed) : null,
|
|
38223
|
-
l1Fee: args.l1Fee ? hexToBigInt(args.l1Fee) : null,
|
|
38224
|
-
l1FeeScalar: args.l1FeeScalar ? Number(args.l1FeeScalar) : null
|
|
38225
|
-
};
|
|
38226
|
-
}
|
|
38227
|
-
})
|
|
38228
|
-
};
|
|
38229
|
-
|
|
38230
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/serializers.js
|
|
38231
|
-
init_address();
|
|
38232
|
-
init_isAddress();
|
|
38233
|
-
init_concat();
|
|
38234
|
-
init_toHex();
|
|
38235
|
-
init_toRlp();
|
|
38236
|
-
init_serializeTransaction();
|
|
38237
|
-
function serializeTransaction2(transaction, signature) {
|
|
38238
|
-
if (isDeposit(transaction))
|
|
38239
|
-
return serializeTransactionDeposit(transaction);
|
|
38240
|
-
return serializeTransaction(transaction, signature);
|
|
38241
|
-
}
|
|
38242
|
-
var serializers = {
|
|
38243
|
-
transaction: serializeTransaction2
|
|
38244
|
-
};
|
|
38245
|
-
function serializeTransactionDeposit(transaction) {
|
|
38246
|
-
assertTransactionDeposit(transaction);
|
|
38247
|
-
const { sourceHash, data, from: from14, gas, isSystemTx, mint, to, value } = transaction;
|
|
38248
|
-
const serializedTransaction = [
|
|
38249
|
-
sourceHash,
|
|
38250
|
-
from14,
|
|
38251
|
-
to ?? "0x",
|
|
38252
|
-
mint ? toHex(mint) : "0x",
|
|
38253
|
-
value ? toHex(value) : "0x",
|
|
38254
|
-
gas ? toHex(gas) : "0x",
|
|
38255
|
-
isSystemTx ? "0x1" : "0x",
|
|
38256
|
-
data ?? "0x"
|
|
38257
|
-
];
|
|
38258
|
-
return concatHex([
|
|
38259
|
-
"0x7e",
|
|
38260
|
-
toRlp(serializedTransaction)
|
|
38261
|
-
]);
|
|
38262
|
-
}
|
|
38263
|
-
function isDeposit(transaction) {
|
|
38264
|
-
if (transaction.type === "deposit")
|
|
38265
|
-
return true;
|
|
38266
|
-
if (typeof transaction.sourceHash !== "undefined")
|
|
38267
|
-
return true;
|
|
38268
|
-
return false;
|
|
38269
|
-
}
|
|
38270
|
-
function assertTransactionDeposit(transaction) {
|
|
38271
|
-
const { from: from14, to } = transaction;
|
|
38272
|
-
if (from14 && !isAddress(from14))
|
|
38273
|
-
throw new InvalidAddressError({ address: from14 });
|
|
38274
|
-
if (to && !isAddress(to))
|
|
38275
|
-
throw new InvalidAddressError({ address: to });
|
|
38276
|
-
}
|
|
38277
|
-
|
|
38278
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/op-stack/chainConfig.js
|
|
38279
|
-
var chainConfig = {
|
|
38280
|
-
blockTime: 2e3,
|
|
38281
|
-
contracts,
|
|
38282
|
-
formatters,
|
|
38283
|
-
serializers
|
|
38284
|
-
};
|
|
38285
|
-
|
|
38286
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/arbitrum.js
|
|
38287
|
-
init_defineChain();
|
|
38288
|
-
var arbitrum = /* @__PURE__ */ defineChain({
|
|
38289
|
-
id: 42161,
|
|
38290
|
-
name: "Arbitrum One",
|
|
38291
|
-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
38292
|
-
blockTime: 250,
|
|
38293
|
-
rpcUrls: {
|
|
38294
|
-
default: {
|
|
38295
|
-
http: ["https://arb1.arbitrum.io/rpc"]
|
|
38296
|
-
}
|
|
38297
|
-
},
|
|
38298
|
-
blockExplorers: {
|
|
38299
|
-
default: {
|
|
38300
|
-
name: "Arbiscan",
|
|
38301
|
-
url: "https://arbiscan.io",
|
|
38302
|
-
apiUrl: "https://api.arbiscan.io/api"
|
|
38303
|
-
}
|
|
38304
|
-
},
|
|
38305
|
-
contracts: {
|
|
38306
|
-
multicall3: {
|
|
38307
|
-
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38308
|
-
blockCreated: 7654707
|
|
38309
|
-
}
|
|
38310
|
-
}
|
|
38311
|
-
});
|
|
38312
|
-
|
|
38313
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/base.js
|
|
38314
|
-
init_defineChain();
|
|
38315
|
-
var sourceId = 1;
|
|
38316
|
-
var base = /* @__PURE__ */ defineChain({
|
|
38317
|
-
...chainConfig,
|
|
38318
|
-
id: 8453,
|
|
38319
|
-
name: "Base",
|
|
38320
|
-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
38321
|
-
rpcUrls: {
|
|
38322
|
-
default: {
|
|
38323
|
-
http: ["https://mainnet.base.org"]
|
|
38324
|
-
}
|
|
38325
|
-
},
|
|
38326
|
-
blockExplorers: {
|
|
38327
|
-
default: {
|
|
38328
|
-
name: "Basescan",
|
|
38329
|
-
url: "https://basescan.org",
|
|
38330
|
-
apiUrl: "https://api.basescan.org/api"
|
|
38331
|
-
}
|
|
38332
|
-
},
|
|
38333
|
-
contracts: {
|
|
38334
|
-
...chainConfig.contracts,
|
|
38335
|
-
disputeGameFactory: {
|
|
38336
|
-
[sourceId]: {
|
|
38337
|
-
address: "0x43edB88C4B80fDD2AdFF2412A7BebF9dF42cB40e"
|
|
38338
|
-
}
|
|
38339
|
-
},
|
|
38340
|
-
l2OutputOracle: {
|
|
38341
|
-
[sourceId]: {
|
|
38342
|
-
address: "0x56315b90c40730925ec5485cf004d835058518A0"
|
|
38343
|
-
}
|
|
38344
|
-
},
|
|
38345
|
-
multicall3: {
|
|
38346
|
-
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38347
|
-
blockCreated: 5022
|
|
38348
|
-
},
|
|
38349
|
-
portal: {
|
|
38350
|
-
[sourceId]: {
|
|
38351
|
-
address: "0x49048044D57e1C92A77f79988d21Fa8fAF74E97e",
|
|
38352
|
-
blockCreated: 17482143
|
|
38353
|
-
}
|
|
38354
|
-
},
|
|
38355
|
-
l1StandardBridge: {
|
|
38356
|
-
[sourceId]: {
|
|
38357
|
-
address: "0x3154Cf16ccdb4C6d922629664174b904d80F2C35",
|
|
38358
|
-
blockCreated: 17482143
|
|
38359
|
-
}
|
|
38360
|
-
}
|
|
38361
|
-
},
|
|
38362
|
-
sourceId
|
|
38363
|
-
});
|
|
38364
|
-
var basePreconf = /* @__PURE__ */ defineChain({
|
|
38365
|
-
...base,
|
|
38366
|
-
experimental_preconfirmationTime: 200,
|
|
38367
|
-
rpcUrls: {
|
|
38368
|
-
default: {
|
|
38369
|
-
http: ["https://mainnet-preconf.base.org"]
|
|
38370
|
-
}
|
|
38371
|
-
}
|
|
38372
|
-
});
|
|
38373
|
-
|
|
38374
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/baseSepolia.js
|
|
38375
|
-
init_defineChain();
|
|
38376
|
-
var sourceId2 = 11155111;
|
|
38377
|
-
var baseSepolia = /* @__PURE__ */ defineChain({
|
|
38378
|
-
...chainConfig,
|
|
38379
|
-
id: 84532,
|
|
38380
|
-
network: "base-sepolia",
|
|
38381
|
-
name: "Base Sepolia",
|
|
38382
|
-
nativeCurrency: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 },
|
|
38383
|
-
rpcUrls: {
|
|
38384
|
-
default: {
|
|
38385
|
-
http: ["https://sepolia.base.org"]
|
|
38386
|
-
}
|
|
38387
|
-
},
|
|
38388
|
-
blockExplorers: {
|
|
38389
|
-
default: {
|
|
38390
|
-
name: "Basescan",
|
|
38391
|
-
url: "https://sepolia.basescan.org",
|
|
38392
|
-
apiUrl: "https://api-sepolia.basescan.org/api"
|
|
38393
|
-
}
|
|
38394
|
-
},
|
|
38395
|
-
contracts: {
|
|
38396
|
-
...chainConfig.contracts,
|
|
38397
|
-
disputeGameFactory: {
|
|
38398
|
-
[sourceId2]: {
|
|
38399
|
-
address: "0xd6E6dBf4F7EA0ac412fD8b65ED297e64BB7a06E1"
|
|
38400
|
-
}
|
|
38401
|
-
},
|
|
38402
|
-
l2OutputOracle: {
|
|
38403
|
-
[sourceId2]: {
|
|
38404
|
-
address: "0x84457ca9D0163FbC4bbfe4Dfbb20ba46e48DF254"
|
|
38405
|
-
}
|
|
38406
|
-
},
|
|
38407
|
-
portal: {
|
|
38408
|
-
[sourceId2]: {
|
|
38409
|
-
address: "0x49f53e41452c74589e85ca1677426ba426459e85",
|
|
38410
|
-
blockCreated: 4446677
|
|
38411
|
-
}
|
|
38412
|
-
},
|
|
38413
|
-
l1StandardBridge: {
|
|
38414
|
-
[sourceId2]: {
|
|
38415
|
-
address: "0xfd0Bf71F60660E2f608ed56e1659C450eB113120",
|
|
38416
|
-
blockCreated: 4446677
|
|
38417
|
-
}
|
|
38418
|
-
},
|
|
38419
|
-
multicall3: {
|
|
38420
|
-
address: "0xca11bde05977b3631167028862be2a173976ca11",
|
|
38421
|
-
blockCreated: 1059647
|
|
38422
|
-
}
|
|
38423
|
-
},
|
|
38424
|
-
testnet: true,
|
|
38425
|
-
sourceId: sourceId2
|
|
38426
|
-
});
|
|
38427
|
-
var baseSepoliaPreconf = /* @__PURE__ */ defineChain({
|
|
38428
|
-
...baseSepolia,
|
|
38429
|
-
experimental_preconfirmationTime: 200,
|
|
38430
|
-
rpcUrls: {
|
|
38431
|
-
default: {
|
|
38432
|
-
http: ["https://sepolia-preconf.base.org"]
|
|
38433
|
-
}
|
|
38434
|
-
}
|
|
38435
|
-
});
|
|
38436
|
-
|
|
38437
|
-
// ../../node_modules/.pnpm/viem@2.51.3_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@5.0.10_zod@4.4.3/node_modules/viem/_esm/chains/definitions/unichain.js
|
|
38438
|
-
init_defineChain();
|
|
38439
|
-
var sourceId3 = 1;
|
|
38440
|
-
var unichain = /* @__PURE__ */ defineChain({
|
|
38441
|
-
...chainConfig,
|
|
38442
|
-
id: 130,
|
|
38443
|
-
name: "Unichain",
|
|
38444
|
-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
38445
|
-
blockTime: 1e3,
|
|
38446
|
-
rpcUrls: {
|
|
38447
|
-
default: {
|
|
38448
|
-
http: ["https://mainnet.unichain.org/"]
|
|
38551
|
+
return;
|
|
38449
38552
|
}
|
|
38450
|
-
|
|
38451
|
-
|
|
38452
|
-
|
|
38453
|
-
|
|
38454
|
-
|
|
38455
|
-
|
|
38553
|
+
throw err;
|
|
38554
|
+
}
|
|
38555
|
+
}
|
|
38556
|
+
var SAIL_MAINNET_CHAINS = [8453, 42161, 130];
|
|
38557
|
+
async function fetchProxyCreationCode(preferredChainId) {
|
|
38558
|
+
const rpcUrl = getRpcUrl(preferredChainId) ?? void 0;
|
|
38559
|
+
const publicClient = createPublicClient({
|
|
38560
|
+
chain: getChainById(preferredChainId),
|
|
38561
|
+
transport: http(rpcUrl)
|
|
38562
|
+
});
|
|
38563
|
+
return await publicClient.readContract({
|
|
38564
|
+
address: SAFE_V141.proxyFactory,
|
|
38565
|
+
abi: safeProxyFactoryAbi,
|
|
38566
|
+
functionName: "proxyCreationCode"
|
|
38567
|
+
});
|
|
38568
|
+
}
|
|
38569
|
+
async function accountPredict(options) {
|
|
38570
|
+
const stored = readJsonFile(sailPath("account.json"));
|
|
38571
|
+
let ownerAddr;
|
|
38572
|
+
if (options.owner) {
|
|
38573
|
+
if (!isAddress(options.owner, { strict: false })) {
|
|
38574
|
+
throw new Error(`Invalid --owner address: ${options.owner}`);
|
|
38456
38575
|
}
|
|
38457
|
-
|
|
38458
|
-
|
|
38459
|
-
|
|
38460
|
-
|
|
38461
|
-
|
|
38462
|
-
|
|
38463
|
-
},
|
|
38464
|
-
disputeGameFactory: {
|
|
38465
|
-
[sourceId3]: {
|
|
38466
|
-
address: "0x2F12d621a16e2d3285929C9996f478508951dFe4"
|
|
38467
|
-
}
|
|
38468
|
-
},
|
|
38469
|
-
portal: {
|
|
38470
|
-
[sourceId3]: {
|
|
38471
|
-
address: "0x0bd48f6B86a26D3a217d0Fa6FfE2B491B956A7a2"
|
|
38472
|
-
}
|
|
38473
|
-
},
|
|
38474
|
-
l1StandardBridge: {
|
|
38475
|
-
[sourceId3]: {
|
|
38476
|
-
address: "0x81014F44b0a345033bB2b3B21C7a1A308B35fEeA"
|
|
38477
|
-
}
|
|
38576
|
+
ownerAddr = getAddress(options.owner);
|
|
38577
|
+
} else {
|
|
38578
|
+
if (!stored?.owner) {
|
|
38579
|
+
throw new Error(
|
|
38580
|
+
"No owner found in .sail/account.json. Pass --owner <address> or run sailor onboard first."
|
|
38581
|
+
);
|
|
38478
38582
|
}
|
|
38479
|
-
|
|
38480
|
-
|
|
38481
|
-
|
|
38482
|
-
|
|
38483
|
-
|
|
38484
|
-
|
|
38485
|
-
|
|
38486
|
-
|
|
38487
|
-
|
|
38488
|
-
|
|
38489
|
-
}
|
|
38490
|
-
function getChainById(chainId) {
|
|
38491
|
-
const chain2 = CHAINS[chainId];
|
|
38492
|
-
if (!chain2) {
|
|
38583
|
+
ownerAddr = getAddress(stored.owner);
|
|
38584
|
+
}
|
|
38585
|
+
let managerAddr;
|
|
38586
|
+
if (options.manager) {
|
|
38587
|
+
if (!isAddress(options.manager, { strict: false })) {
|
|
38588
|
+
throw new Error(`Invalid --manager address: ${options.manager}`);
|
|
38589
|
+
}
|
|
38590
|
+
managerAddr = getAddress(options.manager);
|
|
38591
|
+
} else if (stored?.manager) {
|
|
38592
|
+
managerAddr = getAddress(stored.manager);
|
|
38593
|
+
} else {
|
|
38493
38594
|
throw new Error(
|
|
38494
|
-
|
|
38595
|
+
"The predicted address depends on the agent (manager) wallet, which is mixed into the kernel's CREATE2 salt.\nPass --manager <agent address> (create one first with `sailor keys`), or run after onboarding so it can be read from .sail/account.json."
|
|
38495
38596
|
);
|
|
38496
38597
|
}
|
|
38497
|
-
|
|
38498
|
-
|
|
38499
|
-
|
|
38500
|
-
|
|
38501
|
-
|
|
38502
|
-
|
|
38503
|
-
|
|
38504
|
-
|
|
38505
|
-
|
|
38506
|
-
|
|
38507
|
-
|
|
38508
|
-
|
|
38509
|
-
|
|
38510
|
-
const
|
|
38511
|
-
|
|
38512
|
-
const
|
|
38513
|
-
|
|
38598
|
+
const saltNonce = options.salt != null ? BigInt(options.salt) : 0n;
|
|
38599
|
+
let chainIds;
|
|
38600
|
+
if (options.chain) {
|
|
38601
|
+
const chainId = Number(options.chain);
|
|
38602
|
+
if (!(chainId in sailDeployments)) {
|
|
38603
|
+
throw new Error(
|
|
38604
|
+
`Chain ${chainId} has no Sail Protocol deployment. Supported: ${Object.keys(sailDeployments).join(", ")}`
|
|
38605
|
+
);
|
|
38606
|
+
}
|
|
38607
|
+
chainIds = [chainId];
|
|
38608
|
+
} else {
|
|
38609
|
+
chainIds = SAIL_MAINNET_CHAINS;
|
|
38610
|
+
}
|
|
38611
|
+
const firstChain = chainIds[0];
|
|
38612
|
+
const proxyCreationCode = await fetchProxyCreationCode(firstChain);
|
|
38613
|
+
const results = chainIds.map((chainId) => {
|
|
38614
|
+
const deployment = sailDeployments[chainId];
|
|
38615
|
+
const viemChain = getChainById(chainId);
|
|
38616
|
+
const initializer = buildSafeSetupInitializer({
|
|
38617
|
+
owners: [ownerAddr],
|
|
38618
|
+
threshold: 1n,
|
|
38619
|
+
kernel: deployment.kernel,
|
|
38620
|
+
safeModuleEnabler: deployment.safeModuleEnabler
|
|
38621
|
+
});
|
|
38622
|
+
const predictedAddress = computeSailSmaAddress({
|
|
38623
|
+
initializer,
|
|
38624
|
+
saltNonce,
|
|
38625
|
+
deployer: ownerAddr,
|
|
38626
|
+
permissionSigner: ownerAddr,
|
|
38627
|
+
manager: managerAddr,
|
|
38628
|
+
feePolicy: deployment.standardFeePolicy,
|
|
38629
|
+
proxyCreationCode
|
|
38630
|
+
});
|
|
38631
|
+
return {
|
|
38632
|
+
chainId,
|
|
38633
|
+
name: viemChain.name,
|
|
38634
|
+
predictedAddress,
|
|
38635
|
+
kernel: deployment.kernel,
|
|
38636
|
+
safeModuleEnabler: deployment.safeModuleEnabler
|
|
38637
|
+
};
|
|
38638
|
+
});
|
|
38639
|
+
const uniqueAddresses = new Set(results.map((r) => r.predictedAddress.toLowerCase()));
|
|
38640
|
+
const allSame = uniqueAddresses.size === 1;
|
|
38641
|
+
if (options.json) {
|
|
38642
|
+
console.log(
|
|
38643
|
+
JSON.stringify(
|
|
38644
|
+
{
|
|
38645
|
+
salt: saltNonce.toString(),
|
|
38646
|
+
owner: ownerAddr,
|
|
38647
|
+
manager: managerAddr,
|
|
38648
|
+
chains: results.map(({ chainId, name, predictedAddress }) => ({
|
|
38649
|
+
chainId,
|
|
38650
|
+
name,
|
|
38651
|
+
predictedAddress
|
|
38652
|
+
})),
|
|
38653
|
+
allSame,
|
|
38654
|
+
note: allSame ? "All chains produce the same address with this salt, owner, and manager." : "Addresses differ per chain because the kernel salt binds the chain-specific fee policy and the Safe initializer encodes chain-specific contract addresses (kernel, safeModuleEnabler). Cross-chain same-address requires deterministic protocol deployment or a registerExisting() flow."
|
|
38655
|
+
},
|
|
38656
|
+
null,
|
|
38657
|
+
2
|
|
38658
|
+
)
|
|
38659
|
+
);
|
|
38660
|
+
return;
|
|
38661
|
+
}
|
|
38662
|
+
console.log("\nPredicted Safe addresses");
|
|
38663
|
+
console.log(` Owner: ${ownerAddr}`);
|
|
38664
|
+
console.log(` Manager: ${managerAddr}`);
|
|
38665
|
+
console.log(` Salt: ${saltNonce}`);
|
|
38666
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
38667
|
+
for (const { chainId, name, predictedAddress } of results) {
|
|
38668
|
+
console.log(` ${name.padEnd(14)} (${String(chainId).padEnd(5)}): ${predictedAddress}`);
|
|
38669
|
+
}
|
|
38670
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
38671
|
+
if (allSame) {
|
|
38672
|
+
console.log("\u2713 All chains produce the same address.");
|
|
38673
|
+
} else {
|
|
38674
|
+
console.log("\n\u26A0 Addresses differ across chains.");
|
|
38675
|
+
console.log(
|
|
38676
|
+
" Root cause: SailKernel.createAccount binds the CREATE2 salt as\n keccak256(saltNonce, deployer, permissionSigner, manager, feePolicy),\n then SafeProxyFactory derives the address from that bound salt and the\n Safe initializer. Both the fee policy and the initializer (kernel,\n safeModuleEnabler) are chain-specific, so each chain yields a different\n address even with the same owner, manager, and salt.\n\n For cross-chain same-address the Sail Protocol needs one of:\n A) Deterministic (CREATE2) deployment of kernel + safeModuleEnabler +\n fee policy so they land at the same address on every chain.\n B) A registerExisting() path allowing a plain Safe (deployed with a\n chain-agnostic initializer) to be registered with the kernel."
|
|
38677
|
+
);
|
|
38678
|
+
}
|
|
38679
|
+
console.log(`
|
|
38680
|
+
To deploy on this chain: sailor onboard --new-sma --salt ${saltNonce}`);
|
|
38514
38681
|
}
|
|
38515
38682
|
|
|
38516
38683
|
// src/lib/output.ts
|
|
@@ -38714,6 +38881,16 @@ async function capabilities(options = {}) {
|
|
|
38714
38881
|
// src/commands/doctor.ts
|
|
38715
38882
|
init_esm2();
|
|
38716
38883
|
|
|
38884
|
+
// src/lib/contract-check.ts
|
|
38885
|
+
async function checkContractExists(pc, address) {
|
|
38886
|
+
try {
|
|
38887
|
+
const code = await pc.getCode({ address });
|
|
38888
|
+
return { address, hasCode: !!code && code !== "0x" };
|
|
38889
|
+
} catch (err) {
|
|
38890
|
+
return { address, hasCode: false, error: err.message.split("\n")[0] };
|
|
38891
|
+
}
|
|
38892
|
+
}
|
|
38893
|
+
|
|
38717
38894
|
// src/lib/permission-resolver.ts
|
|
38718
38895
|
var IPERMISSION_ABI = [
|
|
38719
38896
|
{
|
|
@@ -38740,20 +38917,39 @@ var IPERMISSION_ABI = [
|
|
|
38740
38917
|
outputs: [{ type: "bool" }]
|
|
38741
38918
|
}
|
|
38742
38919
|
];
|
|
38743
|
-
|
|
38744
|
-
const {
|
|
38920
|
+
function buildPermissionContext(params) {
|
|
38921
|
+
const { account: account2, manager, call: call2, blockInfo } = params;
|
|
38745
38922
|
const selector = call2.data.length >= 10 ? call2.data.slice(0, 10) : "0x00000000";
|
|
38746
|
-
|
|
38923
|
+
return {
|
|
38747
38924
|
account: account2,
|
|
38748
38925
|
manager,
|
|
38749
38926
|
submitter: manager,
|
|
38750
|
-
//
|
|
38927
|
+
// runner submits dispatches from the manager (agent) wallet
|
|
38751
38928
|
target: call2.target,
|
|
38752
38929
|
selector,
|
|
38753
38930
|
value: call2.value,
|
|
38754
38931
|
blockTimestamp: blockInfo.timestamp,
|
|
38755
38932
|
blockNumber: blockInfo.number
|
|
38756
38933
|
};
|
|
38934
|
+
}
|
|
38935
|
+
async function probePermissionForCall(params) {
|
|
38936
|
+
const { publicClient, permission, account: account2, manager, call: call2, blockInfo } = params;
|
|
38937
|
+
const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo });
|
|
38938
|
+
try {
|
|
38939
|
+
const accepted = await publicClient.readContract({
|
|
38940
|
+
address: permission,
|
|
38941
|
+
abi: IPERMISSION_ABI,
|
|
38942
|
+
functionName: "evaluate",
|
|
38943
|
+
args: [call2.data, ctx]
|
|
38944
|
+
});
|
|
38945
|
+
return { accepted: Boolean(accepted), reverted: false };
|
|
38946
|
+
} catch (err) {
|
|
38947
|
+
return { accepted: false, reverted: true, error: err.message.split("\n")[0] };
|
|
38948
|
+
}
|
|
38949
|
+
}
|
|
38950
|
+
async function resolvePermissionForCall(params) {
|
|
38951
|
+
const { publicClient, account: account2, manager, call: call2, registeredPermissions, blockInfo } = params;
|
|
38952
|
+
const ctx = buildPermissionContext({ account: account2, manager, call: call2, blockInfo });
|
|
38757
38953
|
for (const permission of registeredPermissions) {
|
|
38758
38954
|
try {
|
|
38759
38955
|
const accepted = await publicClient.readContract({
|
|
@@ -38845,9 +39041,14 @@ async function doctor(options = {}) {
|
|
|
38845
39041
|
const safe = options.account ? getAddress(options.account) : stored?.safe ? getAddress(stored.safe) : null;
|
|
38846
39042
|
let permissions = [];
|
|
38847
39043
|
let checks = [];
|
|
39044
|
+
let permsNoCode = [];
|
|
38848
39045
|
if (safe) {
|
|
38849
39046
|
const mandates = await client.mandate.list(safe);
|
|
38850
39047
|
permissions = mandates.map((m) => getAddress(m.permission));
|
|
39048
|
+
if (permissions.length > 0) {
|
|
39049
|
+
const codeChecks = await Promise.all(permissions.map((p) => checkContractExists(pc, p)));
|
|
39050
|
+
permsNoCode = codeChecks.filter((c) => !c.hasCode && !c.error).map((c) => c.address);
|
|
39051
|
+
}
|
|
38851
39052
|
if (caps.dispatchModel === "conjunctive" && permissions.length > 0) {
|
|
38852
39053
|
checks = await Promise.all(permissions.map((p) => probePassThrough(pc, p, safe)));
|
|
38853
39054
|
}
|
|
@@ -38884,7 +39085,9 @@ async function doctor(options = {}) {
|
|
|
38884
39085
|
manager: managerAddr ? { address: managerAddr, ...managerBal ?? {} } : null
|
|
38885
39086
|
},
|
|
38886
39087
|
account: safe,
|
|
39088
|
+
saltNonce: stored?.saltNonce ?? null,
|
|
38887
39089
|
permissions,
|
|
39090
|
+
permissionsWithoutCode: permsNoCode,
|
|
38888
39091
|
conjunctivePassThrough: caps.dispatchModel === "conjunctive" ? checks.map((c) => ({
|
|
38889
39092
|
permission: c.permission,
|
|
38890
39093
|
passesThrough: c.passesThrough,
|
|
@@ -38948,6 +39151,56 @@ async function doctor(options = {}) {
|
|
|
38948
39151
|
return;
|
|
38949
39152
|
}
|
|
38950
39153
|
console.log(`Account: ${safe}`);
|
|
39154
|
+
if (stored?.saltNonce != null) {
|
|
39155
|
+
const saltNonce = BigInt(stored.saltNonce);
|
|
39156
|
+
const MAINNET_CHAINS = [8453, 42161, 130];
|
|
39157
|
+
try {
|
|
39158
|
+
const proxyCreationCode = await pc.readContract({
|
|
39159
|
+
address: SAFE_V141.proxyFactory,
|
|
39160
|
+
abi: safeProxyFactoryAbi,
|
|
39161
|
+
functionName: "proxyCreationCode"
|
|
39162
|
+
});
|
|
39163
|
+
const ownerAddr2 = stored.owner ? getAddress(stored.owner) : null;
|
|
39164
|
+
const managerAddr2 = stored.manager ? getAddress(stored.manager) : null;
|
|
39165
|
+
if (ownerAddr2 && managerAddr2) {
|
|
39166
|
+
console.log(
|
|
39167
|
+
`
|
|
39168
|
+
Multi-chain addresses (salt ${saltNonce}, owner ${ownerAddr2}, manager ${managerAddr2}):`
|
|
39169
|
+
);
|
|
39170
|
+
const CHAIN_NAMES = { 8453: "Base", 42161: "Arbitrum", 130: "Unichain" };
|
|
39171
|
+
for (const cid of MAINNET_CHAINS) {
|
|
39172
|
+
const dep = sailDeployments[cid];
|
|
39173
|
+
const initializer = buildSafeSetupInitializer({
|
|
39174
|
+
owners: [ownerAddr2],
|
|
39175
|
+
threshold: 1n,
|
|
39176
|
+
kernel: dep.kernel,
|
|
39177
|
+
safeModuleEnabler: dep.safeModuleEnabler
|
|
39178
|
+
});
|
|
39179
|
+
const predicted = computeSailSmaAddress({
|
|
39180
|
+
initializer,
|
|
39181
|
+
saltNonce,
|
|
39182
|
+
deployer: ownerAddr2,
|
|
39183
|
+
permissionSigner: ownerAddr2,
|
|
39184
|
+
manager: managerAddr2,
|
|
39185
|
+
feePolicy: dep.standardFeePolicy,
|
|
39186
|
+
proxyCreationCode
|
|
39187
|
+
});
|
|
39188
|
+
const isDeployed = predicted.toLowerCase() === safe.toLowerCase() && cid === chainId;
|
|
39189
|
+
const label = isDeployed ? "deployed (this account)" : predicted;
|
|
39190
|
+
console.log(` ${CHAIN_NAMES[cid].padEnd(12)} (${cid}): ${label}`);
|
|
39191
|
+
}
|
|
39192
|
+
console.log(
|
|
39193
|
+
' \u26A0 Addresses differ per chain (chain-specific kernel salt + initializer). Run "sailor account predict" for details.'
|
|
39194
|
+
);
|
|
39195
|
+
}
|
|
39196
|
+
} catch {
|
|
39197
|
+
}
|
|
39198
|
+
} else if (stored) {
|
|
39199
|
+
console.log(
|
|
39200
|
+
"\nMulti-chain addresses: saltNonce not stored (deployed before salt tracking)."
|
|
39201
|
+
);
|
|
39202
|
+
console.log(" To enable: re-deploy with sailor onboard --new-sma --salt 0");
|
|
39203
|
+
}
|
|
38951
39204
|
if (permissions.length === 0) {
|
|
38952
39205
|
console.log(
|
|
38953
39206
|
"\n\u26A0 No permissions registered \u2014 every dispatch will be denied (NoPermissionsRegistered)."
|
|
@@ -38957,6 +39210,13 @@ async function doctor(options = {}) {
|
|
|
38957
39210
|
}
|
|
38958
39211
|
console.log(`
|
|
38959
39212
|
Registered permissions (${permissions.length}):`);
|
|
39213
|
+
if (permsNoCode.length > 0) {
|
|
39214
|
+
console.log(
|
|
39215
|
+
`
|
|
39216
|
+
\u26A0 ${permsNoCode.length} registered permission(s) have NO contract code on chain ${chainId} \u2014 dispatches naming them will fail. Verify the address (wrong chain?) or revoke:`
|
|
39217
|
+
);
|
|
39218
|
+
permsNoCode.forEach((p) => console.log(` ${p}`));
|
|
39219
|
+
}
|
|
38960
39220
|
if (caps.dispatchModel === "selective") {
|
|
38961
39221
|
permissions.forEach((p, i) => console.log(` ${i + 1}. ${p}`));
|
|
38962
39222
|
console.log("\nEach dispatch names one permission, so pass-through is not required.");
|
|
@@ -40295,18 +40555,21 @@ Project: ${project.name}`));
|
|
|
40295
40555
|
say(
|
|
40296
40556
|
() => console.log(
|
|
40297
40557
|
`
|
|
40298
|
-
\u2192
|
|
40299
|
-
|
|
40558
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
40559
|
+
http://localhost:${projectPort(process.cwd())}/#/station
|
|
40300
40560
|
`
|
|
40301
40561
|
)
|
|
40302
40562
|
);
|
|
40303
40563
|
let smaAddress;
|
|
40304
40564
|
let justCreated = false;
|
|
40305
40565
|
let ownerAddress = project.getOwner();
|
|
40566
|
+
let deployedSaltNonce;
|
|
40306
40567
|
if (smaChoice.kind === "new") {
|
|
40307
|
-
const
|
|
40568
|
+
const saltNonce = options.salt != null ? BigInt(options.salt) : 0n;
|
|
40569
|
+
const created = await createSma(project, channel, publicClient, agentAddress, json, saltNonce);
|
|
40308
40570
|
smaAddress = created.sma;
|
|
40309
40571
|
ownerAddress = created.owner;
|
|
40572
|
+
deployedSaltNonce = created.saltNonce;
|
|
40310
40573
|
justCreated = true;
|
|
40311
40574
|
} else {
|
|
40312
40575
|
smaAddress = smaChoice.address;
|
|
@@ -40349,7 +40612,8 @@ Project: ${project.name}`));
|
|
|
40349
40612
|
owner: ownerAddress ?? permissionSigner,
|
|
40350
40613
|
permissionSigner,
|
|
40351
40614
|
manager: onChainManager,
|
|
40352
|
-
chainId: project.chainId
|
|
40615
|
+
chainId: project.chainId,
|
|
40616
|
+
saltNonce: deployedSaltNonce
|
|
40353
40617
|
});
|
|
40354
40618
|
if (options.skipMandate) {
|
|
40355
40619
|
return { sma: smaAddress, agent: agentAddress, mandates: [], created: justCreated };
|
|
@@ -40500,7 +40764,7 @@ async function waitForRegistration(publicClient, kernel, account2, attempts) {
|
|
|
40500
40764
|
}
|
|
40501
40765
|
return false;
|
|
40502
40766
|
}
|
|
40503
|
-
async function createSma(project, channel, publicClient, agentAddress, json = false) {
|
|
40767
|
+
async function createSma(project, channel, publicClient, agentAddress, json = false, saltNonce = 0n) {
|
|
40504
40768
|
const say = (fn) => {
|
|
40505
40769
|
if (!json) fn();
|
|
40506
40770
|
};
|
|
@@ -40514,7 +40778,6 @@ async function createSma(project, channel, publicClient, agentAddress, json = fa
|
|
|
40514
40778
|
kernel: project.contracts.kernel,
|
|
40515
40779
|
safeModuleEnabler: deployment.safeModuleEnabler
|
|
40516
40780
|
});
|
|
40517
|
-
const saltNonce = BigInt(Date.now());
|
|
40518
40781
|
const createAccountData = encodeFunctionData({
|
|
40519
40782
|
abi: SailKernelAbi,
|
|
40520
40783
|
functionName: "createAccount",
|
|
@@ -40565,6 +40828,7 @@ async function createSma(project, channel, publicClient, agentAddress, json = fa
|
|
|
40565
40828
|
}
|
|
40566
40829
|
const safeAddress = registered.args.account;
|
|
40567
40830
|
say(() => console.log("\u2713", `SMA created at ${safeAddress}`));
|
|
40831
|
+
say(() => console.log(" Salt:", saltNonce.toString(), "(stored in .sail/account.json \u2014 use for sailor account predict)"));
|
|
40568
40832
|
appendActivity({
|
|
40569
40833
|
ts: nowIso(),
|
|
40570
40834
|
actor: "owner",
|
|
@@ -40573,9 +40837,10 @@ async function createSma(project, channel, publicClient, agentAddress, json = fa
|
|
|
40573
40837
|
owner: ownerAddress,
|
|
40574
40838
|
manager: agentAddress,
|
|
40575
40839
|
txHash: response.txHash,
|
|
40576
|
-
chainId: project.chainId
|
|
40840
|
+
chainId: project.chainId,
|
|
40841
|
+
saltNonce: saltNonce.toString()
|
|
40577
40842
|
});
|
|
40578
|
-
return { sma: safeAddress, owner: ownerAddress };
|
|
40843
|
+
return { sma: safeAddress, owner: ownerAddress, saltNonce };
|
|
40579
40844
|
}
|
|
40580
40845
|
async function attachMandate(project, channel, publicClient, agentSigner, smaAddress, permissionSigner, template, opts = {}) {
|
|
40581
40846
|
const say = (fn) => {
|
|
@@ -40723,7 +40988,8 @@ async function persistAccount(publicClient, account2) {
|
|
|
40723
40988
|
permissionSigner: checksum4(account2.permissionSigner),
|
|
40724
40989
|
manager: checksum4(account2.manager),
|
|
40725
40990
|
chainId: account2.chainId,
|
|
40726
|
-
createdAtBlock
|
|
40991
|
+
createdAtBlock,
|
|
40992
|
+
...account2.saltNonce != null ? { saltNonce: account2.saltNonce.toString() } : {}
|
|
40727
40993
|
};
|
|
40728
40994
|
upsertAccountInList(stored);
|
|
40729
40995
|
writeJsonFile(sailPath("account.json"), stored);
|
|
@@ -40834,8 +41100,8 @@ async function runDeploy(project, channel, options) {
|
|
|
40834
41100
|
say(() => {
|
|
40835
41101
|
console.log(
|
|
40836
41102
|
`
|
|
40837
|
-
\u2192
|
|
40838
|
-
|
|
41103
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
41104
|
+
http://localhost:${projectPort(process.cwd())}/#/station
|
|
40839
41105
|
`
|
|
40840
41106
|
);
|
|
40841
41107
|
console.log(`Pushing deploy request for "${contractName}"\u2026`);
|
|
@@ -41057,8 +41323,8 @@ ${spec.label} clone (${options.template})`);
|
|
|
41057
41323
|
console.log(` SMA: ${sma}`);
|
|
41058
41324
|
for (const d of spec.describe(initParams)) console.log(` ${d.label}: ${d.value}`);
|
|
41059
41325
|
console.log(`
|
|
41060
|
-
\u2192
|
|
41061
|
-
|
|
41326
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
41327
|
+
http://localhost:${projectPort(process.cwd())}/#/station
|
|
41062
41328
|
`);
|
|
41063
41329
|
});
|
|
41064
41330
|
const nonce = await publicClient.readContract({
|
|
@@ -41221,8 +41487,8 @@ async function runAttach(project, channel, options) {
|
|
|
41221
41487
|
if (!json) {
|
|
41222
41488
|
console.log(
|
|
41223
41489
|
`
|
|
41224
|
-
\u2192
|
|
41225
|
-
|
|
41490
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
41491
|
+
http://localhost:${projectPort(process.cwd())}/#/station
|
|
41226
41492
|
`
|
|
41227
41493
|
);
|
|
41228
41494
|
}
|
|
@@ -41304,8 +41570,8 @@ Revoking ${targets.length} permission(s) from ${sma}:`);
|
|
|
41304
41570
|
for (const p of targets) console.log(` ${nameFor(p) ?? p} ${p}`);
|
|
41305
41571
|
console.log(
|
|
41306
41572
|
`
|
|
41307
|
-
\u2192
|
|
41308
|
-
|
|
41573
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
41574
|
+
http://localhost:${projectPort(process.cwd())}/#/station
|
|
41309
41575
|
`
|
|
41310
41576
|
);
|
|
41311
41577
|
});
|
|
@@ -41606,6 +41872,88 @@ function runForgeBuild() {
|
|
|
41606
41872
|
|
|
41607
41873
|
// src/commands/mandate.ts
|
|
41608
41874
|
init_esm2();
|
|
41875
|
+
|
|
41876
|
+
// src/lib/permission-explainer.ts
|
|
41877
|
+
var import_node_fs11 = require("node:fs");
|
|
41878
|
+
var import_node_path10 = require("node:path");
|
|
41879
|
+
function explainPermission(name, sourcePath) {
|
|
41880
|
+
const resolved = sourcePath ?? (0, import_node_path10.join)(process.cwd(), "mandates", `${name}.sol`);
|
|
41881
|
+
let src;
|
|
41882
|
+
try {
|
|
41883
|
+
src = (0, import_node_fs11.readFileSync)(resolved, "utf8");
|
|
41884
|
+
} catch {
|
|
41885
|
+
return null;
|
|
41886
|
+
}
|
|
41887
|
+
return parseStructured(src) ?? parseNatSpec(src) ?? parseRequires(src);
|
|
41888
|
+
}
|
|
41889
|
+
function parseStructured(src) {
|
|
41890
|
+
if (!src.includes("ENFORCED ON-CHAIN")) return null;
|
|
41891
|
+
const lines = src.split("\n");
|
|
41892
|
+
const result = {
|
|
41893
|
+
source: "structured",
|
|
41894
|
+
enforced: [],
|
|
41895
|
+
notEnforced: []
|
|
41896
|
+
};
|
|
41897
|
+
const headerLines = [];
|
|
41898
|
+
for (const line of lines) {
|
|
41899
|
+
const t = line.trim();
|
|
41900
|
+
if (t.startsWith("import ") || t.startsWith("contract ") || t.startsWith("abstract contract ")) break;
|
|
41901
|
+
if (t.startsWith("//")) headerLines.push(t.slice(2));
|
|
41902
|
+
}
|
|
41903
|
+
let section = null;
|
|
41904
|
+
for (const raw of headerLines) {
|
|
41905
|
+
const trimmed = raw.trim();
|
|
41906
|
+
if (/^─+$/.test(trimmed)) continue;
|
|
41907
|
+
if (trimmed.includes("ENFORCED ON-CHAIN")) {
|
|
41908
|
+
section = "enforced";
|
|
41909
|
+
continue;
|
|
41910
|
+
}
|
|
41911
|
+
if (trimmed.includes("NOT ENFORCED")) {
|
|
41912
|
+
section = "notEnforced";
|
|
41913
|
+
continue;
|
|
41914
|
+
}
|
|
41915
|
+
if (trimmed.includes("VERIFY BEFORE USE")) {
|
|
41916
|
+
section = null;
|
|
41917
|
+
continue;
|
|
41918
|
+
}
|
|
41919
|
+
if (section === null) {
|
|
41920
|
+
const kv = trimmed.match(/^(Protocol|Version|Chain|Target)\s*:\s*(.+)$/i);
|
|
41921
|
+
if (kv) {
|
|
41922
|
+
const key = kv[1].toLowerCase();
|
|
41923
|
+
result[key] = kv[2].trim();
|
|
41924
|
+
}
|
|
41925
|
+
}
|
|
41926
|
+
if (section && trimmed.startsWith("\u2022")) {
|
|
41927
|
+
const bullet = trimmed.slice(1).trim();
|
|
41928
|
+
if (bullet) result[section].push(bullet);
|
|
41929
|
+
}
|
|
41930
|
+
}
|
|
41931
|
+
if (result.enforced.length === 0 && !result.protocol) return null;
|
|
41932
|
+
return result;
|
|
41933
|
+
}
|
|
41934
|
+
function parseNatSpec(src) {
|
|
41935
|
+
const enforced = [];
|
|
41936
|
+
const notEnforced = [];
|
|
41937
|
+
for (const line of src.split("\n")) {
|
|
41938
|
+
const t = line.trim();
|
|
41939
|
+
const notice = t.match(/^\/\/\/\s*@notice\s+(.+)$/);
|
|
41940
|
+
if (notice) enforced.push(notice[1].trim());
|
|
41941
|
+
const dev = t.match(/^\/\/\/\s*@dev\s+(.+)$/);
|
|
41942
|
+
if (dev) notEnforced.push(dev[1].trim());
|
|
41943
|
+
}
|
|
41944
|
+
if (enforced.length === 0 && notEnforced.length === 0) return null;
|
|
41945
|
+
return { source: "natspec", enforced, notEnforced };
|
|
41946
|
+
}
|
|
41947
|
+
function parseRequires(src) {
|
|
41948
|
+
const enforced = [];
|
|
41949
|
+
const re = /require\s*\([^,)]+,\s*["']([^"']+)["']\)/g;
|
|
41950
|
+
let m;
|
|
41951
|
+
while ((m = re.exec(src)) !== null) enforced.push(m[1]);
|
|
41952
|
+
if (enforced.length === 0) return null;
|
|
41953
|
+
return { source: "require-only", enforced, notEnforced: [] };
|
|
41954
|
+
}
|
|
41955
|
+
|
|
41956
|
+
// src/commands/mandate.ts
|
|
41609
41957
|
async function fetchOnChainPermissions(account2) {
|
|
41610
41958
|
try {
|
|
41611
41959
|
const project = new ProjectContext();
|
|
@@ -41672,11 +42020,15 @@ ${permissions.length} permission(s) tracked for SMA ${account2.safe}:
|
|
|
41672
42020
|
console.log(` ${p.address}`);
|
|
41673
42021
|
console.log(` ${status2}`);
|
|
41674
42022
|
}
|
|
42023
|
+
const store = new MandateStore();
|
|
41675
42024
|
const draft = {
|
|
41676
42025
|
account: account2.safe,
|
|
41677
42026
|
chainId: account2.chainId,
|
|
41678
|
-
|
|
41679
|
-
|
|
42027
|
+
permissions: permissions.filter((p) => !p.revokedOnChain).map((p) => {
|
|
42028
|
+
const mandate2 = store.find(p.address);
|
|
42029
|
+
const explanation = explainPermission(p.label, mandate2?.sourcePath) ?? void 0;
|
|
42030
|
+
return { address: p.address, label: p.label, explanation };
|
|
42031
|
+
}),
|
|
41680
42032
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41681
42033
|
};
|
|
41682
42034
|
writeJsonFile(sailPath("mandate-draft.json"), draft);
|
|
@@ -41739,8 +42091,231 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
|
|
|
41739
42091
|
\u2713 Saved to .sail/mandate.json \u2014 agent is ready to run.`);
|
|
41740
42092
|
}
|
|
41741
42093
|
|
|
42094
|
+
// src/commands/mandate-simulate.ts
|
|
42095
|
+
var import_node_fs12 = require("node:fs");
|
|
42096
|
+
init_esm2();
|
|
42097
|
+
function parseExpect(raw, where) {
|
|
42098
|
+
if (raw === void 0) return void 0;
|
|
42099
|
+
const v = raw.toLowerCase();
|
|
42100
|
+
if (v === "pass" || v === "fail") return v;
|
|
42101
|
+
throw new Error(`${where}: "expect" must be "pass" or "fail" \u2014 got "${raw}".`);
|
|
42102
|
+
}
|
|
42103
|
+
function resolveSampleCalls(options) {
|
|
42104
|
+
const hasInline = options.target !== void 0 || options.calldata !== void 0;
|
|
42105
|
+
if (options.calls && hasInline) {
|
|
42106
|
+
throw new Error("Provide EITHER --calls <file> OR inline --target/--calldata, not both.");
|
|
42107
|
+
}
|
|
42108
|
+
if (options.calls) {
|
|
42109
|
+
let raw;
|
|
42110
|
+
try {
|
|
42111
|
+
raw = JSON.parse((0, import_node_fs12.readFileSync)(options.calls, "utf8"));
|
|
42112
|
+
} catch (err) {
|
|
42113
|
+
throw new Error(`Could not read --calls file "${options.calls}": ${err.message}`);
|
|
42114
|
+
}
|
|
42115
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
42116
|
+
throw new Error(`--calls file must be a non-empty JSON array of { target, calldata, ... }.`);
|
|
42117
|
+
}
|
|
42118
|
+
return raw.map((entry, i) => parseCallEntry(entry, i));
|
|
42119
|
+
}
|
|
42120
|
+
if (!hasInline) {
|
|
42121
|
+
throw new Error(
|
|
42122
|
+
"No sample calls. Pass --target <addr> --calldata <hex> for one call, or --calls <file.json> for a batch."
|
|
42123
|
+
);
|
|
42124
|
+
}
|
|
42125
|
+
if (!options.target || !options.calldata) {
|
|
42126
|
+
throw new Error("Inline call requires BOTH --target <addr> and --calldata <hex>.");
|
|
42127
|
+
}
|
|
42128
|
+
return [
|
|
42129
|
+
parseCallEntry(
|
|
42130
|
+
{
|
|
42131
|
+
target: options.target,
|
|
42132
|
+
calldata: options.calldata,
|
|
42133
|
+
value: options.value,
|
|
42134
|
+
expect: options.expect,
|
|
42135
|
+
label: options.label
|
|
42136
|
+
},
|
|
42137
|
+
0
|
|
42138
|
+
)
|
|
42139
|
+
];
|
|
42140
|
+
}
|
|
42141
|
+
function parseCallEntry(entry, index2) {
|
|
42142
|
+
const where = `call[${index2}]`;
|
|
42143
|
+
const target = entry.target;
|
|
42144
|
+
if (typeof target !== "string" || !isAddress(target, { strict: false })) {
|
|
42145
|
+
throw new Error(`${where}: "target" must be a valid address \u2014 got ${JSON.stringify(target)}.`);
|
|
42146
|
+
}
|
|
42147
|
+
const data = entry.calldata ?? entry.data;
|
|
42148
|
+
if (typeof data !== "string" || !isHex(data)) {
|
|
42149
|
+
throw new Error(`${where}: "calldata" must be a 0x-prefixed hex string.`);
|
|
42150
|
+
}
|
|
42151
|
+
let value = 0n;
|
|
42152
|
+
if (entry.value !== void 0 && entry.value !== null && entry.value !== "") {
|
|
42153
|
+
try {
|
|
42154
|
+
value = BigInt(entry.value);
|
|
42155
|
+
} catch {
|
|
42156
|
+
throw new Error(`${where}: "value" must be an integer (wei) \u2014 got ${JSON.stringify(entry.value)}.`);
|
|
42157
|
+
}
|
|
42158
|
+
}
|
|
42159
|
+
const label = typeof entry.label === "string" && entry.label.trim() ? entry.label.trim() : `call ${index2 + 1}`;
|
|
42160
|
+
return {
|
|
42161
|
+
label,
|
|
42162
|
+
target: getAddress(target),
|
|
42163
|
+
data,
|
|
42164
|
+
value,
|
|
42165
|
+
expect: parseExpect(entry.expect, where)
|
|
42166
|
+
};
|
|
42167
|
+
}
|
|
42168
|
+
function managerAddress(safe) {
|
|
42169
|
+
const stored = readJsonFile(sailPath("account.json"));
|
|
42170
|
+
if (stored?.manager && isAddress(stored.manager, { strict: false })) {
|
|
42171
|
+
return getAddress(stored.manager);
|
|
42172
|
+
}
|
|
42173
|
+
const ks = readJsonFile(resolveKeyPath("manager", safe));
|
|
42174
|
+
return ks?.address ? getAddress(`0x${ks.address.replace(/^0x/, "")}`) : null;
|
|
42175
|
+
}
|
|
42176
|
+
async function mandateSimulate(options) {
|
|
42177
|
+
const json = !!options.json;
|
|
42178
|
+
const project = new ProjectContext();
|
|
42179
|
+
const chainId = project.chainId;
|
|
42180
|
+
const rpcUrl = getRpcUrl(chainId) ?? getChainById(chainId).rpcUrls.default.http[0];
|
|
42181
|
+
const pc = createPublicClient({ chain: getChainById(chainId), transport: http(rpcUrl) });
|
|
42182
|
+
const store = new MandateStore();
|
|
42183
|
+
const tracked = store.find(options.address);
|
|
42184
|
+
const rawPermission = tracked?.address ?? options.address;
|
|
42185
|
+
if (!isAddress(rawPermission, { strict: false })) {
|
|
42186
|
+
throw new Error(`--address must be a permission address or a tracked name: ${options.address}`);
|
|
42187
|
+
}
|
|
42188
|
+
const permission = getAddress(rawPermission);
|
|
42189
|
+
const stored = readJsonFile(sailPath("account.json"));
|
|
42190
|
+
if (options.sma && !isAddress(options.sma, { strict: false })) {
|
|
42191
|
+
throw new Error(`Invalid --sma address: ${options.sma}`);
|
|
42192
|
+
}
|
|
42193
|
+
const accountRaw = options.sma ?? stored?.safe;
|
|
42194
|
+
if (!accountRaw) {
|
|
42195
|
+
throw new Error("No SMA. Pass --sma <address> or create one (.sail/account.json).");
|
|
42196
|
+
}
|
|
42197
|
+
const account2 = getAddress(accountRaw);
|
|
42198
|
+
const resolvedManager = managerAddress(options.sma ?? stored?.safe);
|
|
42199
|
+
const manager = resolvedManager ?? account2;
|
|
42200
|
+
const managerIsStandIn = resolvedManager === null;
|
|
42201
|
+
const calls = resolveSampleCalls(options);
|
|
42202
|
+
let blockInfo = { number: 0n, timestamp: 0n };
|
|
42203
|
+
let blockStale = false;
|
|
42204
|
+
try {
|
|
42205
|
+
const block = await pc.getBlock();
|
|
42206
|
+
blockInfo = { number: block.number ?? 0n, timestamp: block.timestamp ?? 0n };
|
|
42207
|
+
} catch {
|
|
42208
|
+
blockStale = true;
|
|
42209
|
+
}
|
|
42210
|
+
const results = await Promise.all(
|
|
42211
|
+
calls.map(async (c, i) => {
|
|
42212
|
+
const [probe, codeCheck] = await Promise.all([
|
|
42213
|
+
probePermissionForCall({
|
|
42214
|
+
publicClient: pc,
|
|
42215
|
+
permission,
|
|
42216
|
+
account: account2,
|
|
42217
|
+
manager,
|
|
42218
|
+
call: { target: c.target, value: c.value, data: c.data },
|
|
42219
|
+
blockInfo
|
|
42220
|
+
}),
|
|
42221
|
+
checkContractExists(pc, c.target)
|
|
42222
|
+
]);
|
|
42223
|
+
const result = probe.accepted ? "pass" : "fail";
|
|
42224
|
+
return {
|
|
42225
|
+
index: i,
|
|
42226
|
+
label: c.label,
|
|
42227
|
+
target: c.target,
|
|
42228
|
+
value: c.value.toString(),
|
|
42229
|
+
result,
|
|
42230
|
+
reverted: probe.reverted,
|
|
42231
|
+
revertReason: probe.error,
|
|
42232
|
+
expect: c.expect ?? null,
|
|
42233
|
+
match: c.expect ? c.expect === result : null,
|
|
42234
|
+
targetHasCode: codeCheck.hasCode,
|
|
42235
|
+
targetCheckError: codeCheck.error
|
|
42236
|
+
};
|
|
42237
|
+
})
|
|
42238
|
+
);
|
|
42239
|
+
const mismatches = results.filter((r) => r.match === false);
|
|
42240
|
+
const noCodeTargets = results.filter((r) => !r.targetHasCode && !r.targetCheckError);
|
|
42241
|
+
const ok = mismatches.length === 0;
|
|
42242
|
+
if (json) {
|
|
42243
|
+
emit(true, () => {
|
|
42244
|
+
}, {
|
|
42245
|
+
status: ok ? "ok" : "mismatch",
|
|
42246
|
+
spendsGas: false,
|
|
42247
|
+
probe: "off-chain eth_call (evaluate)",
|
|
42248
|
+
chainId,
|
|
42249
|
+
permission,
|
|
42250
|
+
sma: account2,
|
|
42251
|
+
submitter: manager,
|
|
42252
|
+
submitterIsStandIn: managerIsStandIn,
|
|
42253
|
+
blockNumber: blockInfo.number.toString(),
|
|
42254
|
+
blockContextStale: blockStale,
|
|
42255
|
+
results: results.map((r) => ({
|
|
42256
|
+
index: r.index,
|
|
42257
|
+
label: r.label,
|
|
42258
|
+
target: r.target,
|
|
42259
|
+
value: r.value,
|
|
42260
|
+
result: r.result,
|
|
42261
|
+
reverted: r.reverted,
|
|
42262
|
+
revertReason: r.revertReason,
|
|
42263
|
+
expect: r.expect,
|
|
42264
|
+
match: r.match,
|
|
42265
|
+
targetHasCode: r.targetHasCode,
|
|
42266
|
+
targetCheckError: r.targetCheckError
|
|
42267
|
+
})),
|
|
42268
|
+
mismatches: mismatches.length,
|
|
42269
|
+
noCodeTargets: noCodeTargets.map((r) => r.target),
|
|
42270
|
+
ok
|
|
42271
|
+
});
|
|
42272
|
+
if (!ok) process.exit(1);
|
|
42273
|
+
return;
|
|
42274
|
+
}
|
|
42275
|
+
console.log("\nsailor mandate simulate \u2014 off-chain probe (eth_call). Spends NO gas, signs nothing.");
|
|
42276
|
+
console.log(
|
|
42277
|
+
"Shows what the permission's evaluate() returns for these calls. It does NOT guarantee\nthe permission is correct \u2014 only what it does for exactly these inputs."
|
|
42278
|
+
);
|
|
42279
|
+
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
42280
|
+
console.log(`Permission: ${permission}`);
|
|
42281
|
+
console.log(`SMA: ${account2}`);
|
|
42282
|
+
console.log(
|
|
42283
|
+
`Submitter: ${manager}${managerIsStandIn ? " (stand-in: no manager key found locally)" : " (agent wallet)"}`
|
|
42284
|
+
);
|
|
42285
|
+
console.log(`Chain: ${chainId} block ${blockInfo.number}${blockStale ? " \u26A0 could not fetch block \u2014 time/block-gated permissions may show false negatives" : ""}`);
|
|
42286
|
+
console.log("");
|
|
42287
|
+
for (const r of results) {
|
|
42288
|
+
const verdict = r.result === "pass" ? "PASS " : r.reverted ? "REVERT" : "FAIL ";
|
|
42289
|
+
const expectStr = r.expect === null ? "" : r.match ? ` expected ${r.expect} \u2713 MATCH` : ` expected ${r.expect} \u2717 MISMATCH`;
|
|
42290
|
+
console.log(`[${r.index + 1}] ${verdict} ${r.label}${expectStr}`);
|
|
42291
|
+
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`;
|
|
42292
|
+
console.log(` target ${r.target} ${codeNote}`);
|
|
42293
|
+
if (r.reverted && r.revertReason) {
|
|
42294
|
+
console.log(` evaluate() reverted: ${r.revertReason}`);
|
|
42295
|
+
}
|
|
42296
|
+
}
|
|
42297
|
+
console.log("");
|
|
42298
|
+
if (results.every((r) => r.expect === null)) {
|
|
42299
|
+
console.log(`Probed ${results.length} call(s). No expectations were supplied (informational only).`);
|
|
42300
|
+
} else {
|
|
42301
|
+
const matched = results.filter((r) => r.match === true).length;
|
|
42302
|
+
const checked = results.filter((r) => r.expect !== null).length;
|
|
42303
|
+
if (ok) {
|
|
42304
|
+
console.log(`Result: ${matched}/${checked} matched expectations. \u2713`);
|
|
42305
|
+
} else {
|
|
42306
|
+
console.log(`Result: ${matched}/${checked} matched, ${mismatches.length} MISMATCH. \u2717`);
|
|
42307
|
+
}
|
|
42308
|
+
}
|
|
42309
|
+
if (noCodeTargets.length > 0) {
|
|
42310
|
+
console.log(
|
|
42311
|
+
`\u26A0 ${noCodeTargets.length} target(s) have no contract code on chain ${chainId} \u2014 likely a wrong or wrong-chain address.`
|
|
42312
|
+
);
|
|
42313
|
+
}
|
|
42314
|
+
if (!ok) process.exit(1);
|
|
42315
|
+
}
|
|
42316
|
+
|
|
41742
42317
|
// src/commands/rotate-signer.ts
|
|
41743
|
-
var
|
|
42318
|
+
var import_node_fs13 = require("node:fs");
|
|
41744
42319
|
init_esm2();
|
|
41745
42320
|
var PENDING_REATTACH_FILE = ["state", "pending-reattach.json"];
|
|
41746
42321
|
async function rotateSigner(options) {
|
|
@@ -41851,8 +42426,8 @@ SMA: ${smaAddress}`);
|
|
|
41851
42426
|
}
|
|
41852
42427
|
console.log(
|
|
41853
42428
|
`
|
|
41854
|
-
\u2192
|
|
41855
|
-
|
|
42429
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
42430
|
+
http://localhost:${projectPort(process.cwd())}/#/station
|
|
41856
42431
|
`
|
|
41857
42432
|
);
|
|
41858
42433
|
});
|
|
@@ -42127,7 +42702,7 @@ function writePending(pending) {
|
|
|
42127
42702
|
}
|
|
42128
42703
|
function clearPending() {
|
|
42129
42704
|
try {
|
|
42130
|
-
(0,
|
|
42705
|
+
(0, import_node_fs13.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
|
|
42131
42706
|
} catch {
|
|
42132
42707
|
}
|
|
42133
42708
|
}
|
|
@@ -42167,8 +42742,8 @@ async function ownerConnect(options) {
|
|
|
42167
42742
|
try {
|
|
42168
42743
|
await channel.start();
|
|
42169
42744
|
if (!options.json) {
|
|
42170
|
-
console.log("\u2192 Open
|
|
42171
|
-
console.log(`
|
|
42745
|
+
console.log("\u2192 Open the Sailor dashboard and connect your wallet:");
|
|
42746
|
+
console.log(` http://localhost:${projectPort(projectRoot)}/#/station`);
|
|
42172
42747
|
if (channel.remote) console.log(" (using the running signing station)");
|
|
42173
42748
|
console.log("\nWaiting for a wallet connection\u2026");
|
|
42174
42749
|
}
|
|
@@ -42213,30 +42788,30 @@ function ownerShow(options) {
|
|
|
42213
42788
|
}
|
|
42214
42789
|
|
|
42215
42790
|
// src/commands/run.ts
|
|
42216
|
-
var
|
|
42217
|
-
var
|
|
42791
|
+
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
42792
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
42218
42793
|
var import_node_url = require("node:url");
|
|
42219
42794
|
init_esm2();
|
|
42220
42795
|
|
|
42221
42796
|
// src/lib/process.ts
|
|
42222
|
-
var
|
|
42797
|
+
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
42223
42798
|
function agentPidPath() {
|
|
42224
42799
|
return sailPath("agent.pid");
|
|
42225
42800
|
}
|
|
42226
42801
|
function writeAgentPid() {
|
|
42227
|
-
|
|
42228
|
-
|
|
42802
|
+
import_node_fs14.default.mkdirSync(sailPath(), { recursive: true });
|
|
42803
|
+
import_node_fs14.default.writeFileSync(agentPidPath(), `${process.pid}
|
|
42229
42804
|
`);
|
|
42230
42805
|
}
|
|
42231
42806
|
function clearAgentPid() {
|
|
42232
42807
|
try {
|
|
42233
|
-
|
|
42808
|
+
import_node_fs14.default.rmSync(agentPidPath());
|
|
42234
42809
|
} catch {
|
|
42235
42810
|
}
|
|
42236
42811
|
}
|
|
42237
42812
|
function readAgentPid() {
|
|
42238
42813
|
try {
|
|
42239
|
-
const pid = Number.parseInt(
|
|
42814
|
+
const pid = Number.parseInt(import_node_fs14.default.readFileSync(agentPidPath(), "utf-8").trim(), 10);
|
|
42240
42815
|
return Number.isNaN(pid) ? null : pid;
|
|
42241
42816
|
} catch {
|
|
42242
42817
|
return null;
|
|
@@ -42266,7 +42841,7 @@ var ERC20_BALANCE_ABI = [
|
|
|
42266
42841
|
function loadAgentData(filePath) {
|
|
42267
42842
|
if (!filePath) return {};
|
|
42268
42843
|
try {
|
|
42269
|
-
const parsed = JSON.parse(
|
|
42844
|
+
const parsed = JSON.parse(import_node_fs15.default.readFileSync(filePath, "utf-8"));
|
|
42270
42845
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
42271
42846
|
} catch {
|
|
42272
42847
|
return {};
|
|
@@ -42275,8 +42850,8 @@ function loadAgentData(filePath) {
|
|
|
42275
42850
|
async function loadAgent() {
|
|
42276
42851
|
const candidates = ["src/agent.ts", "src/agent.js", "dist/agent.js", "dist/src/agent.js"];
|
|
42277
42852
|
for (const rel of candidates) {
|
|
42278
|
-
const abs =
|
|
42279
|
-
if (!
|
|
42853
|
+
const abs = import_node_path11.default.join(process.cwd(), rel);
|
|
42854
|
+
if (!import_node_fs15.default.existsSync(abs)) continue;
|
|
42280
42855
|
let mod2;
|
|
42281
42856
|
if (abs.endsWith(".ts")) {
|
|
42282
42857
|
const { tsImport } = await import("tsx/esm/api");
|
|
@@ -42763,14 +43338,14 @@ async function sessionResume() {
|
|
|
42763
43338
|
}
|
|
42764
43339
|
|
|
42765
43340
|
// src/commands/station.ts
|
|
42766
|
-
var
|
|
42767
|
-
var
|
|
42768
|
-
var RUNTIME_SERVER_FILE2 = (0,
|
|
43341
|
+
var import_node_fs16 = require("node:fs");
|
|
43342
|
+
var import_node_path12 = require("node:path");
|
|
43343
|
+
var RUNTIME_SERVER_FILE2 = (0, import_node_path12.join)(".sail", "runtime", "server.json");
|
|
42769
43344
|
function readState(projectRoot) {
|
|
42770
|
-
const file = (0,
|
|
42771
|
-
if (!(0,
|
|
43345
|
+
const file = (0, import_node_path12.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
43346
|
+
if (!(0, import_node_fs16.existsSync)(file)) return null;
|
|
42772
43347
|
try {
|
|
42773
|
-
return JSON.parse((0,
|
|
43348
|
+
return JSON.parse((0, import_node_fs16.readFileSync)(file, "utf8"));
|
|
42774
43349
|
} catch {
|
|
42775
43350
|
return null;
|
|
42776
43351
|
}
|
|
@@ -42842,9 +43417,9 @@ async function stationStop(options) {
|
|
|
42842
43417
|
}
|
|
42843
43418
|
const daemon = await discoverDaemon(projectRoot);
|
|
42844
43419
|
if (!daemon) {
|
|
42845
|
-
const file = (0,
|
|
43420
|
+
const file = (0, import_node_path12.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
42846
43421
|
try {
|
|
42847
|
-
if ((0,
|
|
43422
|
+
if ((0, import_node_fs16.existsSync)(file)) (0, import_node_fs16.rmSync)(file);
|
|
42848
43423
|
} catch {
|
|
42849
43424
|
}
|
|
42850
43425
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -42860,9 +43435,9 @@ async function stationStop(options) {
|
|
|
42860
43435
|
pid: state.pid
|
|
42861
43436
|
});
|
|
42862
43437
|
} catch {
|
|
42863
|
-
const file = (0,
|
|
43438
|
+
const file = (0, import_node_path12.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
42864
43439
|
try {
|
|
42865
|
-
if ((0,
|
|
43440
|
+
if ((0, import_node_fs16.existsSync)(file)) (0, import_node_fs16.rmSync)(file);
|
|
42866
43441
|
} catch {
|
|
42867
43442
|
}
|
|
42868
43443
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -42917,15 +43492,15 @@ async function status() {
|
|
|
42917
43492
|
|
|
42918
43493
|
// src/commands/ui.ts
|
|
42919
43494
|
var import_node_child_process2 = require("node:child_process");
|
|
42920
|
-
var
|
|
43495
|
+
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
42921
43496
|
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
42922
|
-
var
|
|
42923
|
-
var UI_STATE_FILE =
|
|
43497
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
43498
|
+
var UI_STATE_FILE = import_node_path13.default.join(".sail", "runtime", "ui.json");
|
|
42924
43499
|
function readState2(projectRoot) {
|
|
42925
|
-
const file =
|
|
42926
|
-
if (!
|
|
43500
|
+
const file = import_node_path13.default.join(projectRoot, UI_STATE_FILE);
|
|
43501
|
+
if (!import_node_fs17.default.existsSync(file)) return null;
|
|
42927
43502
|
try {
|
|
42928
|
-
return JSON.parse(
|
|
43503
|
+
return JSON.parse(import_node_fs17.default.readFileSync(file, "utf-8"));
|
|
42929
43504
|
} catch {
|
|
42930
43505
|
return null;
|
|
42931
43506
|
}
|
|
@@ -42948,15 +43523,15 @@ function findFreePort(from14) {
|
|
|
42948
43523
|
}
|
|
42949
43524
|
async function uiCommand() {
|
|
42950
43525
|
const distDir = cliDistDir();
|
|
42951
|
-
const uiDistDir =
|
|
42952
|
-
const serverBundle =
|
|
43526
|
+
const uiDistDir = import_node_path13.default.join(packageRoot(), "packages", "ui", "dist");
|
|
43527
|
+
const serverBundle = import_node_path13.default.resolve(distDir, "server.cjs");
|
|
42953
43528
|
const projectRoot = process.cwd();
|
|
42954
|
-
const sailDir2 =
|
|
43529
|
+
const sailDir2 = import_node_path13.default.join(projectRoot, ".sail");
|
|
42955
43530
|
const port = await findFreePort(projectPort(projectRoot));
|
|
42956
|
-
if (!
|
|
43531
|
+
if (!import_node_fs17.default.existsSync(serverBundle)) {
|
|
42957
43532
|
throw new Error(`Server bundle not found at ${serverBundle}. Re-run the sailor build.`);
|
|
42958
43533
|
}
|
|
42959
|
-
if (!
|
|
43534
|
+
if (!import_node_fs17.default.existsSync(import_node_path13.default.join(uiDistDir, "index.html"))) {
|
|
42960
43535
|
throw new Error(`UI dist not found at ${uiDistDir}. Re-run the sailor build.`);
|
|
42961
43536
|
}
|
|
42962
43537
|
const existing = readState2(projectRoot);
|
|
@@ -42974,9 +43549,9 @@ async function uiCommand() {
|
|
|
42974
43549
|
if (!isAlive(child.pid)) {
|
|
42975
43550
|
throw new Error(`Sailor UI process exited immediately. Check that the server bundle is intact.`);
|
|
42976
43551
|
}
|
|
42977
|
-
|
|
42978
|
-
|
|
42979
|
-
|
|
43552
|
+
import_node_fs17.default.mkdirSync(import_node_path13.default.join(projectRoot, ".sail", "runtime"), { recursive: true });
|
|
43553
|
+
import_node_fs17.default.writeFileSync(
|
|
43554
|
+
import_node_path13.default.join(projectRoot, UI_STATE_FILE),
|
|
42980
43555
|
JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
|
|
42981
43556
|
);
|
|
42982
43557
|
console.log(`Sailor UI started at http://localhost:${port} (pid ${child.pid})`);
|
|
@@ -42987,7 +43562,7 @@ function uiStatus() {
|
|
|
42987
43562
|
if (state && isAlive(state.pid)) {
|
|
42988
43563
|
console.log(`\u25CF running http://localhost:${state.port} (pid ${state.pid})`);
|
|
42989
43564
|
} else {
|
|
42990
|
-
if (state)
|
|
43565
|
+
if (state) import_node_fs17.default.rmSync(import_node_path13.default.join(process.cwd(), UI_STATE_FILE), { force: true });
|
|
42991
43566
|
console.log("\u25CB Sailor UI is not running");
|
|
42992
43567
|
}
|
|
42993
43568
|
}
|
|
@@ -42999,12 +43574,12 @@ function uiStop() {
|
|
|
42999
43574
|
return;
|
|
43000
43575
|
}
|
|
43001
43576
|
if (!isAlive(state.pid)) {
|
|
43002
|
-
|
|
43577
|
+
import_node_fs17.default.rmSync(import_node_path13.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
43003
43578
|
console.log("Sailor UI is not running (stale state file removed).");
|
|
43004
43579
|
return;
|
|
43005
43580
|
}
|
|
43006
43581
|
process.kill(state.pid, "SIGTERM");
|
|
43007
|
-
|
|
43582
|
+
import_node_fs17.default.rmSync(import_node_path13.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
43008
43583
|
console.log(`Stopped Sailor UI (pid ${state.pid}).`);
|
|
43009
43584
|
}
|
|
43010
43585
|
|
|
@@ -43058,6 +43633,12 @@ keys.command("export-ci").description(
|
|
|
43058
43633
|
).action(action(keysExportCi));
|
|
43059
43634
|
var account = program2.command("account").description("Manage the Sail SMA");
|
|
43060
43635
|
account.command("create").description("Create a new Sail SMA on-chain").action(action(accountCreate));
|
|
43636
|
+
account.command("predict").description(
|
|
43637
|
+
"Compute the deterministic Safe address for a given owner + manager + salt (no gas, no deployment)"
|
|
43638
|
+
).option("--owner <address>", "Owner EOA address (defaults to .sail/account.json)").option(
|
|
43639
|
+
"--manager <address>",
|
|
43640
|
+
"Agent (manager) wallet \u2014 mixed into the kernel salt (defaults to .sail/account.json)"
|
|
43641
|
+
).option("--salt <n>", "CREATE2 salt nonce (default: 0)").option("--chain <id>", "Show prediction for one chain only").option("--json", "Emit machine-readable JSON").action(actionWith(accountPredict));
|
|
43061
43642
|
account.command("rotate-signer").description("Rotate the SMA's delegated signer (agent wallet) and re-approve its mandates").option("--sma <address>", "SMA to rotate (defaults to the active account)").option("--to <address>", "Rotate to an existing agent-wallet address instead of generating one").option("--generate", "Generate a fresh local agent wallet (default when --to is omitted)").option("--skip-reattach", "Do not re-approve the previously-attached mandates").option("--reattach-only", "Skip rotation; only re-approve mandates (resume after funding)").option("--json", "Machine-readable output").action(actionWith(rotateSigner));
|
|
43062
43643
|
var mandate = program2.command("mandate").description("Manage mandates");
|
|
43063
43644
|
mandate.command("prepare").description("Prepare a mandate draft for review and signing in the UI (MetaMask)").action(action(mandatePrepare));
|
|
@@ -43067,8 +43648,11 @@ mandate.command("attach").description("Register an already-deployed permission o
|
|
|
43067
43648
|
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));
|
|
43068
43649
|
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));
|
|
43069
43650
|
mandate.command("templates").description("Show how to author your own permission contract (and any community-deployed addresses)").option("--json", "Emit machine-readable JSON").action(actionWith(mandateTemplates));
|
|
43651
|
+
mandate.command("simulate").description(
|
|
43652
|
+
"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"
|
|
43653
|
+
).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));
|
|
43070
43654
|
mandate.command("list").description("List permission contracts deployed from this project").action(action(async () => mandateContractsList()));
|
|
43071
|
-
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("--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));
|
|
43655
|
+
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));
|
|
43072
43656
|
var station = program2.command("station").description("Manage the persistent signing station (browser signing daemon)");
|
|
43073
43657
|
station.command("start").description("Start the signing station and keep it running (blocks \u2014 run in the background)").option("--json", "Emit machine-readable JSON").action(actionWith(stationStart));
|
|
43074
43658
|
station.command("status").description("Show whether a signing station is running for this project").option("--json", "Emit machine-readable JSON").action(actionWith(stationStatus));
|