@dev.sail.money/sailor 1.3.0-224 → 1.3.0-226
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/README.md +16 -0
- package/package.json +7 -1
- package/packages/cli/dist/index.cjs +699 -135
- package/packages/cli/dist/server.cjs +15990 -17974
- package/packages/sdk/dist/abis/ConfigurablePermission.d.ts +130 -0
- package/packages/sdk/dist/abis/ConfigurablePermission.d.ts.map +1 -0
- package/packages/sdk/dist/abis/ConfigurablePermission.js +79 -0
- package/packages/sdk/dist/abis/ConfigurablePermission.js.map +1 -0
- package/packages/sdk/dist/abis/index.d.ts +1 -0
- package/packages/sdk/dist/abis/index.d.ts.map +1 -1
- package/packages/sdk/dist/abis/index.js +1 -0
- package/packages/sdk/dist/abis/index.js.map +1 -1
- package/packages/sdk/dist/index.d.ts +1 -0
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +1 -0
- 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/ui/dist/assets/{add-HBssdE_q.js → add-DoHGZfJI.js} +2 -2
- package/packages/ui/dist/assets/{all-wallets-kgnKzcam.js → all-wallets-CUKVFyT3.js} +2 -2
- package/packages/ui/dist/assets/{app-store-C7gfCF4e.js → app-store-DyQ4PZOs.js} +1 -1
- package/packages/ui/dist/assets/{apple-DmsD7XsU.js → apple-Dc-GOiDW.js} +2 -2
- package/packages/ui/dist/assets/arrow-bottom-C-dI8Oh_.js +8 -0
- package/packages/ui/dist/assets/{arrow-bottom-circle-Cl21xaXp.js → arrow-bottom-circle-BH2LebvP.js} +2 -2
- package/packages/ui/dist/assets/arrow-left-CUIn5NsD.js +8 -0
- package/packages/ui/dist/assets/arrow-right-B-X57DDF.js +8 -0
- package/packages/ui/dist/assets/arrow-top-BNOmzVbg.js +8 -0
- package/packages/ui/dist/assets/{bank-BthuR5Ky.js → bank-Dqcy3Map.js} +2 -2
- package/packages/ui/dist/assets/{basic-BSdElBI1.js → basic-CN95kOlB.js} +177 -177
- package/packages/ui/dist/assets/{browser-BMfpXAJE.js → browser-v-WzD6Au.js} +2 -2
- package/packages/ui/dist/assets/{card-BEvVqDzc.js → card-DJmQXuOi.js} +2 -2
- package/packages/ui/dist/assets/ccip-8oS512uk.js +1 -0
- package/packages/ui/dist/assets/{checkmark-BqYZHVCR.js → checkmark-6Rvy6Al7.js} +2 -2
- package/packages/ui/dist/assets/{checkmark-bold-DjNGbayE.js → checkmark-bold-GYXSMFUr.js} +2 -2
- package/packages/ui/dist/assets/chevron-bottom-BF1Fa2NO.js +8 -0
- package/packages/ui/dist/assets/chevron-left-kj9KjPLp.js +8 -0
- package/packages/ui/dist/assets/chevron-right-CHH0lg7_.js +8 -0
- package/packages/ui/dist/assets/chevron-top-DjHmnG32.js +8 -0
- package/packages/ui/dist/assets/{chrome-store-bPC0PXv4.js → chrome-store-KzNe4H9H.js} +2 -2
- package/packages/ui/dist/assets/{clock-BolGF8wp.js → clock-xHvMNQNx.js} +2 -2
- package/packages/ui/dist/assets/{close-Bo18lqFQ.js → close-nKtgX0WM.js} +2 -2
- package/packages/ui/dist/assets/{coinPlaceholder-Bz-0VLbz.js → coinPlaceholder-gnwD3g4G.js} +2 -2
- package/packages/ui/dist/assets/{compass-CKKiFCLR.js → compass-wnLBxh3w.js} +2 -2
- package/packages/ui/dist/assets/{copy-CYIav_IY.js → copy-CmLisiOG.js} +2 -2
- package/packages/ui/dist/assets/core-BLOM5s8O.js +907 -0
- package/packages/ui/dist/assets/cursor-DgwjrlpZ.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-DE9tExWo.js → cursor-transparent-CjVDknUI.js} +2 -2
- package/packages/ui/dist/assets/{desktop-CWNluv_t.js → desktop-BSGjR5fT.js} +2 -2
- package/packages/ui/dist/assets/{disconnect-Db6qWs6T.js → disconnect-DkOQ_j9U.js} +2 -2
- package/packages/ui/dist/assets/{discord-Cj6mVoBK.js → discord-DtvZ281_.js} +2 -2
- package/packages/ui/dist/assets/{etherscan-CCFLsPvo.js → etherscan-BB3baLbR.js} +2 -2
- package/packages/ui/dist/assets/events-DQ172AOg.js +1 -0
- package/packages/ui/dist/assets/{exclamation-triangle-DJWx46rU.js → exclamation-triangle-BrR8a-pR.js} +2 -2
- package/packages/ui/dist/assets/{extension-BtaF8Z9u.js → extension-BiGAMg97.js} +2 -2
- package/packages/ui/dist/assets/external-link-qUc7QuKA.js +8 -0
- package/packages/ui/dist/assets/{facebook-BoGz1nMk.js → facebook-BuXatc22.js} +2 -2
- package/packages/ui/dist/assets/{farcaster-AsPTw3iB.js → farcaster-USwPlLU8.js} +2 -2
- package/packages/ui/dist/assets/{filters-D1-1MQtc.js → filters-BWx3pZxN.js} +2 -2
- package/packages/ui/dist/assets/{github-B1FrwkiF.js → github-CUSWD7ff.js} +2 -2
- package/packages/ui/dist/assets/{google-DnrnTDFz.js → google-CxJSLEaz.js} +2 -2
- package/packages/ui/dist/assets/{help-circle-CI10dCJN.js → help-circle-_8isjSO0.js} +1 -1
- package/packages/ui/dist/assets/{id-B627Euj0.js → id-DJCzMfx_.js} +2 -2
- package/packages/ui/dist/assets/{image-3O2KHUgY.js → image-CmG69MZj.js} +2 -2
- package/packages/ui/dist/assets/{index-CeZ-3oZK.js → index-3YqzzyrK.js} +3 -3
- package/packages/ui/dist/assets/index-B07bCKJ8.css +1 -0
- package/packages/ui/dist/assets/index-BIqjq0q5.js +1 -0
- package/packages/ui/dist/assets/index-BV8s6ez1.js +1 -0
- package/packages/ui/dist/assets/index-D8zwDy7d.js +1780 -0
- package/packages/ui/dist/assets/index-DHVwxjrm.js +47 -0
- package/packages/ui/dist/assets/index-DsxB7ORb.js +16 -0
- package/packages/ui/dist/assets/index.es-Hqwz_Ukd.js +26 -0
- package/packages/ui/dist/assets/{info-CMmDZSrf.js → info-XYctdUoY.js} +2 -2
- package/packages/ui/dist/assets/{info-circle-ChsNDy1e.js → info-circle-D_fYZUhv.js} +2 -2
- package/packages/ui/dist/assets/{lightbulb-DDlT2eHQ.js → lightbulb-BqKkDThe.js} +2 -2
- package/packages/ui/dist/assets/{mail-DyTAk3JR.js → mail-CM4laVWT.js} +2 -2
- package/packages/ui/dist/assets/metamask-sdk-8TvB8vxr.js +542 -0
- package/packages/ui/dist/assets/{mobile-B1ZTQh8S.js → mobile-C2cl_MIN.js} +2 -2
- package/packages/ui/dist/assets/{more-BNIrTkTn.js → more-DOik7ytj.js} +2 -2
- package/packages/ui/dist/assets/{network-placeholder-BRBk5JfG.js → network-placeholder-CC9Cg0q_.js} +2 -2
- package/packages/ui/dist/assets/{nftPlaceholder-xtnGz2yb.js → nftPlaceholder-Oe_bTYkM.js} +2 -2
- package/packages/ui/dist/assets/{off-BfgRQBAE.js → off-ao0Rdo1E.js} +2 -2
- package/packages/ui/dist/assets/{play-store-BFjPDZvv.js → play-store-BcQlROdR.js} +2 -2
- package/packages/ui/dist/assets/{plus-C3dNKGgI.js → plus-DSOprccT.js} +2 -2
- package/packages/ui/dist/assets/{qr-code-BovNFnu8.js → qr-code-B64-C9CJ.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-DdcYEE6i.js → recycle-horizontal-BJg7qNO9.js} +2 -2
- package/packages/ui/dist/assets/{refresh-P6W_osB6.js → refresh-Dexg1q9p.js} +2 -2
- package/packages/ui/dist/assets/{reown-logo-DbesEx7U.js → reown-logo-D8KP4d24.js} +2 -2
- package/packages/ui/dist/assets/{search-DMB73W4z.js → search-CBfhIhB0.js} +2 -2
- package/packages/ui/dist/assets/{secp256k1-URVniZ2R.js → secp256k1-BOKPNuRR.js} +1 -1
- package/packages/ui/dist/assets/{send-BUsSvitv.js → send-DpJV-P0b.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontal-CjaXc-eY.js → swapHorizontal-DC-Elc2j.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontalBold-DuNmGzT_.js → swapHorizontalBold-Unn8xI55.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontalMedium-CgZZIpJT.js → swapHorizontalMedium-B58RR8wP.js} +2 -2
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-BC1bVmtH.js → swapHorizontalRoundedBold-UTrbE6zM.js} +2 -2
- package/packages/ui/dist/assets/{swapVertical-PyYv49m9.js → swapVertical-CLBtBVG1.js} +2 -2
- package/packages/ui/dist/assets/{telegram-DaCrUlL0.js → telegram-C_tvCVU8.js} +2 -2
- package/packages/ui/dist/assets/{three-dots-D9tEmhOK.js → three-dots-BIn_IFa0.js} +2 -2
- package/packages/ui/dist/assets/{twitch-2m8_XY_5.js → twitch-BqiEXRul.js} +2 -2
- package/packages/ui/dist/assets/{twitterIcon-BQ4fWtR1.js → twitterIcon-CquA5TCG.js} +2 -2
- package/packages/ui/dist/assets/{verify-DJtFLNUq.js → verify-DOUX5_SE.js} +2 -2
- package/packages/ui/dist/assets/{verify-filled-B2cSEFoP.js → verify-filled-nMk53S_a.js} +2 -2
- package/packages/ui/dist/assets/{w3m-modal-YBSDQDS1.js → w3m-modal-B-JVYtbP.js} +1 -1
- package/packages/ui/dist/assets/{wallet-C7Gv760P.js → wallet-BjbzMOXA.js} +2 -2
- package/packages/ui/dist/assets/{wallet-placeholder-DtZ8_f4p.js → wallet-placeholder-DPidGoJt.js} +2 -2
- package/packages/ui/dist/assets/{walletconnect-DsIIuQfT.js → walletconnect-Dw14KwDj.js} +3 -3
- package/packages/ui/dist/assets/{warning-circle-CTMOrGt2.js → warning-circle-Ewxxj9bx.js} +2 -2
- package/packages/ui/dist/assets/{x-BmL9CVvs.js → x-B5Li_yME.js} +2 -2
- package/packages/ui/dist/index.html +2 -2
- package/templates/default/.agents/skills/sail-mandates/references/approvals.md +3 -3
- package/templates/default/.agents/skills/sail-servers/SKILL.md +1 -0
- package/templates/default/.agents/skills/sail-swap-quote/SKILL.md +76 -0
- package/templates/default/.agents/skills/sail-template-approve-batch/SKILL.md +98 -0
- package/templates/default/.agents/skills/sail-template-borrow/SKILL.md +68 -0
- package/templates/default/.agents/skills/sail-template-deposit/SKILL.md +61 -0
- package/templates/default/.agents/skills/sail-template-swap/SKILL.md +207 -0
- package/templates/default/.agents/skills/sail-template-swap-no-oracle/SKILL.md +100 -0
- package/templates/default/.agents/skills/sail-template-transfer/SKILL.md +52 -0
- package/templates/default/.agents/skills/sail-template-withdraw/SKILL.md +50 -0
- package/templates/default/.agents/skills/sail-templates/SKILL.md +142 -0
- package/templates/default/.agents/skills/sail-templates/catalog.mjs +200 -0
- package/templates/default/.agents/skills/sail-templates/deployed.json +133 -0
- package/templates/default/.agents/skills/sail-templates/oracles/IOracle.sol +13 -0
- package/templates/default/.agents/skills/sail-templates/oracles/UniV3TwapOracle.sol +114 -0
- package/templates/default/.agents/skills/sail-templates/oracles/libs/FullMath.sol +62 -0
- package/templates/default/.agents/skills/sail-templates/oracles/libs/TickMath.sol +44 -0
- package/templates/default/.agents/skills/sail-templates/references/config-schemas.md +139 -0
- package/templates/default/.agents/skills/sail-templates/references/reuse-flow.md +139 -0
- package/templates/default/.agents/skills/sail-token-resolve/SKILL.md +174 -0
- package/templates/default/.env.example +9 -0
- package/templates/default/AGENTS.md +21 -2
- package/templates/default/scripts/quote-swap.mjs +211 -0
- package/templates/default/scripts/resolve-token.mjs +992 -0
- package/templates/default/scripts/shared-template-addr.mjs +110 -0
- package/packages/ui/dist/assets/arrow-bottom-B3CywkhY.js +0 -8
- package/packages/ui/dist/assets/arrow-left-Bp_pqRAk.js +0 -8
- package/packages/ui/dist/assets/arrow-right-CRK93G5I.js +0 -8
- package/packages/ui/dist/assets/arrow-top-DyDJtPkJ.js +0 -8
- package/packages/ui/dist/assets/ccip-BALQiE-q.js +0 -1
- package/packages/ui/dist/assets/chevron-bottom-BEHbtNKD.js +0 -8
- package/packages/ui/dist/assets/chevron-left-C__dvO-Z.js +0 -8
- package/packages/ui/dist/assets/chevron-right-9abfT5a8.js +0 -8
- package/packages/ui/dist/assets/chevron-top-B2VeyvGH.js +0 -8
- package/packages/ui/dist/assets/core-8m_0OoS0.js +0 -907
- package/packages/ui/dist/assets/cursor-D10zW2HG.js +0 -3
- package/packages/ui/dist/assets/events-BGQ3xBjc.js +0 -1
- package/packages/ui/dist/assets/external-link-5wYZl3Lh.js +0 -8
- package/packages/ui/dist/assets/fallback-B2d-ODZG.js +0 -1
- package/packages/ui/dist/assets/index-CKoOBsKn.css +0 -1
- package/packages/ui/dist/assets/index-CgsvP_iE.js +0 -1
- package/packages/ui/dist/assets/index-DDe72Fsi.js +0 -1
- package/packages/ui/dist/assets/index-DKCg39xU.js +0 -16
- package/packages/ui/dist/assets/index-DhVzwxqf.js +0 -1
- package/packages/ui/dist/assets/index-ohx1EwWJ.js +0 -1789
- package/packages/ui/dist/assets/index.es-ClarUTak.js +0 -26
- package/packages/ui/dist/assets/metamask-sdk-CoU-3z33.js +0 -542
- package/packages/ui/dist/assets/native-CJ5et6AR.js +0 -1
- package/packages/ui/dist/assets/parseSignature-DPmCI80m.js +0 -1
|
@@ -15767,13 +15767,13 @@ var init_getCallError = __esm({
|
|
|
15767
15767
|
|
|
15768
15768
|
// ../../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/utils/promise/withResolvers.js
|
|
15769
15769
|
function withResolvers() {
|
|
15770
|
-
let
|
|
15770
|
+
let resolve4 = () => void 0;
|
|
15771
15771
|
let reject = () => void 0;
|
|
15772
15772
|
const promise = new Promise((resolve_, reject_) => {
|
|
15773
|
-
|
|
15773
|
+
resolve4 = resolve_;
|
|
15774
15774
|
reject = reject_;
|
|
15775
15775
|
});
|
|
15776
|
-
return { promise, resolve:
|
|
15776
|
+
return { promise, resolve: resolve4, reject };
|
|
15777
15777
|
}
|
|
15778
15778
|
var init_withResolvers = __esm({
|
|
15779
15779
|
"../../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/utils/promise/withResolvers.js"() {
|
|
@@ -15792,8 +15792,8 @@ function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait2 = 0, sort
|
|
|
15792
15792
|
if (sort && Array.isArray(data))
|
|
15793
15793
|
data.sort(sort);
|
|
15794
15794
|
for (let i = 0; i < scheduler.length; i++) {
|
|
15795
|
-
const { resolve:
|
|
15796
|
-
|
|
15795
|
+
const { resolve: resolve4 } = scheduler[i];
|
|
15796
|
+
resolve4?.([data[i], data]);
|
|
15797
15797
|
}
|
|
15798
15798
|
}).catch((err) => {
|
|
15799
15799
|
for (let i = 0; i < scheduler.length; i++) {
|
|
@@ -15809,16 +15809,16 @@ function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait2 = 0, sort
|
|
|
15809
15809
|
return {
|
|
15810
15810
|
flush,
|
|
15811
15811
|
async schedule(args) {
|
|
15812
|
-
const { promise, resolve:
|
|
15812
|
+
const { promise, resolve: resolve4, reject } = withResolvers();
|
|
15813
15813
|
const split2 = shouldSplitBatch?.([...getBatchedArgs(), args]);
|
|
15814
15814
|
if (split2)
|
|
15815
15815
|
exec();
|
|
15816
15816
|
const hasActiveScheduler = getScheduler().length > 0;
|
|
15817
15817
|
if (hasActiveScheduler) {
|
|
15818
|
-
setScheduler({ args, resolve:
|
|
15818
|
+
setScheduler({ args, resolve: resolve4, reject });
|
|
15819
15819
|
return promise;
|
|
15820
15820
|
}
|
|
15821
|
-
setScheduler({ args, resolve:
|
|
15821
|
+
setScheduler({ args, resolve: resolve4, reject });
|
|
15822
15822
|
setTimeout(exec, wait2);
|
|
15823
15823
|
return promise;
|
|
15824
15824
|
}
|
|
@@ -16595,7 +16595,7 @@ var init_observe = __esm({
|
|
|
16595
16595
|
|
|
16596
16596
|
// ../../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/utils/wait.js
|
|
16597
16597
|
async function wait(time, { signal } = {}) {
|
|
16598
|
-
return new Promise((
|
|
16598
|
+
return new Promise((resolve4, reject) => {
|
|
16599
16599
|
if (signal?.aborted) {
|
|
16600
16600
|
reject(getAbortError(signal));
|
|
16601
16601
|
return;
|
|
@@ -16603,7 +16603,7 @@ async function wait(time, { signal } = {}) {
|
|
|
16603
16603
|
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
16604
16604
|
const timeout = setTimeout(() => {
|
|
16605
16605
|
cleanup();
|
|
16606
|
-
|
|
16606
|
+
resolve4();
|
|
16607
16607
|
}, time);
|
|
16608
16608
|
const onAbort = () => {
|
|
16609
16609
|
clearTimeout(timeout);
|
|
@@ -17419,7 +17419,7 @@ var init_calls = __esm({
|
|
|
17419
17419
|
|
|
17420
17420
|
// ../../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/utils/promise/withRetry.js
|
|
17421
17421
|
function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shouldRetry2 = () => true, signal } = {}) {
|
|
17422
|
-
return new Promise((
|
|
17422
|
+
return new Promise((resolve4, reject) => {
|
|
17423
17423
|
const attemptRetry = async ({ count = 0 } = {}) => {
|
|
17424
17424
|
if (signal?.aborted) {
|
|
17425
17425
|
reject(getAbortError(signal));
|
|
@@ -17439,7 +17439,7 @@ function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shoul
|
|
|
17439
17439
|
};
|
|
17440
17440
|
try {
|
|
17441
17441
|
const data = await fn();
|
|
17442
|
-
|
|
17442
|
+
resolve4(data);
|
|
17443
17443
|
} catch (err) {
|
|
17444
17444
|
if (signal?.aborted) {
|
|
17445
17445
|
reject(getAbortError(signal));
|
|
@@ -17586,7 +17586,7 @@ async function sendCalls(client, parameters) {
|
|
|
17586
17586
|
results.push({ reason, status: "rejected" });
|
|
17587
17587
|
}
|
|
17588
17588
|
if (experimental_fallbackDelay > 0)
|
|
17589
|
-
await new Promise((
|
|
17589
|
+
await new Promise((resolve4) => setTimeout(resolve4, experimental_fallbackDelay));
|
|
17590
17590
|
}
|
|
17591
17591
|
if (results.every((r) => r.status === "rejected"))
|
|
17592
17592
|
throw results[0].reason;
|
|
@@ -17716,9 +17716,9 @@ async function waitForCallsStatus(client, parameters) {
|
|
|
17716
17716
|
throwOnFailure = false
|
|
17717
17717
|
} = parameters;
|
|
17718
17718
|
const observerId = stringify(["waitForCallsStatus", client.uid, id]);
|
|
17719
|
-
const { promise, resolve:
|
|
17719
|
+
const { promise, resolve: resolve4, reject } = withResolvers();
|
|
17720
17720
|
let timer;
|
|
17721
|
-
const unobserve = observe(observerId, { resolve:
|
|
17721
|
+
const unobserve = observe(observerId, { resolve: resolve4, reject }, (emit2) => {
|
|
17722
17722
|
const unpoll = poll(async () => {
|
|
17723
17723
|
const done = (fn) => {
|
|
17724
17724
|
clearTimeout(timer);
|
|
@@ -18123,13 +18123,13 @@ async function isImageUri(uri) {
|
|
|
18123
18123
|
}
|
|
18124
18124
|
if (!Object.hasOwn(globalThis, "Image"))
|
|
18125
18125
|
return false;
|
|
18126
|
-
return new Promise((
|
|
18126
|
+
return new Promise((resolve4) => {
|
|
18127
18127
|
const img = new Image();
|
|
18128
18128
|
img.onload = () => {
|
|
18129
|
-
|
|
18129
|
+
resolve4(true);
|
|
18130
18130
|
};
|
|
18131
18131
|
img.onerror = () => {
|
|
18132
|
-
|
|
18132
|
+
resolve4(false);
|
|
18133
18133
|
};
|
|
18134
18134
|
img.src = uri;
|
|
18135
18135
|
});
|
|
@@ -20077,7 +20077,7 @@ var init_nonceManager = __esm({
|
|
|
20077
20077
|
|
|
20078
20078
|
// ../../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/utils/promise/withTimeout.js
|
|
20079
20079
|
function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, signal }) {
|
|
20080
|
-
return new Promise((
|
|
20080
|
+
return new Promise((resolve4, reject) => {
|
|
20081
20081
|
;
|
|
20082
20082
|
(async () => {
|
|
20083
20083
|
let timeoutId;
|
|
@@ -20092,7 +20092,7 @@ function withTimeout(fn, { errorInstance = new Error("timed out"), timeout, sign
|
|
|
20092
20092
|
}
|
|
20093
20093
|
}, timeout);
|
|
20094
20094
|
}
|
|
20095
|
-
|
|
20095
|
+
resolve4(await fn({ signal: controller?.signal || null }));
|
|
20096
20096
|
} catch (err) {
|
|
20097
20097
|
if (controller?.signal.aborted && isAbortError(err)) {
|
|
20098
20098
|
reject(errorInstance);
|
|
@@ -24137,10 +24137,10 @@ async function getWebSocketRpcClient(url, options = {}) {
|
|
|
24137
24137
|
socket.addEventListener("error", onError);
|
|
24138
24138
|
socket.addEventListener("open", onOpen);
|
|
24139
24139
|
if (socket.readyState === WebSocket5.CONNECTING) {
|
|
24140
|
-
await new Promise((
|
|
24140
|
+
await new Promise((resolve4, reject) => {
|
|
24141
24141
|
if (!socket)
|
|
24142
24142
|
return;
|
|
24143
|
-
socket.onopen =
|
|
24143
|
+
socket.onopen = resolve4;
|
|
24144
24144
|
socket.onerror = reject;
|
|
24145
24145
|
});
|
|
24146
24146
|
}
|
|
@@ -28321,13 +28321,13 @@ async function waitForTransactionReceipt(client, parameters) {
|
|
|
28321
28321
|
let retrying = false;
|
|
28322
28322
|
let _unobserve;
|
|
28323
28323
|
let _unwatch;
|
|
28324
|
-
const { promise, resolve:
|
|
28324
|
+
const { promise, resolve: resolve4, reject } = withResolvers();
|
|
28325
28325
|
const timer = timeout ? setTimeout(() => {
|
|
28326
28326
|
_unwatch?.();
|
|
28327
28327
|
_unobserve?.();
|
|
28328
28328
|
reject(new WaitForTransactionReceiptTimeoutError({ hash: hash3 }));
|
|
28329
28329
|
}, timeout) : void 0;
|
|
28330
|
-
_unobserve = observe(observerId, { onReplaced, resolve:
|
|
28330
|
+
_unobserve = observe(observerId, { onReplaced, resolve: resolve4, reject }, async (emit2) => {
|
|
28331
28331
|
receipt = await getAction(client, getTransactionReceipt, "getTransactionReceipt")({ hash: hash3 }).catch(() => void 0);
|
|
28332
28332
|
if (receipt && confirmations <= 1) {
|
|
28333
28333
|
clearTimeout(timer);
|
|
@@ -30586,7 +30586,7 @@ function webSocket(url, config = {}) {
|
|
|
30586
30586
|
},
|
|
30587
30587
|
async subscribe({ params, onData, onError }) {
|
|
30588
30588
|
const rpcClient = await getWebSocketRpcClient(url_, wsRpcClientOpts);
|
|
30589
|
-
const { result: subscriptionId } = await new Promise((
|
|
30589
|
+
const { result: subscriptionId } = await new Promise((resolve4, reject) => rpcClient.request({
|
|
30590
30590
|
body: {
|
|
30591
30591
|
method: "eth_subscribe",
|
|
30592
30592
|
params
|
|
@@ -30603,7 +30603,7 @@ function webSocket(url, config = {}) {
|
|
|
30603
30603
|
return;
|
|
30604
30604
|
}
|
|
30605
30605
|
if (typeof response.id === "number") {
|
|
30606
|
-
|
|
30606
|
+
resolve4(response);
|
|
30607
30607
|
return;
|
|
30608
30608
|
}
|
|
30609
30609
|
if (response.method !== "eth_subscription")
|
|
@@ -30614,12 +30614,12 @@ function webSocket(url, config = {}) {
|
|
|
30614
30614
|
return {
|
|
30615
30615
|
subscriptionId,
|
|
30616
30616
|
async unsubscribe() {
|
|
30617
|
-
return new Promise((
|
|
30617
|
+
return new Promise((resolve4) => rpcClient.request({
|
|
30618
30618
|
body: {
|
|
30619
30619
|
method: "eth_unsubscribe",
|
|
30620
30620
|
params: [subscriptionId]
|
|
30621
30621
|
},
|
|
30622
|
-
onResponse:
|
|
30622
|
+
onResponse: resolve4
|
|
30623
30623
|
}));
|
|
30624
30624
|
}
|
|
30625
30625
|
};
|
|
@@ -35190,8 +35190,8 @@ var require_websocket_server2 = __commonJS({
|
|
|
35190
35190
|
});
|
|
35191
35191
|
|
|
35192
35192
|
// src/index.ts
|
|
35193
|
-
var
|
|
35194
|
-
var
|
|
35193
|
+
var import_node_fs22 = require("node:fs");
|
|
35194
|
+
var import_node_path18 = require("node:path");
|
|
35195
35195
|
|
|
35196
35196
|
// ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
|
|
35197
35197
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -36355,7 +36355,7 @@ var CONFIGURABLE_PERMISSION_ABI = [
|
|
|
36355
36355
|
];
|
|
36356
36356
|
var DEFAULT_DISPATCH_GAS = 2000000n;
|
|
36357
36357
|
function delay(ms) {
|
|
36358
|
-
return new Promise((
|
|
36358
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
36359
36359
|
}
|
|
36360
36360
|
var CALL_COMPONENTS = [
|
|
36361
36361
|
{ name: "target", type: "address" },
|
|
@@ -37877,6 +37877,60 @@ var SailGovernanceAbi = [
|
|
|
37877
37877
|
}
|
|
37878
37878
|
];
|
|
37879
37879
|
|
|
37880
|
+
// ../sdk/dist/abis/ConfigurablePermission.js
|
|
37881
|
+
var ConfigurablePermissionAbi = [
|
|
37882
|
+
{
|
|
37883
|
+
type: "function",
|
|
37884
|
+
name: "configure",
|
|
37885
|
+
stateMutability: "nonpayable",
|
|
37886
|
+
inputs: [
|
|
37887
|
+
{ name: "account", type: "address" },
|
|
37888
|
+
{ name: "params", type: "bytes" },
|
|
37889
|
+
{ name: "deadline", type: "uint256" },
|
|
37890
|
+
{ name: "sig", type: "bytes" }
|
|
37891
|
+
],
|
|
37892
|
+
outputs: []
|
|
37893
|
+
},
|
|
37894
|
+
{
|
|
37895
|
+
type: "function",
|
|
37896
|
+
name: "configureDirect",
|
|
37897
|
+
stateMutability: "nonpayable",
|
|
37898
|
+
inputs: [
|
|
37899
|
+
{ name: "account", type: "address" },
|
|
37900
|
+
{ name: "params", type: "bytes" }
|
|
37901
|
+
],
|
|
37902
|
+
outputs: []
|
|
37903
|
+
},
|
|
37904
|
+
{
|
|
37905
|
+
type: "function",
|
|
37906
|
+
name: "isConfigured",
|
|
37907
|
+
stateMutability: "view",
|
|
37908
|
+
inputs: [{ name: "account", type: "address" }],
|
|
37909
|
+
outputs: [{ name: "", type: "bool" }]
|
|
37910
|
+
},
|
|
37911
|
+
{
|
|
37912
|
+
type: "function",
|
|
37913
|
+
name: "configNonces",
|
|
37914
|
+
stateMutability: "view",
|
|
37915
|
+
inputs: [{ name: "account", type: "address" }],
|
|
37916
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
37917
|
+
},
|
|
37918
|
+
{
|
|
37919
|
+
type: "function",
|
|
37920
|
+
name: "configuredEpoch",
|
|
37921
|
+
stateMutability: "view",
|
|
37922
|
+
inputs: [{ name: "account", type: "address" }],
|
|
37923
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
37924
|
+
},
|
|
37925
|
+
{
|
|
37926
|
+
type: "function",
|
|
37927
|
+
name: "hashTypedDataV4",
|
|
37928
|
+
stateMutability: "view",
|
|
37929
|
+
inputs: [{ name: "structHash", type: "bytes32" }],
|
|
37930
|
+
outputs: [{ name: "", type: "bytes32" }]
|
|
37931
|
+
}
|
|
37932
|
+
];
|
|
37933
|
+
|
|
37880
37934
|
// ../sdk/dist/safe.js
|
|
37881
37935
|
init_esm2();
|
|
37882
37936
|
var setManagerAbi = [
|
|
@@ -38759,14 +38813,14 @@ function getRl() {
|
|
|
38759
38813
|
function ask(query) {
|
|
38760
38814
|
getRl();
|
|
38761
38815
|
process.stdout.write(query);
|
|
38762
|
-
return new Promise((
|
|
38816
|
+
return new Promise((resolve4) => {
|
|
38763
38817
|
const buffered = lineQueue.shift();
|
|
38764
38818
|
if (buffered !== void 0) {
|
|
38765
|
-
|
|
38819
|
+
resolve4(buffered);
|
|
38766
38820
|
} else if (inputClosed) {
|
|
38767
|
-
|
|
38821
|
+
resolve4("");
|
|
38768
38822
|
} else {
|
|
38769
|
-
waiters.push(
|
|
38823
|
+
waiters.push(resolve4);
|
|
38770
38824
|
}
|
|
38771
38825
|
});
|
|
38772
38826
|
}
|
|
@@ -38957,11 +39011,11 @@ function isProcessAlive(pid) {
|
|
|
38957
39011
|
}
|
|
38958
39012
|
}
|
|
38959
39013
|
function findFreePort(from14) {
|
|
38960
|
-
return new Promise((
|
|
39014
|
+
return new Promise((resolve4, reject) => {
|
|
38961
39015
|
const server = import_node_net.default.createServer();
|
|
38962
39016
|
server.unref();
|
|
38963
|
-
server.on("error", () => findFreePort(from14 + 1).then(
|
|
38964
|
-
server.listen(from14, "127.0.0.1", () => server.close(() =>
|
|
39017
|
+
server.on("error", () => findFreePort(from14 + 1).then(resolve4, reject));
|
|
39018
|
+
server.listen(from14, "127.0.0.1", () => server.close(() => resolve4(from14)));
|
|
38965
39019
|
});
|
|
38966
39020
|
}
|
|
38967
39021
|
|
|
@@ -39575,8 +39629,9 @@ var SigningServer = class {
|
|
|
39575
39629
|
}
|
|
39576
39630
|
}
|
|
39577
39631
|
if (!(0, import_node_fs6.existsSync)(this.runtimeDir)) (0, import_node_fs6.mkdirSync)(this.runtimeDir, { recursive: true });
|
|
39632
|
+
const serverStatePath = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
|
|
39578
39633
|
(0, import_node_fs6.writeFileSync)(
|
|
39579
|
-
|
|
39634
|
+
serverStatePath,
|
|
39580
39635
|
JSON.stringify(
|
|
39581
39636
|
{
|
|
39582
39637
|
url: this._url,
|
|
@@ -39588,8 +39643,10 @@ var SigningServer = class {
|
|
|
39588
39643
|
},
|
|
39589
39644
|
null,
|
|
39590
39645
|
2
|
|
39591
|
-
)
|
|
39646
|
+
),
|
|
39647
|
+
{ mode: 384 }
|
|
39592
39648
|
);
|
|
39649
|
+
(0, import_node_fs6.chmodSync)(serverStatePath, 384);
|
|
39593
39650
|
}
|
|
39594
39651
|
removeRuntimeState() {
|
|
39595
39652
|
const path11 = (0, import_node_path4.join)(this.runtimeDir, SERVER_STATE_FILE);
|
|
@@ -41514,13 +41571,13 @@ Added (new in template):`);
|
|
|
41514
41571
|
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
41515
41572
|
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
41516
41573
|
function readStdin() {
|
|
41517
|
-
return new Promise((
|
|
41574
|
+
return new Promise((resolve4, reject) => {
|
|
41518
41575
|
let data = "";
|
|
41519
41576
|
process.stdin.setEncoding("utf8");
|
|
41520
41577
|
process.stdin.on("data", (c) => {
|
|
41521
41578
|
data += c;
|
|
41522
41579
|
});
|
|
41523
|
-
process.stdin.on("end", () =>
|
|
41580
|
+
process.stdin.on("end", () => resolve4(data));
|
|
41524
41581
|
process.stdin.on("error", reject);
|
|
41525
41582
|
});
|
|
41526
41583
|
}
|
|
@@ -41828,6 +41885,22 @@ var MandateStore = class {
|
|
|
41828
41885
|
this.write(data);
|
|
41829
41886
|
return mandate2;
|
|
41830
41887
|
}
|
|
41888
|
+
/**
|
|
41889
|
+
* Track a permission only if no record at its address exists yet, returning the
|
|
41890
|
+
* record either way. Used by `mandate attach` for addresses that were never
|
|
41891
|
+
* deployed from this project — e.g. a shared permission singleton the operator
|
|
41892
|
+
* attaches by address. Without a store record, `recordAttachment` is a no-op and
|
|
41893
|
+
* the permission stays invisible to `mandate prepare`/`sign`. Unlike `add`, this
|
|
41894
|
+
* never overwrites an existing record (so richer deploy-time metadata such as
|
|
41895
|
+
* `sourcePath` is preserved). For attach-only records, `txHash`/`deployedAt`
|
|
41896
|
+
* reflect the registration/first-tracked moment, not an on-chain deployment.
|
|
41897
|
+
*/
|
|
41898
|
+
ensureTracked(mandate2) {
|
|
41899
|
+
const existing = this.read().mandates.find(
|
|
41900
|
+
(m) => m.address.toLowerCase() === mandate2.address.toLowerCase()
|
|
41901
|
+
);
|
|
41902
|
+
return existing ?? this.add(mandate2);
|
|
41903
|
+
}
|
|
41831
41904
|
/** Update mutable metadata fields on a tracked mandate (name, sourcePath, artifactPath). */
|
|
41832
41905
|
update(addressOrName, patch) {
|
|
41833
41906
|
const data = this.read();
|
|
@@ -42474,6 +42547,14 @@ function publicClientFor(project) {
|
|
|
42474
42547
|
transport: http(getRpcUrl(project.chainId))
|
|
42475
42548
|
}).extend(publicActions);
|
|
42476
42549
|
}
|
|
42550
|
+
function knownTemplateLabel(chainId, address) {
|
|
42551
|
+
try {
|
|
42552
|
+
const known = getSailDeployment(chainId).knownTemplates ?? [];
|
|
42553
|
+
return known.find((t) => t.address.toLowerCase() === address.toLowerCase())?.label;
|
|
42554
|
+
} catch {
|
|
42555
|
+
return void 0;
|
|
42556
|
+
}
|
|
42557
|
+
}
|
|
42477
42558
|
async function mandateDeploy(options) {
|
|
42478
42559
|
const project = requireProject();
|
|
42479
42560
|
const channel = await createSigningChannel(process.cwd());
|
|
@@ -42943,7 +43024,14 @@ async function runAttach(project, channel, options) {
|
|
|
42943
43024
|
label,
|
|
42944
43025
|
json
|
|
42945
43026
|
);
|
|
42946
|
-
|
|
43027
|
+
store.ensureTracked({
|
|
43028
|
+
name: label,
|
|
43029
|
+
address: mandateAddress,
|
|
43030
|
+
txHash,
|
|
43031
|
+
chainId: project.chainId,
|
|
43032
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43033
|
+
});
|
|
43034
|
+
store.recordAttachment(mandateAddress, { sma, txHash });
|
|
42947
43035
|
emit(json, () => {
|
|
42948
43036
|
}, {
|
|
42949
43037
|
status: "ok",
|
|
@@ -42957,7 +43045,14 @@ async function runAttachBatch(project, channel, options, sma, store) {
|
|
|
42957
43045
|
announceSigningUrl(json);
|
|
42958
43046
|
const txHash = await attachBatchToSma(project, channel, publicClient, sma, permissions, json);
|
|
42959
43047
|
for (const permission of permissions) {
|
|
42960
|
-
|
|
43048
|
+
store.ensureTracked({
|
|
43049
|
+
name: knownTemplateLabel(project.chainId, permission) ?? permission,
|
|
43050
|
+
address: permission,
|
|
43051
|
+
txHash,
|
|
43052
|
+
chainId: project.chainId,
|
|
43053
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43054
|
+
});
|
|
43055
|
+
store.recordAttachment(permission, { sma, txHash });
|
|
42961
43056
|
}
|
|
42962
43057
|
emit(json, () => {
|
|
42963
43058
|
}, {
|
|
@@ -43553,14 +43648,37 @@ async function trackedPermissionsFor(account2, chainId, kernel) {
|
|
|
43553
43648
|
};
|
|
43554
43649
|
});
|
|
43555
43650
|
const onChain = kernel ? await fetchOnChainPermissions(account2.safe, chainId, kernel) : null;
|
|
43556
|
-
if (onChain
|
|
43557
|
-
|
|
43558
|
-
|
|
43559
|
-
|
|
43560
|
-
|
|
43651
|
+
if (onChain === null) return local;
|
|
43652
|
+
return mergeOnChainPermissions(local, onChain, knownTemplateLabeler(chainId));
|
|
43653
|
+
}
|
|
43654
|
+
function mergeOnChainPermissions(local, onChain, labelFor = () => void 0) {
|
|
43655
|
+
for (const p of local) {
|
|
43656
|
+
if (p.registeredOnSma && !onChain.has(p.address.toLowerCase())) {
|
|
43657
|
+
p.revokedOnChain = true;
|
|
43658
|
+
}
|
|
43659
|
+
}
|
|
43660
|
+
const localAddrs = new Set(local.map((p) => p.address.toLowerCase()));
|
|
43661
|
+
const extra = [];
|
|
43662
|
+
for (const addr of onChain) {
|
|
43663
|
+
if (!localAddrs.has(addr)) {
|
|
43664
|
+
extra.push({
|
|
43665
|
+
address: addr,
|
|
43666
|
+
label: labelFor(addr) ?? `permission ${addr.slice(0, 10)}\u2026`,
|
|
43667
|
+
registeredOnSma: true
|
|
43668
|
+
});
|
|
43561
43669
|
}
|
|
43562
43670
|
}
|
|
43563
|
-
return local;
|
|
43671
|
+
return [...local, ...extra];
|
|
43672
|
+
}
|
|
43673
|
+
function knownTemplateLabeler(chainId) {
|
|
43674
|
+
const map = /* @__PURE__ */ new Map();
|
|
43675
|
+
try {
|
|
43676
|
+
for (const t of getSailDeployment(chainId).knownTemplates ?? []) {
|
|
43677
|
+
map.set(t.address.toLowerCase(), t.label);
|
|
43678
|
+
}
|
|
43679
|
+
} catch {
|
|
43680
|
+
}
|
|
43681
|
+
return (addr) => map.get(addr.toLowerCase());
|
|
43564
43682
|
}
|
|
43565
43683
|
function printNoPermissionsGuidance() {
|
|
43566
43684
|
console.log(
|
|
@@ -43682,8 +43800,451 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
|
|
|
43682
43800
|
\u2713 Saved to .sail/mandate.json \u2014 agent is ready to run.`);
|
|
43683
43801
|
}
|
|
43684
43802
|
|
|
43685
|
-
// src/commands/mandate-
|
|
43803
|
+
// src/commands/mandate-configure.ts
|
|
43686
43804
|
var import_node_fs15 = require("node:fs");
|
|
43805
|
+
var import_node_path13 = require("node:path");
|
|
43806
|
+
|
|
43807
|
+
// ../sdk/dist/templates/boundedSwap.js
|
|
43808
|
+
init_esm2();
|
|
43809
|
+
var ABI = [
|
|
43810
|
+
{ name: "routers", type: "address[]" },
|
|
43811
|
+
{ name: "tokensIn", type: "address[]" },
|
|
43812
|
+
{ name: "tokensOut", type: "address[]" },
|
|
43813
|
+
{ name: "maxAmountPerTx", type: "uint256" },
|
|
43814
|
+
{ name: "maxSlippageBps", type: "uint256" },
|
|
43815
|
+
{ name: "priceOracle", type: "address" },
|
|
43816
|
+
{ name: "maxPriceAgeSec", type: "uint256" }
|
|
43817
|
+
];
|
|
43818
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
43819
|
+
var boundedSwapTemplate = {
|
|
43820
|
+
name: "SharedBoundedSwapPermission",
|
|
43821
|
+
address: "0x0000000000000000000000000000000000000000",
|
|
43822
|
+
encoder: {
|
|
43823
|
+
encode(params) {
|
|
43824
|
+
return encodeAbiParameters(ABI, [
|
|
43825
|
+
params.routers,
|
|
43826
|
+
params.tokensIn,
|
|
43827
|
+
params.tokensOut,
|
|
43828
|
+
params.maxAmountPerTx,
|
|
43829
|
+
BigInt(params.maxSlippageBps),
|
|
43830
|
+
params.priceOracle,
|
|
43831
|
+
BigInt(params.maxPriceAgeSec)
|
|
43832
|
+
]);
|
|
43833
|
+
},
|
|
43834
|
+
decode(data) {
|
|
43835
|
+
const decoded = decodeAbiParameters(ABI, data);
|
|
43836
|
+
return {
|
|
43837
|
+
routers: [...decoded[0]],
|
|
43838
|
+
tokensIn: [...decoded[1]],
|
|
43839
|
+
tokensOut: [...decoded[2]],
|
|
43840
|
+
maxAmountPerTx: decoded[3],
|
|
43841
|
+
maxSlippageBps: Number(decoded[4]),
|
|
43842
|
+
priceOracle: decoded[5],
|
|
43843
|
+
maxPriceAgeSec: Number(decoded[6])
|
|
43844
|
+
};
|
|
43845
|
+
}
|
|
43846
|
+
},
|
|
43847
|
+
explainer: {
|
|
43848
|
+
explain(params) {
|
|
43849
|
+
const warnings = [];
|
|
43850
|
+
if (params.maxSlippageBps > 100) {
|
|
43851
|
+
warnings.push(`High slippage tolerance: ${params.maxSlippageBps / 100}%`);
|
|
43852
|
+
}
|
|
43853
|
+
if (params.priceOracle === ZERO_ADDRESS) {
|
|
43854
|
+
warnings.push("No price oracle configured \u2014 swaps are not checked against a reference price");
|
|
43855
|
+
}
|
|
43856
|
+
return {
|
|
43857
|
+
templateName: "SharedBoundedSwapPermission",
|
|
43858
|
+
humanReadable: [
|
|
43859
|
+
`Maximum input per swap: ${params.maxAmountPerTx.toString()} (input-token base units)`,
|
|
43860
|
+
`Maximum slippage: ${params.maxSlippageBps / 100}%`,
|
|
43861
|
+
`Allowed routers: ${params.routers.join(", ")}`,
|
|
43862
|
+
`Allowed input tokens: ${params.tokensIn.join(", ")}`,
|
|
43863
|
+
`Allowed output tokens: ${params.tokensOut.join(", ")}`,
|
|
43864
|
+
params.priceOracle === ZERO_ADDRESS ? "Price oracle: none" : `Price oracle: ${params.priceOracle} (max age ${params.maxPriceAgeSec}s)`
|
|
43865
|
+
],
|
|
43866
|
+
warnings
|
|
43867
|
+
};
|
|
43868
|
+
}
|
|
43869
|
+
}
|
|
43870
|
+
};
|
|
43871
|
+
|
|
43872
|
+
// src/commands/mandate-configure.ts
|
|
43873
|
+
init_esm2();
|
|
43874
|
+
var TEMPLATE_REGISTRY = {
|
|
43875
|
+
SwapPermission: {
|
|
43876
|
+
label: "Bounded Swap (Uniswap V3)",
|
|
43877
|
+
bigintFields: ["maxAmountPerTx"],
|
|
43878
|
+
encode: (raw) => boundedSwapTemplate.encoder.encode(coerceSwapParams(raw)),
|
|
43879
|
+
decode: (blob) => {
|
|
43880
|
+
const p = boundedSwapTemplate.encoder.decode(blob);
|
|
43881
|
+
return {
|
|
43882
|
+
routers: p.routers,
|
|
43883
|
+
tokensIn: p.tokensIn,
|
|
43884
|
+
tokensOut: p.tokensOut,
|
|
43885
|
+
maxAmountPerTx: p.maxAmountPerTx.toString(),
|
|
43886
|
+
maxSlippageBps: p.maxSlippageBps,
|
|
43887
|
+
priceOracle: p.priceOracle,
|
|
43888
|
+
maxPriceAgeSec: p.maxPriceAgeSec
|
|
43889
|
+
};
|
|
43890
|
+
}
|
|
43891
|
+
}
|
|
43892
|
+
};
|
|
43893
|
+
function asAddressArray(v, field) {
|
|
43894
|
+
if (!Array.isArray(v)) throw new Error(`${field}: expected an array of addresses`);
|
|
43895
|
+
return v.map((x, i) => {
|
|
43896
|
+
if (typeof x !== "string" || !isAddress(x, { strict: false })) {
|
|
43897
|
+
throw new Error(`${field}[${i}]: invalid address "${String(x)}"`);
|
|
43898
|
+
}
|
|
43899
|
+
return getAddress(x);
|
|
43900
|
+
});
|
|
43901
|
+
}
|
|
43902
|
+
function asAddress(v, field) {
|
|
43903
|
+
if (typeof v !== "string" || !isAddress(v, { strict: false })) {
|
|
43904
|
+
throw new Error(`${field}: invalid address "${String(v)}"`);
|
|
43905
|
+
}
|
|
43906
|
+
return getAddress(v);
|
|
43907
|
+
}
|
|
43908
|
+
function asUint(v, field) {
|
|
43909
|
+
if (v === void 0 || v === null) throw new Error(`${field}: missing`);
|
|
43910
|
+
try {
|
|
43911
|
+
return BigInt(typeof v === "string" || typeof v === "number" ? v : String(v));
|
|
43912
|
+
} catch {
|
|
43913
|
+
throw new Error(`${field}: expected an integer, got "${String(v)}"`);
|
|
43914
|
+
}
|
|
43915
|
+
}
|
|
43916
|
+
function asInt(v, field) {
|
|
43917
|
+
const n = asUint(v, field);
|
|
43918
|
+
return Number(n);
|
|
43919
|
+
}
|
|
43920
|
+
function coerceSwapParams(raw) {
|
|
43921
|
+
return {
|
|
43922
|
+
routers: asAddressArray(raw.routers, "routers"),
|
|
43923
|
+
tokensIn: asAddressArray(raw.tokensIn, "tokensIn"),
|
|
43924
|
+
tokensOut: asAddressArray(raw.tokensOut, "tokensOut"),
|
|
43925
|
+
maxAmountPerTx: asUint(raw.maxAmountPerTx, "maxAmountPerTx"),
|
|
43926
|
+
maxSlippageBps: asInt(raw.maxSlippageBps, "maxSlippageBps"),
|
|
43927
|
+
priceOracle: asAddress(raw.priceOracle, "priceOracle"),
|
|
43928
|
+
maxPriceAgeSec: asInt(raw.maxPriceAgeSec, "maxPriceAgeSec")
|
|
43929
|
+
};
|
|
43930
|
+
}
|
|
43931
|
+
function requireProject2() {
|
|
43932
|
+
if (!ProjectContext.exists()) {
|
|
43933
|
+
console.log('No Sailor project found. Run "sailor init" first.');
|
|
43934
|
+
process.exit(1);
|
|
43935
|
+
}
|
|
43936
|
+
return new ProjectContext();
|
|
43937
|
+
}
|
|
43938
|
+
function fail2(err, json = false) {
|
|
43939
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
43940
|
+
emit(json, () => console.error(`
|
|
43941
|
+
Mandate configure failed: ${msg}`), {
|
|
43942
|
+
status: "error",
|
|
43943
|
+
error: msg
|
|
43944
|
+
});
|
|
43945
|
+
process.exit(1);
|
|
43946
|
+
}
|
|
43947
|
+
function publicClientFor2(project) {
|
|
43948
|
+
return createPublicClient({
|
|
43949
|
+
chain: getChainById(project.chainId),
|
|
43950
|
+
transport: http(getRpcUrl(project.chainId))
|
|
43951
|
+
}).extend(publicActions);
|
|
43952
|
+
}
|
|
43953
|
+
function announceSigningUrl2(json) {
|
|
43954
|
+
const url = signingPageUrl(projectPort(process.cwd()));
|
|
43955
|
+
if (json) {
|
|
43956
|
+
process.stdout.write(`${JSON.stringify({ status: "waiting_for_signature", url })}
|
|
43957
|
+
`);
|
|
43958
|
+
} else {
|
|
43959
|
+
console.log(`
|
|
43960
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
43961
|
+
${url}
|
|
43962
|
+
`);
|
|
43963
|
+
}
|
|
43964
|
+
}
|
|
43965
|
+
function resolveBlob(options) {
|
|
43966
|
+
const hasParams = options.params !== void 0;
|
|
43967
|
+
const hasArgsFile = options.argsFile !== void 0;
|
|
43968
|
+
if (hasParams && hasArgsFile) {
|
|
43969
|
+
throw new Error("Provide EITHER --params <hex> OR --args-file <path>, not both.");
|
|
43970
|
+
}
|
|
43971
|
+
if (!hasParams && !hasArgsFile) {
|
|
43972
|
+
throw new Error(
|
|
43973
|
+
"Provide the config blob as --params <0x-hex>, or as --args-file <path> paired with --template <Name>."
|
|
43974
|
+
);
|
|
43975
|
+
}
|
|
43976
|
+
if (hasParams) {
|
|
43977
|
+
const raw2 = options.params.trim();
|
|
43978
|
+
if (!isHex(raw2) || raw2.length <= 2) {
|
|
43979
|
+
throw new Error(`--params must be 0x-prefixed hex; got "${options.params}".`);
|
|
43980
|
+
}
|
|
43981
|
+
return { blob: raw2, via: "params" };
|
|
43982
|
+
}
|
|
43983
|
+
const templateName = options.template;
|
|
43984
|
+
if (!templateName) {
|
|
43985
|
+
throw new Error("--args-file requires --template <Name> (e.g. SwapPermission).");
|
|
43986
|
+
}
|
|
43987
|
+
const entry = TEMPLATE_REGISTRY[templateName];
|
|
43988
|
+
if (!entry) {
|
|
43989
|
+
throw new Error(
|
|
43990
|
+
`Unknown --template "${templateName}". Known: ${Object.keys(TEMPLATE_REGISTRY).join(", ")}. Pass a pre-encoded blob with --params for any other template.`
|
|
43991
|
+
);
|
|
43992
|
+
}
|
|
43993
|
+
const argsFilePath = (0, import_node_path13.resolve)(options.argsFile);
|
|
43994
|
+
let raw;
|
|
43995
|
+
try {
|
|
43996
|
+
raw = (0, import_node_fs15.readFileSync)(argsFilePath, "utf8").trim();
|
|
43997
|
+
} catch {
|
|
43998
|
+
throw new Error(`Cannot read --args-file: ${argsFilePath}`);
|
|
43999
|
+
}
|
|
44000
|
+
let parsed;
|
|
44001
|
+
try {
|
|
44002
|
+
parsed = JSON.parse(raw);
|
|
44003
|
+
} catch (err) {
|
|
44004
|
+
throw new Error(`--args-file is not valid JSON: ${err.message}`);
|
|
44005
|
+
}
|
|
44006
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
44007
|
+
throw new Error("--args-file must contain a JSON object of template params.");
|
|
44008
|
+
}
|
|
44009
|
+
const blob = entry.encode(parsed);
|
|
44010
|
+
return { blob, via: `template:${templateName}` };
|
|
44011
|
+
}
|
|
44012
|
+
async function mandateConfigure(options) {
|
|
44013
|
+
const project = requireProject2();
|
|
44014
|
+
const channel = await createSigningChannel(process.cwd());
|
|
44015
|
+
try {
|
|
44016
|
+
await channel.start();
|
|
44017
|
+
await runConfigure(project, channel, options);
|
|
44018
|
+
} catch (err) {
|
|
44019
|
+
fail2(err, options.json);
|
|
44020
|
+
} finally {
|
|
44021
|
+
channel.stop();
|
|
44022
|
+
}
|
|
44023
|
+
}
|
|
44024
|
+
async function runConfigure(project, channel, options) {
|
|
44025
|
+
const json = !!options.json;
|
|
44026
|
+
const say = (fn) => {
|
|
44027
|
+
if (!json) fn();
|
|
44028
|
+
};
|
|
44029
|
+
if (!isAddress(options.sma, { strict: false })) {
|
|
44030
|
+
throw new Error(`Invalid --sma address: ${options.sma}`);
|
|
44031
|
+
}
|
|
44032
|
+
if (!isAddress(options.address, { strict: false })) {
|
|
44033
|
+
throw new Error(
|
|
44034
|
+
`--address must be a deployed shared-template singleton address: ${options.address}`
|
|
44035
|
+
);
|
|
44036
|
+
}
|
|
44037
|
+
const sma = getAddress(options.sma);
|
|
44038
|
+
const singleton = getAddress(options.address);
|
|
44039
|
+
const { blob, via } = resolveBlob(options);
|
|
44040
|
+
const publicClient = publicClientFor2(project);
|
|
44041
|
+
const registered = await publicClient.readContract({
|
|
44042
|
+
address: project.contracts.kernel,
|
|
44043
|
+
abi: SailKernelAbi,
|
|
44044
|
+
functionName: "registered",
|
|
44045
|
+
args: [sma]
|
|
44046
|
+
});
|
|
44047
|
+
if (!registered) {
|
|
44048
|
+
throw new Error(`SMA ${sma} is not registered with SailKernel; cannot configure a permission for it.`);
|
|
44049
|
+
}
|
|
44050
|
+
const kernelConfig = await publicClient.readContract({
|
|
44051
|
+
address: project.contracts.kernel,
|
|
44052
|
+
abi: SailKernelAbi,
|
|
44053
|
+
functionName: "configs",
|
|
44054
|
+
args: [sma]
|
|
44055
|
+
});
|
|
44056
|
+
const permissionSigner = kernelConfig[0];
|
|
44057
|
+
if (!permissionSigner || permissionSigner === getAddress("0x0000000000000000000000000000000000000000")) {
|
|
44058
|
+
throw new Error(`SMA ${sma} has no on-chain permissionSigner; cannot configure.`);
|
|
44059
|
+
}
|
|
44060
|
+
const alreadyConfigured = await publicClient.readContract({
|
|
44061
|
+
address: singleton,
|
|
44062
|
+
abi: ConfigurablePermissionAbi,
|
|
44063
|
+
functionName: "isConfigured",
|
|
44064
|
+
args: [sma]
|
|
44065
|
+
});
|
|
44066
|
+
if (alreadyConfigured && !options.force) {
|
|
44067
|
+
say(
|
|
44068
|
+
() => console.log(
|
|
44069
|
+
`
|
|
44070
|
+
\u2713 ${singleton} is already configured for ${sma} (isConfigured == true).
|
|
44071
|
+
Re-run with --force to overwrite the current bounds.`
|
|
44072
|
+
)
|
|
44073
|
+
);
|
|
44074
|
+
emit(
|
|
44075
|
+
json,
|
|
44076
|
+
() => {
|
|
44077
|
+
},
|
|
44078
|
+
{ status: "ok", alreadyConfigured: true, singleton, sma, chainId: project.chainId }
|
|
44079
|
+
);
|
|
44080
|
+
return;
|
|
44081
|
+
}
|
|
44082
|
+
const nonce = await publicClient.readContract({
|
|
44083
|
+
address: singleton,
|
|
44084
|
+
abi: ConfigurablePermissionAbi,
|
|
44085
|
+
functionName: "configNonces",
|
|
44086
|
+
args: [sma]
|
|
44087
|
+
});
|
|
44088
|
+
say(() => {
|
|
44089
|
+
console.log(`
|
|
44090
|
+
configure ${singleton}`);
|
|
44091
|
+
console.log(` SMA: ${sma}`);
|
|
44092
|
+
console.log(` permissionSigner: ${permissionSigner} (must sign in the browser \u2014 owner tx)`);
|
|
44093
|
+
console.log(` current nonce: ${nonce}`);
|
|
44094
|
+
console.log(` already set: ${alreadyConfigured ? "yes (--force will overwrite)" : "no"}`);
|
|
44095
|
+
console.log(` config blob: ${blob} (via ${via}, ${Math.floor((blob.length - 2) / 2)} bytes)`);
|
|
44096
|
+
});
|
|
44097
|
+
const configureDirectData = encodeFunctionData({
|
|
44098
|
+
abi: ConfigurablePermissionAbi,
|
|
44099
|
+
functionName: "configureDirect",
|
|
44100
|
+
args: [sma, blob]
|
|
44101
|
+
});
|
|
44102
|
+
say(() => console.log(`
|
|
44103
|
+
Pre-flight (eth_call of configureDirect, no gas)\u2026`));
|
|
44104
|
+
try {
|
|
44105
|
+
await publicClient.simulateContract({
|
|
44106
|
+
address: singleton,
|
|
44107
|
+
abi: ConfigurablePermissionAbi,
|
|
44108
|
+
functionName: "configureDirect",
|
|
44109
|
+
args: [sma, blob],
|
|
44110
|
+
account: permissionSigner
|
|
44111
|
+
});
|
|
44112
|
+
} catch (err) {
|
|
44113
|
+
const ce = getContractError(err, {
|
|
44114
|
+
abi: ConfigurablePermissionAbi,
|
|
44115
|
+
address: singleton,
|
|
44116
|
+
args: [sma, blob],
|
|
44117
|
+
functionName: "configureDirect"
|
|
44118
|
+
});
|
|
44119
|
+
const reason = ce?.message ?? err?.message ?? String(err);
|
|
44120
|
+
throw new Error(
|
|
44121
|
+
`Pre-flight reverted \u2014 the config blob is invalid for ${singleton} on ${sma}.
|
|
44122
|
+
Revert: ${reason}
|
|
44123
|
+
This is the encoding gotcha (flat params vs wrapped struct) or an internal bound check. Re-encode per the template's _applyConfig tuple and retry.`
|
|
44124
|
+
);
|
|
44125
|
+
}
|
|
44126
|
+
say(() => console.log("\u2713 pre-flight passed (configureDirect would succeed)."));
|
|
44127
|
+
let decoded;
|
|
44128
|
+
if (options.template && TEMPLATE_REGISTRY[options.template]) {
|
|
44129
|
+
try {
|
|
44130
|
+
decoded = TEMPLATE_REGISTRY[options.template].decode(blob);
|
|
44131
|
+
say(() => {
|
|
44132
|
+
console.log("\nDecoded bounds (what the singleton will store):");
|
|
44133
|
+
for (const [k, v] of Object.entries(decoded)) {
|
|
44134
|
+
const display = Array.isArray(v) ? v.join(", ") : String(v);
|
|
44135
|
+
console.log(` ${k}: ${display}`);
|
|
44136
|
+
}
|
|
44137
|
+
});
|
|
44138
|
+
} catch {
|
|
44139
|
+
}
|
|
44140
|
+
}
|
|
44141
|
+
if (options.simulateOnly) {
|
|
44142
|
+
emit(
|
|
44143
|
+
json,
|
|
44144
|
+
() => {
|
|
44145
|
+
console.log("\n--simulate-only: stopping after pre-flight (no signing, no gas).");
|
|
44146
|
+
},
|
|
44147
|
+
{
|
|
44148
|
+
status: "ok",
|
|
44149
|
+
simulateOnly: true,
|
|
44150
|
+
singleton,
|
|
44151
|
+
sma,
|
|
44152
|
+
permissionSigner,
|
|
44153
|
+
nonce: nonce.toString(),
|
|
44154
|
+
alreadyConfigured,
|
|
44155
|
+
blob,
|
|
44156
|
+
blobBytes: Math.floor((blob.length - 2) / 2),
|
|
44157
|
+
decoded,
|
|
44158
|
+
chainId: project.chainId
|
|
44159
|
+
}
|
|
44160
|
+
);
|
|
44161
|
+
return;
|
|
44162
|
+
}
|
|
44163
|
+
const label = options.label ?? (options.template ?? "shared-template");
|
|
44164
|
+
announceSigningUrl2(json);
|
|
44165
|
+
say(
|
|
44166
|
+
() => console.log(
|
|
44167
|
+
`Pushing configure request \u2014 the mandate signer (${permissionSigner}) must approve in the browser\u2026`
|
|
44168
|
+
)
|
|
44169
|
+
);
|
|
44170
|
+
const response = await channel.requestSignature({
|
|
44171
|
+
type: "transaction",
|
|
44172
|
+
kind: "arbitrary-tx",
|
|
44173
|
+
title: `Configure "${label}"`,
|
|
44174
|
+
description: `Write per-account bounds on the shared permission ${singleton}.
|
|
44175
|
+
You (the mandate signer) send the transaction \u2014 configureDirect requires msg.sender to be the permissionSigner.`,
|
|
44176
|
+
chainId: project.chainId,
|
|
44177
|
+
to: singleton,
|
|
44178
|
+
data: configureDirectData,
|
|
44179
|
+
details: [
|
|
44180
|
+
{ label: "SMA", value: sma },
|
|
44181
|
+
{ label: "Singleton", value: singleton },
|
|
44182
|
+
{ label: "Template", value: options.template ?? "(raw blob)" },
|
|
44183
|
+
{ label: "Mandate signer", value: permissionSigner },
|
|
44184
|
+
{ label: "Config blob (bytes)", value: String(Math.floor((blob.length - 2) / 2)) },
|
|
44185
|
+
...decoded ? Object.entries(decoded).map(([k, v]) => ({
|
|
44186
|
+
label: k,
|
|
44187
|
+
value: Array.isArray(v) ? v.join(", ") : String(v)
|
|
44188
|
+
})) : []
|
|
44189
|
+
]
|
|
44190
|
+
});
|
|
44191
|
+
if (response.status === "rejected") {
|
|
44192
|
+
throw new Error(`User rejected configure: ${response.reason ?? "no reason given"}`);
|
|
44193
|
+
}
|
|
44194
|
+
if (response.status !== "signed") {
|
|
44195
|
+
throw new Error(`Expected a signed transaction, got: ${response.status}`);
|
|
44196
|
+
}
|
|
44197
|
+
say(() => console.log("Waiting for confirmation\u2026"));
|
|
44198
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: response.txHash });
|
|
44199
|
+
if (receipt.status !== "success") {
|
|
44200
|
+
throw new Error(`configureDirect transaction failed (tx ${response.txHash})`);
|
|
44201
|
+
}
|
|
44202
|
+
const configuredNow = await publicClient.readContract({
|
|
44203
|
+
address: singleton,
|
|
44204
|
+
abi: ConfigurablePermissionAbi,
|
|
44205
|
+
functionName: "isConfigured",
|
|
44206
|
+
args: [sma]
|
|
44207
|
+
});
|
|
44208
|
+
if (!configuredNow) {
|
|
44209
|
+
throw new Error(
|
|
44210
|
+
`Tx ${response.txHash} mined, but isConfigured(${sma}) is still false. Verify on-chain.`
|
|
44211
|
+
);
|
|
44212
|
+
}
|
|
44213
|
+
say(() => console.log("\u2713", `Configured ${singleton} for ${sma} (isConfigured == true).`));
|
|
44214
|
+
appendActivity({
|
|
44215
|
+
ts: nowIso(),
|
|
44216
|
+
actor: "owner",
|
|
44217
|
+
type: "permission_configured",
|
|
44218
|
+
permission: singleton,
|
|
44219
|
+
name: label,
|
|
44220
|
+
sma,
|
|
44221
|
+
txHash: response.txHash,
|
|
44222
|
+
chainId: project.chainId
|
|
44223
|
+
});
|
|
44224
|
+
emit(
|
|
44225
|
+
json,
|
|
44226
|
+
() => {
|
|
44227
|
+
console.log(
|
|
44228
|
+
`
|
|
44229
|
+
Next: prove it accepts/rejects the right calls before dispatching:
|
|
44230
|
+
sailor mandate simulate --address ${singleton} --sma ${sma} --calls ./probe.json`
|
|
44231
|
+
);
|
|
44232
|
+
},
|
|
44233
|
+
{
|
|
44234
|
+
status: "ok",
|
|
44235
|
+
singleton,
|
|
44236
|
+
sma,
|
|
44237
|
+
template: options.template,
|
|
44238
|
+
permissionSigner,
|
|
44239
|
+
txHash: response.txHash,
|
|
44240
|
+
blob,
|
|
44241
|
+
chainId: project.chainId
|
|
44242
|
+
}
|
|
44243
|
+
);
|
|
44244
|
+
}
|
|
44245
|
+
|
|
44246
|
+
// src/commands/mandate-simulate.ts
|
|
44247
|
+
var import_node_fs16 = require("node:fs");
|
|
43687
44248
|
init_esm2();
|
|
43688
44249
|
function parseExpect(raw, where) {
|
|
43689
44250
|
if (raw === void 0) return void 0;
|
|
@@ -43699,7 +44260,7 @@ function resolveSampleCalls(options) {
|
|
|
43699
44260
|
if (options.calls) {
|
|
43700
44261
|
let raw;
|
|
43701
44262
|
try {
|
|
43702
|
-
raw = JSON.parse((0,
|
|
44263
|
+
raw = JSON.parse((0, import_node_fs16.readFileSync)(options.calls, "utf8"));
|
|
43703
44264
|
} catch (err) {
|
|
43704
44265
|
throw new Error(`Could not read --calls file "${options.calls}": ${err.message}`);
|
|
43705
44266
|
}
|
|
@@ -43915,7 +44476,7 @@ async function mandateSimulate(options) {
|
|
|
43915
44476
|
}
|
|
43916
44477
|
|
|
43917
44478
|
// src/commands/rotate-signer.ts
|
|
43918
|
-
var
|
|
44479
|
+
var import_node_fs17 = require("node:fs");
|
|
43919
44480
|
init_esm2();
|
|
43920
44481
|
var PENDING_REATTACH_FILE = ["state", "pending-reattach.json"];
|
|
43921
44482
|
async function rotateSigner(options) {
|
|
@@ -44301,7 +44862,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
44301
44862
|
const keystore = await keyring.exportKeystore(password);
|
|
44302
44863
|
writeJsonFile(target, keystore, 384);
|
|
44303
44864
|
const perManagerPath = managerKeystorePath(keyring.address);
|
|
44304
|
-
(0,
|
|
44865
|
+
(0, import_node_fs17.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
44305
44866
|
writeJsonFile(perManagerPath, keystore, 384);
|
|
44306
44867
|
say(
|
|
44307
44868
|
() => console.log(
|
|
@@ -44313,7 +44874,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
44313
44874
|
function promoteManagerKeystore(newManager, say) {
|
|
44314
44875
|
const stored = readJsonFile(managerKeystorePath(newManager));
|
|
44315
44876
|
if (!stored) return;
|
|
44316
|
-
(0,
|
|
44877
|
+
(0, import_node_fs17.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
44317
44878
|
const activeTarget = keyPath("manager");
|
|
44318
44879
|
const displaced = readJsonFile(activeTarget);
|
|
44319
44880
|
if (displaced?.address) {
|
|
@@ -44365,7 +44926,7 @@ function writePending(pending) {
|
|
|
44365
44926
|
}
|
|
44366
44927
|
function clearPending() {
|
|
44367
44928
|
try {
|
|
44368
|
-
(0,
|
|
44929
|
+
(0, import_node_fs17.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
|
|
44369
44930
|
} catch {
|
|
44370
44931
|
}
|
|
44371
44932
|
}
|
|
@@ -44464,12 +45025,12 @@ function ownerShow(options) {
|
|
|
44464
45025
|
}
|
|
44465
45026
|
|
|
44466
45027
|
// src/commands/run.ts
|
|
44467
|
-
var
|
|
44468
|
-
var
|
|
45028
|
+
var import_node_fs18 = __toESM(require("node:fs"), 1);
|
|
45029
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
44469
45030
|
var import_node_url = require("node:url");
|
|
44470
45031
|
init_esm2();
|
|
44471
45032
|
var DEFAULT_INTERVAL_SEC = 60;
|
|
44472
|
-
var sleep2 = (ms) => new Promise((
|
|
45033
|
+
var sleep2 = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
44473
45034
|
var ERC20_READ_ABI = [
|
|
44474
45035
|
{
|
|
44475
45036
|
type: "function",
|
|
@@ -44499,7 +45060,7 @@ var ERC20_READ_ABI = [
|
|
|
44499
45060
|
function loadAgentData(filePath) {
|
|
44500
45061
|
if (!filePath) return {};
|
|
44501
45062
|
try {
|
|
44502
|
-
const parsed = JSON.parse(
|
|
45063
|
+
const parsed = JSON.parse(import_node_fs18.default.readFileSync(filePath, "utf-8"));
|
|
44503
45064
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
44504
45065
|
} catch {
|
|
44505
45066
|
return {};
|
|
@@ -44508,8 +45069,8 @@ function loadAgentData(filePath) {
|
|
|
44508
45069
|
async function loadAgent() {
|
|
44509
45070
|
const candidates = ["src/agent.ts", "src/agent.js", "dist/agent.js", "dist/src/agent.js"];
|
|
44510
45071
|
for (const rel of candidates) {
|
|
44511
|
-
const abs =
|
|
44512
|
-
if (!
|
|
45072
|
+
const abs = import_node_path14.default.join(process.cwd(), rel);
|
|
45073
|
+
if (!import_node_fs18.default.existsSync(abs)) continue;
|
|
44513
45074
|
let mod2;
|
|
44514
45075
|
if (abs.endsWith(".ts")) {
|
|
44515
45076
|
const { tsImport } = await import("tsx/esm/api");
|
|
@@ -44804,7 +45365,7 @@ Configure the chain in the SDK chain registry or set KERNEL_ADDRESS in .sail/.en
|
|
|
44804
45365
|
if (isConjunctive && result.txHash) {
|
|
44805
45366
|
try {
|
|
44806
45367
|
await publicClient.waitForTransactionReceipt({ hash: result.txHash, timeout: 3e4 });
|
|
44807
|
-
await new Promise((
|
|
45368
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
44808
45369
|
} catch {
|
|
44809
45370
|
}
|
|
44810
45371
|
}
|
|
@@ -44985,9 +45546,9 @@ async function scan(options) {
|
|
|
44985
45546
|
|
|
44986
45547
|
// src/commands/service.ts
|
|
44987
45548
|
var import_node_child_process2 = require("node:child_process");
|
|
44988
|
-
var
|
|
45549
|
+
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
44989
45550
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
44990
|
-
var
|
|
45551
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
44991
45552
|
function sanitizeName(raw) {
|
|
44992
45553
|
const s = raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
44993
45554
|
return s || "agent";
|
|
@@ -45106,21 +45667,21 @@ function buildWindowsTaskXml(cfg) {
|
|
|
45106
45667
|
`;
|
|
45107
45668
|
}
|
|
45108
45669
|
function isTccProtected(projectDir, home = import_node_os.default.homedir()) {
|
|
45109
|
-
const rel =
|
|
45110
|
-
if (rel.startsWith("..") ||
|
|
45111
|
-
const top = rel.split(
|
|
45670
|
+
const rel = import_node_path15.default.relative(home, import_node_path15.default.resolve(projectDir));
|
|
45671
|
+
if (rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
|
|
45672
|
+
const top = rel.split(import_node_path15.default.sep)[0];
|
|
45112
45673
|
return ["Desktop", "Documents", "Downloads"].includes(top ?? "");
|
|
45113
45674
|
}
|
|
45114
45675
|
function resolveCliEntry() {
|
|
45115
45676
|
try {
|
|
45116
|
-
return
|
|
45677
|
+
return import_node_fs19.default.realpathSync(process.argv[1]);
|
|
45117
45678
|
} catch {
|
|
45118
|
-
return
|
|
45679
|
+
return import_node_path15.default.resolve(process.argv[1]);
|
|
45119
45680
|
}
|
|
45120
45681
|
}
|
|
45121
45682
|
function resolveProjectDir(explicit) {
|
|
45122
|
-
const dir =
|
|
45123
|
-
if (!
|
|
45683
|
+
const dir = import_node_path15.default.resolve(explicit ?? process.cwd());
|
|
45684
|
+
if (!import_node_fs19.default.existsSync(import_node_path15.default.join(dir, ".sail"))) {
|
|
45124
45685
|
throw new Error(
|
|
45125
45686
|
`No .sail/ found in ${dir}.
|
|
45126
45687
|
Run this from your Sailor project root, or pass --project <path>. (The installer does not search parent directories \u2014 that would risk targeting the wrong project.)`
|
|
@@ -45132,7 +45693,7 @@ function passphraseReadiness(projectDir) {
|
|
|
45132
45693
|
const account2 = (() => {
|
|
45133
45694
|
try {
|
|
45134
45695
|
return JSON.parse(
|
|
45135
|
-
|
|
45696
|
+
import_node_fs19.default.readFileSync(import_node_path15.default.join(projectDir, ".sail", "account.json"), "utf-8")
|
|
45136
45697
|
);
|
|
45137
45698
|
} catch {
|
|
45138
45699
|
return null;
|
|
@@ -45148,28 +45709,28 @@ function passphraseReadiness(projectDir) {
|
|
|
45148
45709
|
} finally {
|
|
45149
45710
|
process.chdir(prevCwd);
|
|
45150
45711
|
}
|
|
45151
|
-
const env = parseEnvFile(
|
|
45712
|
+
const env = parseEnvFile(import_node_path15.default.join(projectDir, ".sail", ".env.local"));
|
|
45152
45713
|
const passphraseInEnvFile = Boolean(env.SAIL_PASSPHRASE);
|
|
45153
45714
|
return { keystorePresent, passphraseInEnvFile, ready: keystorePresent && passphraseInEnvFile };
|
|
45154
45715
|
}
|
|
45155
45716
|
function buildConfig(opts) {
|
|
45156
45717
|
const projectDir = resolveProjectDir(opts.project);
|
|
45157
45718
|
return {
|
|
45158
|
-
projectName: sanitizeName(
|
|
45719
|
+
projectName: sanitizeName(import_node_path15.default.basename(projectDir)),
|
|
45159
45720
|
projectDir,
|
|
45160
45721
|
nodePath: process.execPath,
|
|
45161
45722
|
cliEntry: resolveCliEntry(),
|
|
45162
|
-
logPath:
|
|
45723
|
+
logPath: import_node_path15.default.join(projectDir, ".sail", "agent.log"),
|
|
45163
45724
|
interval: opts.interval != null ? Number(opts.interval) : void 0,
|
|
45164
45725
|
chain: opts.chain != null ? Number(opts.chain) : void 0,
|
|
45165
45726
|
restartSec: 30
|
|
45166
45727
|
};
|
|
45167
45728
|
}
|
|
45168
45729
|
function plistPath(projectName) {
|
|
45169
|
-
return
|
|
45730
|
+
return import_node_path15.default.join(import_node_os.default.homedir(), "Library", "LaunchAgents", `${launchdLabel(projectName)}.plist`);
|
|
45170
45731
|
}
|
|
45171
45732
|
function systemdPath(projectName) {
|
|
45172
|
-
return
|
|
45733
|
+
return import_node_path15.default.join(import_node_os.default.homedir(), ".config", "systemd", "user", systemdUnitName(projectName));
|
|
45173
45734
|
}
|
|
45174
45735
|
async function serviceInstall(opts = {}) {
|
|
45175
45736
|
const cfg = buildConfig(opts);
|
|
@@ -45193,12 +45754,12 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45193
45754
|
console.warn(`\u26A0 ${msg}
|
|
45194
45755
|
Proceeding because --force was given.`);
|
|
45195
45756
|
}
|
|
45196
|
-
|
|
45757
|
+
import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(cfg.logPath), { recursive: true });
|
|
45197
45758
|
if (platform === "darwin") {
|
|
45198
45759
|
const plist = buildLaunchdPlist(cfg);
|
|
45199
45760
|
const dest = plistPath(cfg.projectName);
|
|
45200
|
-
|
|
45201
|
-
|
|
45761
|
+
import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(dest), { recursive: true });
|
|
45762
|
+
import_node_fs19.default.writeFileSync(dest, plist);
|
|
45202
45763
|
const uid2 = process.getuid?.() ?? 0;
|
|
45203
45764
|
try {
|
|
45204
45765
|
try {
|
|
@@ -45217,8 +45778,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45217
45778
|
if (platform === "linux") {
|
|
45218
45779
|
const unit = buildSystemdUnit(cfg);
|
|
45219
45780
|
const dest = systemdPath(cfg.projectName);
|
|
45220
|
-
|
|
45221
|
-
|
|
45781
|
+
import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(dest), { recursive: true });
|
|
45782
|
+
import_node_fs19.default.writeFileSync(dest, unit);
|
|
45222
45783
|
try {
|
|
45223
45784
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
45224
45785
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "enable", "--now", systemdUnitName(cfg.projectName)], {
|
|
@@ -45232,8 +45793,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45232
45793
|
}
|
|
45233
45794
|
if (platform === "win32") {
|
|
45234
45795
|
const xml = buildWindowsTaskXml(cfg);
|
|
45235
|
-
const dest =
|
|
45236
|
-
|
|
45796
|
+
const dest = import_node_path15.default.join(import_node_os.default.tmpdir(), `${windowsTaskName(cfg.projectName)}.xml`);
|
|
45797
|
+
import_node_fs19.default.writeFileSync(dest, xml, "utf-8");
|
|
45237
45798
|
try {
|
|
45238
45799
|
(0, import_node_child_process2.execFileSync)(
|
|
45239
45800
|
"schtasks",
|
|
@@ -45244,7 +45805,7 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45244
45805
|
throw new Error(`schtasks /Create failed: ${err.message}`);
|
|
45245
45806
|
} finally {
|
|
45246
45807
|
try {
|
|
45247
|
-
|
|
45808
|
+
import_node_fs19.default.rmSync(dest, { force: true });
|
|
45248
45809
|
} catch {
|
|
45249
45810
|
}
|
|
45250
45811
|
}
|
|
@@ -45270,14 +45831,14 @@ function okInstall(cfg, unit) {
|
|
|
45270
45831
|
);
|
|
45271
45832
|
}
|
|
45272
45833
|
async function serviceStatus(opts = {}) {
|
|
45273
|
-
const projectName = sanitizeName(
|
|
45834
|
+
const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
|
|
45274
45835
|
const platform = process.platform;
|
|
45275
45836
|
let installed = false;
|
|
45276
45837
|
let running = false;
|
|
45277
45838
|
let detail = "";
|
|
45278
45839
|
try {
|
|
45279
45840
|
if (platform === "darwin") {
|
|
45280
|
-
installed =
|
|
45841
|
+
installed = import_node_fs19.default.existsSync(plistPath(projectName));
|
|
45281
45842
|
const uid2 = process.getuid?.() ?? 0;
|
|
45282
45843
|
try {
|
|
45283
45844
|
detail = (0, import_node_child_process2.execFileSync)("launchctl", ["print", `gui/${uid2}/${launchdLabel(projectName)}`], {
|
|
@@ -45289,7 +45850,7 @@ async function serviceStatus(opts = {}) {
|
|
|
45289
45850
|
} catch {
|
|
45290
45851
|
}
|
|
45291
45852
|
} else if (platform === "linux") {
|
|
45292
|
-
installed =
|
|
45853
|
+
installed = import_node_fs19.default.existsSync(systemdPath(projectName));
|
|
45293
45854
|
try {
|
|
45294
45855
|
detail = (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "is-active", systemdUnitName(projectName)], {
|
|
45295
45856
|
encoding: "utf-8",
|
|
@@ -45325,7 +45886,7 @@ async function serviceStatus(opts = {}) {
|
|
|
45325
45886
|
);
|
|
45326
45887
|
}
|
|
45327
45888
|
async function serviceStop(opts = {}) {
|
|
45328
|
-
const projectName = sanitizeName(
|
|
45889
|
+
const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
|
|
45329
45890
|
const platform = process.platform;
|
|
45330
45891
|
if (platform === "darwin") {
|
|
45331
45892
|
const uid2 = process.getuid?.() ?? 0;
|
|
@@ -45344,7 +45905,7 @@ async function serviceStop(opts = {}) {
|
|
|
45344
45905
|
});
|
|
45345
45906
|
}
|
|
45346
45907
|
async function serviceUninstall(opts = {}) {
|
|
45347
|
-
const projectName = sanitizeName(
|
|
45908
|
+
const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
|
|
45348
45909
|
const platform = process.platform;
|
|
45349
45910
|
if (platform === "darwin") {
|
|
45350
45911
|
const uid2 = process.getuid?.() ?? 0;
|
|
@@ -45354,7 +45915,7 @@ async function serviceUninstall(opts = {}) {
|
|
|
45354
45915
|
});
|
|
45355
45916
|
} catch {
|
|
45356
45917
|
}
|
|
45357
|
-
|
|
45918
|
+
import_node_fs19.default.rmSync(plistPath(projectName), { force: true });
|
|
45358
45919
|
} else if (platform === "linux") {
|
|
45359
45920
|
try {
|
|
45360
45921
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "disable", "--now", systemdUnitName(projectName)], {
|
|
@@ -45362,7 +45923,7 @@ async function serviceUninstall(opts = {}) {
|
|
|
45362
45923
|
});
|
|
45363
45924
|
} catch {
|
|
45364
45925
|
}
|
|
45365
|
-
|
|
45926
|
+
import_node_fs19.default.rmSync(systemdPath(projectName), { force: true });
|
|
45366
45927
|
try {
|
|
45367
45928
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "ignore" });
|
|
45368
45929
|
} catch {
|
|
@@ -45380,21 +45941,21 @@ async function serviceUninstall(opts = {}) {
|
|
|
45380
45941
|
}
|
|
45381
45942
|
async function serviceLogs(opts = {}) {
|
|
45382
45943
|
const projectDir = resolveProjectDir(opts.project);
|
|
45383
|
-
const logPath =
|
|
45384
|
-
if (!
|
|
45944
|
+
const logPath = import_node_path15.default.join(projectDir, ".sail", "agent.log");
|
|
45945
|
+
if (!import_node_fs19.default.existsSync(logPath)) {
|
|
45385
45946
|
console.log(`No log yet at ${logPath}. The service writes here once it runs.`);
|
|
45386
45947
|
return;
|
|
45387
45948
|
}
|
|
45388
45949
|
if (opts.follow) {
|
|
45389
45950
|
if (process.platform === "win32") {
|
|
45390
|
-
console.log(
|
|
45951
|
+
console.log(import_node_fs19.default.readFileSync(logPath, "utf-8"));
|
|
45391
45952
|
console.log("(follow mode is not supported on Windows here \u2014 re-run to refresh)");
|
|
45392
45953
|
return;
|
|
45393
45954
|
}
|
|
45394
45955
|
(0, import_node_child_process2.execFileSync)("tail", ["-f", logPath], { stdio: "inherit" });
|
|
45395
45956
|
return;
|
|
45396
45957
|
}
|
|
45397
|
-
const lines =
|
|
45958
|
+
const lines = import_node_fs19.default.readFileSync(logPath, "utf-8").split("\n");
|
|
45398
45959
|
console.log(lines.slice(-200).join("\n"));
|
|
45399
45960
|
}
|
|
45400
45961
|
|
|
@@ -45550,14 +46111,14 @@ async function sessionResume(opts = {}) {
|
|
|
45550
46111
|
}
|
|
45551
46112
|
|
|
45552
46113
|
// src/commands/station.ts
|
|
45553
|
-
var
|
|
45554
|
-
var
|
|
45555
|
-
var RUNTIME_SERVER_FILE2 = (0,
|
|
46114
|
+
var import_node_fs20 = require("node:fs");
|
|
46115
|
+
var import_node_path16 = require("node:path");
|
|
46116
|
+
var RUNTIME_SERVER_FILE2 = (0, import_node_path16.join)(".sail", "runtime", "server.json");
|
|
45556
46117
|
function readState(projectRoot) {
|
|
45557
|
-
const file = (0,
|
|
45558
|
-
if (!(0,
|
|
46118
|
+
const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
46119
|
+
if (!(0, import_node_fs20.existsSync)(file)) return null;
|
|
45559
46120
|
try {
|
|
45560
|
-
return JSON.parse((0,
|
|
46121
|
+
return JSON.parse((0, import_node_fs20.readFileSync)(file, "utf8"));
|
|
45561
46122
|
} catch {
|
|
45562
46123
|
return null;
|
|
45563
46124
|
}
|
|
@@ -45629,9 +46190,9 @@ async function stationStop(options) {
|
|
|
45629
46190
|
}
|
|
45630
46191
|
const daemon = await discoverDaemon(projectRoot);
|
|
45631
46192
|
if (!daemon) {
|
|
45632
|
-
const file = (0,
|
|
46193
|
+
const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
45633
46194
|
try {
|
|
45634
|
-
if ((0,
|
|
46195
|
+
if ((0, import_node_fs20.existsSync)(file)) (0, import_node_fs20.rmSync)(file);
|
|
45635
46196
|
} catch {
|
|
45636
46197
|
}
|
|
45637
46198
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -45647,9 +46208,9 @@ async function stationStop(options) {
|
|
|
45647
46208
|
pid: state.pid
|
|
45648
46209
|
});
|
|
45649
46210
|
} catch {
|
|
45650
|
-
const file = (0,
|
|
46211
|
+
const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
45651
46212
|
try {
|
|
45652
|
-
if ((0,
|
|
46213
|
+
if ((0, import_node_fs20.existsSync)(file)) (0, import_node_fs20.rmSync)(file);
|
|
45653
46214
|
} catch {
|
|
45654
46215
|
}
|
|
45655
46216
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -45711,9 +46272,9 @@ async function status() {
|
|
|
45711
46272
|
|
|
45712
46273
|
// src/commands/ui.ts
|
|
45713
46274
|
var import_node_child_process5 = require("node:child_process");
|
|
45714
|
-
var
|
|
46275
|
+
var import_node_fs21 = __toESM(require("node:fs"), 1);
|
|
45715
46276
|
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
45716
|
-
var
|
|
46277
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
45717
46278
|
|
|
45718
46279
|
// src/lib/tailscale.ts
|
|
45719
46280
|
var import_node_child_process4 = require("node:child_process");
|
|
@@ -45759,12 +46320,12 @@ function tailscaleServeDown() {
|
|
|
45759
46320
|
}
|
|
45760
46321
|
|
|
45761
46322
|
// src/commands/ui.ts
|
|
45762
|
-
var UI_STATE_FILE =
|
|
46323
|
+
var UI_STATE_FILE = import_node_path17.default.join(".sail", "runtime", "ui.json");
|
|
45763
46324
|
function readState2(projectRoot) {
|
|
45764
|
-
const file =
|
|
45765
|
-
if (!
|
|
46325
|
+
const file = import_node_path17.default.join(projectRoot, UI_STATE_FILE);
|
|
46326
|
+
if (!import_node_fs21.default.existsSync(file)) return null;
|
|
45766
46327
|
try {
|
|
45767
|
-
return JSON.parse(
|
|
46328
|
+
return JSON.parse(import_node_fs21.default.readFileSync(file, "utf-8"));
|
|
45768
46329
|
} catch {
|
|
45769
46330
|
return null;
|
|
45770
46331
|
}
|
|
@@ -45772,7 +46333,7 @@ function readState2(projectRoot) {
|
|
|
45772
46333
|
function installedCliVersion() {
|
|
45773
46334
|
try {
|
|
45774
46335
|
const pkg = JSON.parse(
|
|
45775
|
-
|
|
46336
|
+
import_node_fs21.default.readFileSync(import_node_path17.default.join(packageRoot(), "package.json"), "utf-8")
|
|
45776
46337
|
);
|
|
45777
46338
|
return pkg.version ?? null;
|
|
45778
46339
|
} catch {
|
|
@@ -45799,16 +46360,16 @@ async function warnIfVersionSkew(port) {
|
|
|
45799
46360
|
}
|
|
45800
46361
|
function waitForPort(port, timeoutMs) {
|
|
45801
46362
|
const deadline = Date.now() + timeoutMs;
|
|
45802
|
-
return new Promise((
|
|
46363
|
+
return new Promise((resolve4) => {
|
|
45803
46364
|
const attempt = () => {
|
|
45804
46365
|
const socket = import_node_net2.default.connect(port, "127.0.0.1");
|
|
45805
46366
|
socket.once("connect", () => {
|
|
45806
46367
|
socket.destroy();
|
|
45807
|
-
|
|
46368
|
+
resolve4(true);
|
|
45808
46369
|
});
|
|
45809
46370
|
socket.once("error", () => {
|
|
45810
46371
|
socket.destroy();
|
|
45811
|
-
if (Date.now() > deadline)
|
|
46372
|
+
if (Date.now() > deadline) resolve4(false);
|
|
45812
46373
|
else setTimeout(attempt, 150);
|
|
45813
46374
|
});
|
|
45814
46375
|
};
|
|
@@ -45817,16 +46378,16 @@ function waitForPort(port, timeoutMs) {
|
|
|
45817
46378
|
}
|
|
45818
46379
|
async function uiCommand(opts = {}) {
|
|
45819
46380
|
const distDir = cliDistDir();
|
|
45820
|
-
const uiDistDir =
|
|
45821
|
-
const serverBundle =
|
|
46381
|
+
const uiDistDir = import_node_path17.default.join(packageRoot(), "packages", "ui", "dist");
|
|
46382
|
+
const serverBundle = import_node_path17.default.resolve(distDir, "server.cjs");
|
|
45822
46383
|
const projectRoot = process.cwd();
|
|
45823
|
-
const sailDir2 =
|
|
46384
|
+
const sailDir2 = import_node_path17.default.join(projectRoot, ".sail");
|
|
45824
46385
|
const envPort = Number(process.env.PORT);
|
|
45825
46386
|
const port = await findFreePort(Number.isInteger(envPort) && envPort > 0 && envPort <= 65535 ? envPort : projectPort(projectRoot));
|
|
45826
|
-
if (!
|
|
46387
|
+
if (!import_node_fs21.default.existsSync(serverBundle)) {
|
|
45827
46388
|
throw new Error(`Server bundle not found at ${serverBundle}. Re-run the sailor build.`);
|
|
45828
46389
|
}
|
|
45829
|
-
if (!
|
|
46390
|
+
if (!import_node_fs21.default.existsSync(import_node_path17.default.join(uiDistDir, "index.html"))) {
|
|
45830
46391
|
throw new Error(`UI dist not found at ${uiDistDir}. Re-run the sailor build.`);
|
|
45831
46392
|
}
|
|
45832
46393
|
let tailnetUrl = null;
|
|
@@ -45856,10 +46417,10 @@ async function uiCommand(opts = {}) {
|
|
|
45856
46417
|
await warnIfVersionSkew(existing.port);
|
|
45857
46418
|
return;
|
|
45858
46419
|
}
|
|
45859
|
-
const runtimeDir =
|
|
45860
|
-
|
|
45861
|
-
const logFile =
|
|
45862
|
-
const logFd =
|
|
46420
|
+
const runtimeDir = import_node_path17.default.join(projectRoot, ".sail", "runtime");
|
|
46421
|
+
import_node_fs21.default.mkdirSync(runtimeDir, { recursive: true });
|
|
46422
|
+
const logFile = import_node_path17.default.join(runtimeDir, "ui.log");
|
|
46423
|
+
const logFd = import_node_fs21.default.openSync(logFile, "a");
|
|
45863
46424
|
const corsOrigins = [process.env.SAILOR_CORS_ORIGINS, tailnetUrl].filter(Boolean).join(",");
|
|
45864
46425
|
const child = (0, import_node_child_process5.spawn)(process.execPath, [serverBundle], {
|
|
45865
46426
|
detached: true,
|
|
@@ -45874,7 +46435,7 @@ async function uiCommand(opts = {}) {
|
|
|
45874
46435
|
}
|
|
45875
46436
|
});
|
|
45876
46437
|
child.unref();
|
|
45877
|
-
|
|
46438
|
+
import_node_fs21.default.closeSync(logFd);
|
|
45878
46439
|
const READY_TIMEOUT_MS = 1e4;
|
|
45879
46440
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
45880
46441
|
let ready = false;
|
|
@@ -45888,14 +46449,14 @@ async function uiCommand(opts = {}) {
|
|
|
45888
46449
|
if (!ready) {
|
|
45889
46450
|
let tail = "";
|
|
45890
46451
|
try {
|
|
45891
|
-
tail =
|
|
46452
|
+
tail = import_node_fs21.default.readFileSync(logFile, "utf-8").split("\n").filter(Boolean).slice(-15).join("\n");
|
|
45892
46453
|
} catch {
|
|
45893
46454
|
}
|
|
45894
46455
|
throw new Error(
|
|
45895
46456
|
`Sailor UI failed to start within ${READY_TIMEOUT_MS / 1e3}s on port ${port}.` + (tail ? `
|
|
45896
46457
|
|
|
45897
46458
|
Server output:
|
|
45898
|
-
${tail}` : ` See ${
|
|
46459
|
+
${tail}` : ` See ${import_node_path17.default.relative(projectRoot, logFile)}.`)
|
|
45899
46460
|
);
|
|
45900
46461
|
}
|
|
45901
46462
|
let exposed = false;
|
|
@@ -45910,8 +46471,8 @@ ${tail}` : ` See ${import_node_path16.default.relative(projectRoot, logFile)}.`)
|
|
|
45910
46471
|
);
|
|
45911
46472
|
}
|
|
45912
46473
|
}
|
|
45913
|
-
|
|
45914
|
-
|
|
46474
|
+
import_node_fs21.default.writeFileSync(
|
|
46475
|
+
import_node_path17.default.join(projectRoot, UI_STATE_FILE),
|
|
45915
46476
|
JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString(), exposed }, null, 2)
|
|
45916
46477
|
);
|
|
45917
46478
|
console.log(`Sailor UI started at http://localhost:${port} (pid ${child.pid})`);
|
|
@@ -45924,7 +46485,7 @@ async function uiStatus() {
|
|
|
45924
46485
|
console.log(`\u25CF running http://localhost:${state.port} (pid ${state.pid})`);
|
|
45925
46486
|
await warnIfVersionSkew(state.port);
|
|
45926
46487
|
} else {
|
|
45927
|
-
if (state)
|
|
46488
|
+
if (state) import_node_fs21.default.rmSync(import_node_path17.default.join(process.cwd(), UI_STATE_FILE), { force: true });
|
|
45928
46489
|
console.log("\u25CB Sailor UI is not running");
|
|
45929
46490
|
}
|
|
45930
46491
|
}
|
|
@@ -45936,7 +46497,7 @@ function uiStop() {
|
|
|
45936
46497
|
return;
|
|
45937
46498
|
}
|
|
45938
46499
|
if (!isProcessAlive(state.pid)) {
|
|
45939
|
-
|
|
46500
|
+
import_node_fs21.default.rmSync(import_node_path17.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
45940
46501
|
console.log("Sailor UI is not running (stale state file removed).");
|
|
45941
46502
|
return;
|
|
45942
46503
|
}
|
|
@@ -45945,14 +46506,14 @@ function uiStop() {
|
|
|
45945
46506
|
tailscaleServeDown();
|
|
45946
46507
|
console.log("Tailnet exposure removed.");
|
|
45947
46508
|
}
|
|
45948
|
-
|
|
46509
|
+
import_node_fs21.default.rmSync(import_node_path17.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
45949
46510
|
console.log(`Stopped Sailor UI (pid ${state.pid}).`);
|
|
45950
46511
|
}
|
|
45951
46512
|
|
|
45952
46513
|
// src/index.ts
|
|
45953
46514
|
function cliVersion() {
|
|
45954
46515
|
try {
|
|
45955
|
-
const pkg = JSON.parse((0,
|
|
46516
|
+
const pkg = JSON.parse((0, import_node_fs22.readFileSync)((0, import_node_path18.join)(packageRoot(), "package.json"), "utf-8"));
|
|
45956
46517
|
return pkg.version ?? "0.0.0";
|
|
45957
46518
|
} catch {
|
|
45958
46519
|
return "0.0.0";
|
|
@@ -46023,6 +46584,9 @@ mandate.command("attach").description("Register one or more already-deployed per
|
|
|
46023
46584
|
"--address <mandateOrName>",
|
|
46024
46585
|
"Permission address or locally-tracked name; or a comma-separated list of addresses to register together in one signature"
|
|
46025
46586
|
).requiredOption("--sma <address>", "SMA to register the permission on").option("--label <label>", "Human-readable label shown in the signing UI").option("--json", "Emit machine-readable JSON").action(actionWith(mandateAttach));
|
|
46587
|
+
mandate.command("configure").description(
|
|
46588
|
+
"Write per-account bounds on an already-deployed shared permission singleton (configureDirect; owner tx via the signing station). Pairs with `mandate attach`, which only registers \u2014 a registered-but-unconfigured singleton denies every call."
|
|
46589
|
+
).requiredOption("--address <singleton>", "Shared permission singleton address (deployed on this chain)").requiredOption("--sma <address>", "SMA to configure the singleton for").option("--params <hex>", "Pre-encoded config blob (0x-prefixed hex)").option("--args-file <path>", "JSON file of typed params (paired with --template)").option("--template <name>", "Template name (e.g. SwapPermission) \u2014 resolves the encoder for --args-file").option("--label <label>", "Human-readable label shown in the signing UI").option("--simulate-only", "Stop after the off-chain pre-flight (no signing, no gas)").option("--force", "Re-configure even if isConfigured is already true").option("--json", "Emit machine-readable JSON").action(actionWith(mandateConfigure));
|
|
46026
46590
|
mandate.command("deploy-clone").description("[currently unavailable \u2014 no clone templates deployed on any chain; use `mandate deploy`] Deploy + register a standalone clone permission 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));
|
|
46027
46591
|
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));
|
|
46028
46592
|
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));
|