@dev.sail.money/sailor 1.3.0-223 → 1.3.0-225
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/package.json +1 -1
- package/packages/cli/dist/index.cjs +694 -133
- package/packages/cli/dist/server.cjs +15884 -17950
- 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-DLYFRKuI.js → add-QIu9SGBU.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-Dz5SZj5e.js → all-wallets-2auxp9E5.js} +1 -1
- package/packages/ui/dist/assets/{app-store-DCYRFDwY.js → app-store-BVtVvk-F.js} +1 -1
- package/packages/ui/dist/assets/{apple-BcAi8XTW.js → apple-Dq7Ppvqv.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-Bik1zp_1.js → arrow-bottom-DpT3R4Rr.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-BSA6CcrO.js → arrow-bottom-circle-hkf9bWhW.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-07r0E796.js → arrow-left-3PhiE4SD.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-CW1Ka1mT.js → arrow-right-DUIXJHib.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-BoAo8_T9.js → arrow-top-Cf--02la.js} +1 -1
- package/packages/ui/dist/assets/{bank-Bpa5anN0.js → bank-CkRSSgJy.js} +1 -1
- package/packages/ui/dist/assets/{basic-CbzdfUfs.js → basic-D9puI79I.js} +1 -1
- package/packages/ui/dist/assets/{browser-B4YQX2Tn.js → browser-BC8qo0Bh.js} +1 -1
- package/packages/ui/dist/assets/{card-CF8oS4fb.js → card-BYuGTxNc.js} +1 -1
- package/packages/ui/dist/assets/{ccip-DssR-Uhz.js → ccip-BS_rjbk9.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-BihQ9h3G.js → checkmark-C-MZeapS.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-c5EPMyPR.js → checkmark-bold-Bs3hadsW.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-Lijs68sl.js → chevron-bottom-C8mqtkD4.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-Cj7sg_Iw.js → chevron-left-Dxj-vVDJ.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-CqD-gBdk.js → chevron-right-BoIrOTtL.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-DDShxMva.js → chevron-top-BlgziB_P.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-DSBNmkPw.js → chrome-store-sDKm_6es.js} +1 -1
- package/packages/ui/dist/assets/{clock-CjlvcnX9.js → clock-BwfFymxk.js} +1 -1
- package/packages/ui/dist/assets/{close-QhgNd0Xc.js → close-BewD5_E0.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-C7TUN8V-.js → coinPlaceholder-DRPvf0NA.js} +1 -1
- package/packages/ui/dist/assets/{compass-DrE1sLwt.js → compass-BHPvd2dw.js} +1 -1
- package/packages/ui/dist/assets/{copy-CFx1aksp.js → copy-BMv4Y3KF.js} +1 -1
- package/packages/ui/dist/assets/{core-CcaMuBIR.js → core-BMNH6XFj.js} +3 -3
- package/packages/ui/dist/assets/cursor-ir0cjMUl.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-DxBdWZi8.js → cursor-transparent-DT8YBqHU.js} +1 -1
- package/packages/ui/dist/assets/{desktop-B-ATHCGS.js → desktop-BeePUUqi.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-Bvu0LqoD.js → disconnect-C2qT29qY.js} +1 -1
- package/packages/ui/dist/assets/{discord-DrRGYSx6.js → discord-I4ToELfU.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-BaQiGNrH.js → etherscan-3psXC5Ef.js} +1 -1
- package/packages/ui/dist/assets/{events-BYNiBrPy.js → events-Cdt6abbf.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-B3yAGM1Q.js → exclamation-triangle-BCaWksGJ.js} +1 -1
- package/packages/ui/dist/assets/{extension-CYA4bLg-.js → extension-DfYavvbY.js} +1 -1
- package/packages/ui/dist/assets/{external-link-D5PwFm0_.js → external-link-B8uBskz7.js} +1 -1
- package/packages/ui/dist/assets/{facebook-CEwgL1NC.js → facebook-BSvrXy3w.js} +1 -1
- package/packages/ui/dist/assets/{fallback-B9sp077f.js → fallback-BSMYROva.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-Ak6D7Lp_.js → farcaster-CcAuzEDi.js} +1 -1
- package/packages/ui/dist/assets/{filters-CJduAQRB.js → filters-umCx-UFU.js} +1 -1
- package/packages/ui/dist/assets/{github-PLN2sD5Q.js → github-CBNoBl67.js} +1 -1
- package/packages/ui/dist/assets/{google-BRRn9hKY.js → google-yyR1jNOC.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-BnvqUg2y.js → help-circle-C0WjKnIM.js} +1 -1
- package/packages/ui/dist/assets/{id-CJlrhYxX.js → id-BwIK6e_N.js} +1 -1
- package/packages/ui/dist/assets/{image-CPduqsY3.js → image-D5oAo1Te.js} +1 -1
- package/packages/ui/dist/assets/{index-Bp21-hUb.js → index-B_Gc8xPp.js} +1 -1
- package/packages/ui/dist/assets/{index-D-OgqpEg.js → index-BaEe036r.js} +1 -1
- package/packages/ui/dist/assets/{index-vEKHRoHD.js → index-BuqyrXYX.js} +1 -1
- package/packages/ui/dist/assets/index-CKoOBsKn.css +1 -0
- package/packages/ui/dist/assets/index-CPrhuDfP.js +1782 -0
- package/packages/ui/dist/assets/{index-C0GUKQXc.js → index-DCWU1RuS.js} +1 -1
- package/packages/ui/dist/assets/{index-Dyr25y7I.js → index-DMNSiu42.js} +3 -3
- package/packages/ui/dist/assets/{index.es-Dks2goS7.js → index.es-DImsg59a.js} +4 -4
- package/packages/ui/dist/assets/{info-CGNHPKFR.js → info-CtcvKk8x.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-D8mpP6LN.js → info-circle-BIm6XYyt.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-BWGaqAI3.js → lightbulb-CMj21RIi.js} +1 -1
- package/packages/ui/dist/assets/{mail-BcfubTQ2.js → mail-C805tcaU.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-B1i24ALe.js → metamask-sdk-DDk4vkrl.js} +1 -1
- package/packages/ui/dist/assets/{mobile-CglLmMeZ.js → mobile-BEii3NyZ.js} +1 -1
- package/packages/ui/dist/assets/{more-OgWHs8eZ.js → more-RSnRt81X.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-BUhDcMI_.js → network-placeholder-s9JaqzCQ.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-wxKy5Q-x.js → nftPlaceholder-Ccur2yVc.js} +1 -1
- package/packages/ui/dist/assets/{off-DxJM1N51.js → off-DUtG4rlI.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-D838ybCF.js → parseSignature-BbS8pxpB.js} +1 -1
- package/packages/ui/dist/assets/{play-store-jm12tVwP.js → play-store-Bt2HvO3e.js} +1 -1
- package/packages/ui/dist/assets/{plus--zRIsRuA.js → plus-BtEzQu0h.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-DhBJbVz8.js → qr-code-xbQZ-Nio.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-1zQ5U9as.js → recycle-horizontal-d9pzE6vq.js} +1 -1
- package/packages/ui/dist/assets/{refresh-mqmMmKBD.js → refresh-B3-2Sch0.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-RZHJRVcN.js → reown-logo-DBkmQAX8.js} +1 -1
- package/packages/ui/dist/assets/{search-Bd45qI2U.js → search-dgDA8Ou5.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-Uhtu7xK-.js → secp256k1-C4g4FCze.js} +1 -1
- package/packages/ui/dist/assets/{send-4lxASBOR.js → send-CEDXr4l7.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-Cj2JRLJS.js → swapHorizontal-Co6_f8oH.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-Byv9z2H0.js → swapHorizontalBold-k4d22FNy.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-BadlZnn_.js → swapHorizontalMedium-Des6w_mz.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-Dl20h9DP.js → swapHorizontalRoundedBold-CVd4538j.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-DoFYn8T-.js → swapVertical-Cn_eRfv8.js} +1 -1
- package/packages/ui/dist/assets/{telegram-DKM_HViT.js → telegram-BE46RC0s.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-CBLRiosA.js → three-dots-CvqWsUWa.js} +1 -1
- package/packages/ui/dist/assets/{twitch-Dj3xBpb1.js → twitch-9V7YXB0X.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-D-wqABHa.js → twitterIcon-DbUxk6yk.js} +1 -1
- package/packages/ui/dist/assets/{verify-BYs2pfC2.js → verify-CQSnwVrh.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-zJG9VG5w.js → verify-filled-DG_hDTr8.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-sbOUP95Y.js → w3m-modal-BsHGIrg7.js} +1 -1
- package/packages/ui/dist/assets/{wallet-CMl9HrCE.js → wallet-lbVIReb_.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-BneM1wji.js → wallet-placeholder-C_ndmKAs.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-DVz3u0az.js → walletconnect-ByDpG-E0.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-B_P5OBud.js → warning-circle-hrS3II0d.js} +1 -1
- package/packages/ui/dist/assets/{x-CU4y53M6.js → x-BPMn3x5J.js} +1 -1
- 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-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/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/cursor-DXDOwzFz.js +0 -3
- package/packages/ui/dist/assets/index-BGmLv6wn.js +0 -1789
- package/packages/ui/dist/assets/index-lhNfD4jA.css +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
|
|
|
@@ -41514,13 +41568,13 @@ Added (new in template):`);
|
|
|
41514
41568
|
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
41515
41569
|
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
41516
41570
|
function readStdin() {
|
|
41517
|
-
return new Promise((
|
|
41571
|
+
return new Promise((resolve4, reject) => {
|
|
41518
41572
|
let data = "";
|
|
41519
41573
|
process.stdin.setEncoding("utf8");
|
|
41520
41574
|
process.stdin.on("data", (c) => {
|
|
41521
41575
|
data += c;
|
|
41522
41576
|
});
|
|
41523
|
-
process.stdin.on("end", () =>
|
|
41577
|
+
process.stdin.on("end", () => resolve4(data));
|
|
41524
41578
|
process.stdin.on("error", reject);
|
|
41525
41579
|
});
|
|
41526
41580
|
}
|
|
@@ -41828,6 +41882,22 @@ var MandateStore = class {
|
|
|
41828
41882
|
this.write(data);
|
|
41829
41883
|
return mandate2;
|
|
41830
41884
|
}
|
|
41885
|
+
/**
|
|
41886
|
+
* Track a permission only if no record at its address exists yet, returning the
|
|
41887
|
+
* record either way. Used by `mandate attach` for addresses that were never
|
|
41888
|
+
* deployed from this project — e.g. a shared permission singleton the operator
|
|
41889
|
+
* attaches by address. Without a store record, `recordAttachment` is a no-op and
|
|
41890
|
+
* the permission stays invisible to `mandate prepare`/`sign`. Unlike `add`, this
|
|
41891
|
+
* never overwrites an existing record (so richer deploy-time metadata such as
|
|
41892
|
+
* `sourcePath` is preserved). For attach-only records, `txHash`/`deployedAt`
|
|
41893
|
+
* reflect the registration/first-tracked moment, not an on-chain deployment.
|
|
41894
|
+
*/
|
|
41895
|
+
ensureTracked(mandate2) {
|
|
41896
|
+
const existing = this.read().mandates.find(
|
|
41897
|
+
(m) => m.address.toLowerCase() === mandate2.address.toLowerCase()
|
|
41898
|
+
);
|
|
41899
|
+
return existing ?? this.add(mandate2);
|
|
41900
|
+
}
|
|
41831
41901
|
/** Update mutable metadata fields on a tracked mandate (name, sourcePath, artifactPath). */
|
|
41832
41902
|
update(addressOrName, patch) {
|
|
41833
41903
|
const data = this.read();
|
|
@@ -42474,6 +42544,14 @@ function publicClientFor(project) {
|
|
|
42474
42544
|
transport: http(getRpcUrl(project.chainId))
|
|
42475
42545
|
}).extend(publicActions);
|
|
42476
42546
|
}
|
|
42547
|
+
function knownTemplateLabel(chainId, address) {
|
|
42548
|
+
try {
|
|
42549
|
+
const known = getSailDeployment(chainId).knownTemplates ?? [];
|
|
42550
|
+
return known.find((t) => t.address.toLowerCase() === address.toLowerCase())?.label;
|
|
42551
|
+
} catch {
|
|
42552
|
+
return void 0;
|
|
42553
|
+
}
|
|
42554
|
+
}
|
|
42477
42555
|
async function mandateDeploy(options) {
|
|
42478
42556
|
const project = requireProject();
|
|
42479
42557
|
const channel = await createSigningChannel(process.cwd());
|
|
@@ -42943,7 +43021,14 @@ async function runAttach(project, channel, options) {
|
|
|
42943
43021
|
label,
|
|
42944
43022
|
json
|
|
42945
43023
|
);
|
|
42946
|
-
|
|
43024
|
+
store.ensureTracked({
|
|
43025
|
+
name: label,
|
|
43026
|
+
address: mandateAddress,
|
|
43027
|
+
txHash,
|
|
43028
|
+
chainId: project.chainId,
|
|
43029
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43030
|
+
});
|
|
43031
|
+
store.recordAttachment(mandateAddress, { sma, txHash });
|
|
42947
43032
|
emit(json, () => {
|
|
42948
43033
|
}, {
|
|
42949
43034
|
status: "ok",
|
|
@@ -42957,7 +43042,14 @@ async function runAttachBatch(project, channel, options, sma, store) {
|
|
|
42957
43042
|
announceSigningUrl(json);
|
|
42958
43043
|
const txHash = await attachBatchToSma(project, channel, publicClient, sma, permissions, json);
|
|
42959
43044
|
for (const permission of permissions) {
|
|
42960
|
-
|
|
43045
|
+
store.ensureTracked({
|
|
43046
|
+
name: knownTemplateLabel(project.chainId, permission) ?? permission,
|
|
43047
|
+
address: permission,
|
|
43048
|
+
txHash,
|
|
43049
|
+
chainId: project.chainId,
|
|
43050
|
+
deployedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43051
|
+
});
|
|
43052
|
+
store.recordAttachment(permission, { sma, txHash });
|
|
42961
43053
|
}
|
|
42962
43054
|
emit(json, () => {
|
|
42963
43055
|
}, {
|
|
@@ -43553,14 +43645,37 @@ async function trackedPermissionsFor(account2, chainId, kernel) {
|
|
|
43553
43645
|
};
|
|
43554
43646
|
});
|
|
43555
43647
|
const onChain = kernel ? await fetchOnChainPermissions(account2.safe, chainId, kernel) : null;
|
|
43556
|
-
if (onChain
|
|
43557
|
-
|
|
43558
|
-
|
|
43559
|
-
|
|
43560
|
-
|
|
43648
|
+
if (onChain === null) return local;
|
|
43649
|
+
return mergeOnChainPermissions(local, onChain, knownTemplateLabeler(chainId));
|
|
43650
|
+
}
|
|
43651
|
+
function mergeOnChainPermissions(local, onChain, labelFor = () => void 0) {
|
|
43652
|
+
for (const p of local) {
|
|
43653
|
+
if (p.registeredOnSma && !onChain.has(p.address.toLowerCase())) {
|
|
43654
|
+
p.revokedOnChain = true;
|
|
43655
|
+
}
|
|
43656
|
+
}
|
|
43657
|
+
const localAddrs = new Set(local.map((p) => p.address.toLowerCase()));
|
|
43658
|
+
const extra = [];
|
|
43659
|
+
for (const addr of onChain) {
|
|
43660
|
+
if (!localAddrs.has(addr)) {
|
|
43661
|
+
extra.push({
|
|
43662
|
+
address: addr,
|
|
43663
|
+
label: labelFor(addr) ?? `permission ${addr.slice(0, 10)}\u2026`,
|
|
43664
|
+
registeredOnSma: true
|
|
43665
|
+
});
|
|
43561
43666
|
}
|
|
43562
43667
|
}
|
|
43563
|
-
return local;
|
|
43668
|
+
return [...local, ...extra];
|
|
43669
|
+
}
|
|
43670
|
+
function knownTemplateLabeler(chainId) {
|
|
43671
|
+
const map = /* @__PURE__ */ new Map();
|
|
43672
|
+
try {
|
|
43673
|
+
for (const t of getSailDeployment(chainId).knownTemplates ?? []) {
|
|
43674
|
+
map.set(t.address.toLowerCase(), t.label);
|
|
43675
|
+
}
|
|
43676
|
+
} catch {
|
|
43677
|
+
}
|
|
43678
|
+
return (addr) => map.get(addr.toLowerCase());
|
|
43564
43679
|
}
|
|
43565
43680
|
function printNoPermissionsGuidance() {
|
|
43566
43681
|
console.log(
|
|
@@ -43682,8 +43797,451 @@ ${unregistered.length} permission(s) are not yet registered on this SMA. Initiat
|
|
|
43682
43797
|
\u2713 Saved to .sail/mandate.json \u2014 agent is ready to run.`);
|
|
43683
43798
|
}
|
|
43684
43799
|
|
|
43685
|
-
// src/commands/mandate-
|
|
43800
|
+
// src/commands/mandate-configure.ts
|
|
43686
43801
|
var import_node_fs15 = require("node:fs");
|
|
43802
|
+
var import_node_path13 = require("node:path");
|
|
43803
|
+
|
|
43804
|
+
// ../sdk/dist/templates/boundedSwap.js
|
|
43805
|
+
init_esm2();
|
|
43806
|
+
var ABI = [
|
|
43807
|
+
{ name: "routers", type: "address[]" },
|
|
43808
|
+
{ name: "tokensIn", type: "address[]" },
|
|
43809
|
+
{ name: "tokensOut", type: "address[]" },
|
|
43810
|
+
{ name: "maxAmountPerTx", type: "uint256" },
|
|
43811
|
+
{ name: "maxSlippageBps", type: "uint256" },
|
|
43812
|
+
{ name: "priceOracle", type: "address" },
|
|
43813
|
+
{ name: "maxPriceAgeSec", type: "uint256" }
|
|
43814
|
+
];
|
|
43815
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
43816
|
+
var boundedSwapTemplate = {
|
|
43817
|
+
name: "SharedBoundedSwapPermission",
|
|
43818
|
+
address: "0x0000000000000000000000000000000000000000",
|
|
43819
|
+
encoder: {
|
|
43820
|
+
encode(params) {
|
|
43821
|
+
return encodeAbiParameters(ABI, [
|
|
43822
|
+
params.routers,
|
|
43823
|
+
params.tokensIn,
|
|
43824
|
+
params.tokensOut,
|
|
43825
|
+
params.maxAmountPerTx,
|
|
43826
|
+
BigInt(params.maxSlippageBps),
|
|
43827
|
+
params.priceOracle,
|
|
43828
|
+
BigInt(params.maxPriceAgeSec)
|
|
43829
|
+
]);
|
|
43830
|
+
},
|
|
43831
|
+
decode(data) {
|
|
43832
|
+
const decoded = decodeAbiParameters(ABI, data);
|
|
43833
|
+
return {
|
|
43834
|
+
routers: [...decoded[0]],
|
|
43835
|
+
tokensIn: [...decoded[1]],
|
|
43836
|
+
tokensOut: [...decoded[2]],
|
|
43837
|
+
maxAmountPerTx: decoded[3],
|
|
43838
|
+
maxSlippageBps: Number(decoded[4]),
|
|
43839
|
+
priceOracle: decoded[5],
|
|
43840
|
+
maxPriceAgeSec: Number(decoded[6])
|
|
43841
|
+
};
|
|
43842
|
+
}
|
|
43843
|
+
},
|
|
43844
|
+
explainer: {
|
|
43845
|
+
explain(params) {
|
|
43846
|
+
const warnings = [];
|
|
43847
|
+
if (params.maxSlippageBps > 100) {
|
|
43848
|
+
warnings.push(`High slippage tolerance: ${params.maxSlippageBps / 100}%`);
|
|
43849
|
+
}
|
|
43850
|
+
if (params.priceOracle === ZERO_ADDRESS) {
|
|
43851
|
+
warnings.push("No price oracle configured \u2014 swaps are not checked against a reference price");
|
|
43852
|
+
}
|
|
43853
|
+
return {
|
|
43854
|
+
templateName: "SharedBoundedSwapPermission",
|
|
43855
|
+
humanReadable: [
|
|
43856
|
+
`Maximum input per swap: ${params.maxAmountPerTx.toString()} (input-token base units)`,
|
|
43857
|
+
`Maximum slippage: ${params.maxSlippageBps / 100}%`,
|
|
43858
|
+
`Allowed routers: ${params.routers.join(", ")}`,
|
|
43859
|
+
`Allowed input tokens: ${params.tokensIn.join(", ")}`,
|
|
43860
|
+
`Allowed output tokens: ${params.tokensOut.join(", ")}`,
|
|
43861
|
+
params.priceOracle === ZERO_ADDRESS ? "Price oracle: none" : `Price oracle: ${params.priceOracle} (max age ${params.maxPriceAgeSec}s)`
|
|
43862
|
+
],
|
|
43863
|
+
warnings
|
|
43864
|
+
};
|
|
43865
|
+
}
|
|
43866
|
+
}
|
|
43867
|
+
};
|
|
43868
|
+
|
|
43869
|
+
// src/commands/mandate-configure.ts
|
|
43870
|
+
init_esm2();
|
|
43871
|
+
var TEMPLATE_REGISTRY = {
|
|
43872
|
+
SwapPermission: {
|
|
43873
|
+
label: "Bounded Swap (Uniswap V3)",
|
|
43874
|
+
bigintFields: ["maxAmountPerTx"],
|
|
43875
|
+
encode: (raw) => boundedSwapTemplate.encoder.encode(coerceSwapParams(raw)),
|
|
43876
|
+
decode: (blob) => {
|
|
43877
|
+
const p = boundedSwapTemplate.encoder.decode(blob);
|
|
43878
|
+
return {
|
|
43879
|
+
routers: p.routers,
|
|
43880
|
+
tokensIn: p.tokensIn,
|
|
43881
|
+
tokensOut: p.tokensOut,
|
|
43882
|
+
maxAmountPerTx: p.maxAmountPerTx.toString(),
|
|
43883
|
+
maxSlippageBps: p.maxSlippageBps,
|
|
43884
|
+
priceOracle: p.priceOracle,
|
|
43885
|
+
maxPriceAgeSec: p.maxPriceAgeSec
|
|
43886
|
+
};
|
|
43887
|
+
}
|
|
43888
|
+
}
|
|
43889
|
+
};
|
|
43890
|
+
function asAddressArray(v, field) {
|
|
43891
|
+
if (!Array.isArray(v)) throw new Error(`${field}: expected an array of addresses`);
|
|
43892
|
+
return v.map((x, i) => {
|
|
43893
|
+
if (typeof x !== "string" || !isAddress(x, { strict: false })) {
|
|
43894
|
+
throw new Error(`${field}[${i}]: invalid address "${String(x)}"`);
|
|
43895
|
+
}
|
|
43896
|
+
return getAddress(x);
|
|
43897
|
+
});
|
|
43898
|
+
}
|
|
43899
|
+
function asAddress(v, field) {
|
|
43900
|
+
if (typeof v !== "string" || !isAddress(v, { strict: false })) {
|
|
43901
|
+
throw new Error(`${field}: invalid address "${String(v)}"`);
|
|
43902
|
+
}
|
|
43903
|
+
return getAddress(v);
|
|
43904
|
+
}
|
|
43905
|
+
function asUint(v, field) {
|
|
43906
|
+
if (v === void 0 || v === null) throw new Error(`${field}: missing`);
|
|
43907
|
+
try {
|
|
43908
|
+
return BigInt(typeof v === "string" || typeof v === "number" ? v : String(v));
|
|
43909
|
+
} catch {
|
|
43910
|
+
throw new Error(`${field}: expected an integer, got "${String(v)}"`);
|
|
43911
|
+
}
|
|
43912
|
+
}
|
|
43913
|
+
function asInt(v, field) {
|
|
43914
|
+
const n = asUint(v, field);
|
|
43915
|
+
return Number(n);
|
|
43916
|
+
}
|
|
43917
|
+
function coerceSwapParams(raw) {
|
|
43918
|
+
return {
|
|
43919
|
+
routers: asAddressArray(raw.routers, "routers"),
|
|
43920
|
+
tokensIn: asAddressArray(raw.tokensIn, "tokensIn"),
|
|
43921
|
+
tokensOut: asAddressArray(raw.tokensOut, "tokensOut"),
|
|
43922
|
+
maxAmountPerTx: asUint(raw.maxAmountPerTx, "maxAmountPerTx"),
|
|
43923
|
+
maxSlippageBps: asInt(raw.maxSlippageBps, "maxSlippageBps"),
|
|
43924
|
+
priceOracle: asAddress(raw.priceOracle, "priceOracle"),
|
|
43925
|
+
maxPriceAgeSec: asInt(raw.maxPriceAgeSec, "maxPriceAgeSec")
|
|
43926
|
+
};
|
|
43927
|
+
}
|
|
43928
|
+
function requireProject2() {
|
|
43929
|
+
if (!ProjectContext.exists()) {
|
|
43930
|
+
console.log('No Sailor project found. Run "sailor init" first.');
|
|
43931
|
+
process.exit(1);
|
|
43932
|
+
}
|
|
43933
|
+
return new ProjectContext();
|
|
43934
|
+
}
|
|
43935
|
+
function fail2(err, json = false) {
|
|
43936
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
43937
|
+
emit(json, () => console.error(`
|
|
43938
|
+
Mandate configure failed: ${msg}`), {
|
|
43939
|
+
status: "error",
|
|
43940
|
+
error: msg
|
|
43941
|
+
});
|
|
43942
|
+
process.exit(1);
|
|
43943
|
+
}
|
|
43944
|
+
function publicClientFor2(project) {
|
|
43945
|
+
return createPublicClient({
|
|
43946
|
+
chain: getChainById(project.chainId),
|
|
43947
|
+
transport: http(getRpcUrl(project.chainId))
|
|
43948
|
+
}).extend(publicActions);
|
|
43949
|
+
}
|
|
43950
|
+
function announceSigningUrl2(json) {
|
|
43951
|
+
const url = signingPageUrl(projectPort(process.cwd()));
|
|
43952
|
+
if (json) {
|
|
43953
|
+
process.stdout.write(`${JSON.stringify({ status: "waiting_for_signature", url })}
|
|
43954
|
+
`);
|
|
43955
|
+
} else {
|
|
43956
|
+
console.log(`
|
|
43957
|
+
\u2192 Open the Sailor dashboard to approve signing requests:
|
|
43958
|
+
${url}
|
|
43959
|
+
`);
|
|
43960
|
+
}
|
|
43961
|
+
}
|
|
43962
|
+
function resolveBlob(options) {
|
|
43963
|
+
const hasParams = options.params !== void 0;
|
|
43964
|
+
const hasArgsFile = options.argsFile !== void 0;
|
|
43965
|
+
if (hasParams && hasArgsFile) {
|
|
43966
|
+
throw new Error("Provide EITHER --params <hex> OR --args-file <path>, not both.");
|
|
43967
|
+
}
|
|
43968
|
+
if (!hasParams && !hasArgsFile) {
|
|
43969
|
+
throw new Error(
|
|
43970
|
+
"Provide the config blob as --params <0x-hex>, or as --args-file <path> paired with --template <Name>."
|
|
43971
|
+
);
|
|
43972
|
+
}
|
|
43973
|
+
if (hasParams) {
|
|
43974
|
+
const raw2 = options.params.trim();
|
|
43975
|
+
if (!isHex(raw2) || raw2.length <= 2) {
|
|
43976
|
+
throw new Error(`--params must be 0x-prefixed hex; got "${options.params}".`);
|
|
43977
|
+
}
|
|
43978
|
+
return { blob: raw2, via: "params" };
|
|
43979
|
+
}
|
|
43980
|
+
const templateName = options.template;
|
|
43981
|
+
if (!templateName) {
|
|
43982
|
+
throw new Error("--args-file requires --template <Name> (e.g. SwapPermission).");
|
|
43983
|
+
}
|
|
43984
|
+
const entry = TEMPLATE_REGISTRY[templateName];
|
|
43985
|
+
if (!entry) {
|
|
43986
|
+
throw new Error(
|
|
43987
|
+
`Unknown --template "${templateName}". Known: ${Object.keys(TEMPLATE_REGISTRY).join(", ")}. Pass a pre-encoded blob with --params for any other template.`
|
|
43988
|
+
);
|
|
43989
|
+
}
|
|
43990
|
+
const argsFilePath = (0, import_node_path13.resolve)(options.argsFile);
|
|
43991
|
+
let raw;
|
|
43992
|
+
try {
|
|
43993
|
+
raw = (0, import_node_fs15.readFileSync)(argsFilePath, "utf8").trim();
|
|
43994
|
+
} catch {
|
|
43995
|
+
throw new Error(`Cannot read --args-file: ${argsFilePath}`);
|
|
43996
|
+
}
|
|
43997
|
+
let parsed;
|
|
43998
|
+
try {
|
|
43999
|
+
parsed = JSON.parse(raw);
|
|
44000
|
+
} catch (err) {
|
|
44001
|
+
throw new Error(`--args-file is not valid JSON: ${err.message}`);
|
|
44002
|
+
}
|
|
44003
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
44004
|
+
throw new Error("--args-file must contain a JSON object of template params.");
|
|
44005
|
+
}
|
|
44006
|
+
const blob = entry.encode(parsed);
|
|
44007
|
+
return { blob, via: `template:${templateName}` };
|
|
44008
|
+
}
|
|
44009
|
+
async function mandateConfigure(options) {
|
|
44010
|
+
const project = requireProject2();
|
|
44011
|
+
const channel = await createSigningChannel(process.cwd());
|
|
44012
|
+
try {
|
|
44013
|
+
await channel.start();
|
|
44014
|
+
await runConfigure(project, channel, options);
|
|
44015
|
+
} catch (err) {
|
|
44016
|
+
fail2(err, options.json);
|
|
44017
|
+
} finally {
|
|
44018
|
+
channel.stop();
|
|
44019
|
+
}
|
|
44020
|
+
}
|
|
44021
|
+
async function runConfigure(project, channel, options) {
|
|
44022
|
+
const json = !!options.json;
|
|
44023
|
+
const say = (fn) => {
|
|
44024
|
+
if (!json) fn();
|
|
44025
|
+
};
|
|
44026
|
+
if (!isAddress(options.sma, { strict: false })) {
|
|
44027
|
+
throw new Error(`Invalid --sma address: ${options.sma}`);
|
|
44028
|
+
}
|
|
44029
|
+
if (!isAddress(options.address, { strict: false })) {
|
|
44030
|
+
throw new Error(
|
|
44031
|
+
`--address must be a deployed shared-template singleton address: ${options.address}`
|
|
44032
|
+
);
|
|
44033
|
+
}
|
|
44034
|
+
const sma = getAddress(options.sma);
|
|
44035
|
+
const singleton = getAddress(options.address);
|
|
44036
|
+
const { blob, via } = resolveBlob(options);
|
|
44037
|
+
const publicClient = publicClientFor2(project);
|
|
44038
|
+
const registered = await publicClient.readContract({
|
|
44039
|
+
address: project.contracts.kernel,
|
|
44040
|
+
abi: SailKernelAbi,
|
|
44041
|
+
functionName: "registered",
|
|
44042
|
+
args: [sma]
|
|
44043
|
+
});
|
|
44044
|
+
if (!registered) {
|
|
44045
|
+
throw new Error(`SMA ${sma} is not registered with SailKernel; cannot configure a permission for it.`);
|
|
44046
|
+
}
|
|
44047
|
+
const kernelConfig = await publicClient.readContract({
|
|
44048
|
+
address: project.contracts.kernel,
|
|
44049
|
+
abi: SailKernelAbi,
|
|
44050
|
+
functionName: "configs",
|
|
44051
|
+
args: [sma]
|
|
44052
|
+
});
|
|
44053
|
+
const permissionSigner = kernelConfig[0];
|
|
44054
|
+
if (!permissionSigner || permissionSigner === getAddress("0x0000000000000000000000000000000000000000")) {
|
|
44055
|
+
throw new Error(`SMA ${sma} has no on-chain permissionSigner; cannot configure.`);
|
|
44056
|
+
}
|
|
44057
|
+
const alreadyConfigured = await publicClient.readContract({
|
|
44058
|
+
address: singleton,
|
|
44059
|
+
abi: ConfigurablePermissionAbi,
|
|
44060
|
+
functionName: "isConfigured",
|
|
44061
|
+
args: [sma]
|
|
44062
|
+
});
|
|
44063
|
+
if (alreadyConfigured && !options.force) {
|
|
44064
|
+
say(
|
|
44065
|
+
() => console.log(
|
|
44066
|
+
`
|
|
44067
|
+
\u2713 ${singleton} is already configured for ${sma} (isConfigured == true).
|
|
44068
|
+
Re-run with --force to overwrite the current bounds.`
|
|
44069
|
+
)
|
|
44070
|
+
);
|
|
44071
|
+
emit(
|
|
44072
|
+
json,
|
|
44073
|
+
() => {
|
|
44074
|
+
},
|
|
44075
|
+
{ status: "ok", alreadyConfigured: true, singleton, sma, chainId: project.chainId }
|
|
44076
|
+
);
|
|
44077
|
+
return;
|
|
44078
|
+
}
|
|
44079
|
+
const nonce = await publicClient.readContract({
|
|
44080
|
+
address: singleton,
|
|
44081
|
+
abi: ConfigurablePermissionAbi,
|
|
44082
|
+
functionName: "configNonces",
|
|
44083
|
+
args: [sma]
|
|
44084
|
+
});
|
|
44085
|
+
say(() => {
|
|
44086
|
+
console.log(`
|
|
44087
|
+
configure ${singleton}`);
|
|
44088
|
+
console.log(` SMA: ${sma}`);
|
|
44089
|
+
console.log(` permissionSigner: ${permissionSigner} (must sign in the browser \u2014 owner tx)`);
|
|
44090
|
+
console.log(` current nonce: ${nonce}`);
|
|
44091
|
+
console.log(` already set: ${alreadyConfigured ? "yes (--force will overwrite)" : "no"}`);
|
|
44092
|
+
console.log(` config blob: ${blob} (via ${via}, ${Math.floor((blob.length - 2) / 2)} bytes)`);
|
|
44093
|
+
});
|
|
44094
|
+
const configureDirectData = encodeFunctionData({
|
|
44095
|
+
abi: ConfigurablePermissionAbi,
|
|
44096
|
+
functionName: "configureDirect",
|
|
44097
|
+
args: [sma, blob]
|
|
44098
|
+
});
|
|
44099
|
+
say(() => console.log(`
|
|
44100
|
+
Pre-flight (eth_call of configureDirect, no gas)\u2026`));
|
|
44101
|
+
try {
|
|
44102
|
+
await publicClient.simulateContract({
|
|
44103
|
+
address: singleton,
|
|
44104
|
+
abi: ConfigurablePermissionAbi,
|
|
44105
|
+
functionName: "configureDirect",
|
|
44106
|
+
args: [sma, blob],
|
|
44107
|
+
account: permissionSigner
|
|
44108
|
+
});
|
|
44109
|
+
} catch (err) {
|
|
44110
|
+
const ce = getContractError(err, {
|
|
44111
|
+
abi: ConfigurablePermissionAbi,
|
|
44112
|
+
address: singleton,
|
|
44113
|
+
args: [sma, blob],
|
|
44114
|
+
functionName: "configureDirect"
|
|
44115
|
+
});
|
|
44116
|
+
const reason = ce?.message ?? err?.message ?? String(err);
|
|
44117
|
+
throw new Error(
|
|
44118
|
+
`Pre-flight reverted \u2014 the config blob is invalid for ${singleton} on ${sma}.
|
|
44119
|
+
Revert: ${reason}
|
|
44120
|
+
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.`
|
|
44121
|
+
);
|
|
44122
|
+
}
|
|
44123
|
+
say(() => console.log("\u2713 pre-flight passed (configureDirect would succeed)."));
|
|
44124
|
+
let decoded;
|
|
44125
|
+
if (options.template && TEMPLATE_REGISTRY[options.template]) {
|
|
44126
|
+
try {
|
|
44127
|
+
decoded = TEMPLATE_REGISTRY[options.template].decode(blob);
|
|
44128
|
+
say(() => {
|
|
44129
|
+
console.log("\nDecoded bounds (what the singleton will store):");
|
|
44130
|
+
for (const [k, v] of Object.entries(decoded)) {
|
|
44131
|
+
const display = Array.isArray(v) ? v.join(", ") : String(v);
|
|
44132
|
+
console.log(` ${k}: ${display}`);
|
|
44133
|
+
}
|
|
44134
|
+
});
|
|
44135
|
+
} catch {
|
|
44136
|
+
}
|
|
44137
|
+
}
|
|
44138
|
+
if (options.simulateOnly) {
|
|
44139
|
+
emit(
|
|
44140
|
+
json,
|
|
44141
|
+
() => {
|
|
44142
|
+
console.log("\n--simulate-only: stopping after pre-flight (no signing, no gas).");
|
|
44143
|
+
},
|
|
44144
|
+
{
|
|
44145
|
+
status: "ok",
|
|
44146
|
+
simulateOnly: true,
|
|
44147
|
+
singleton,
|
|
44148
|
+
sma,
|
|
44149
|
+
permissionSigner,
|
|
44150
|
+
nonce: nonce.toString(),
|
|
44151
|
+
alreadyConfigured,
|
|
44152
|
+
blob,
|
|
44153
|
+
blobBytes: Math.floor((blob.length - 2) / 2),
|
|
44154
|
+
decoded,
|
|
44155
|
+
chainId: project.chainId
|
|
44156
|
+
}
|
|
44157
|
+
);
|
|
44158
|
+
return;
|
|
44159
|
+
}
|
|
44160
|
+
const label = options.label ?? (options.template ?? "shared-template");
|
|
44161
|
+
announceSigningUrl2(json);
|
|
44162
|
+
say(
|
|
44163
|
+
() => console.log(
|
|
44164
|
+
`Pushing configure request \u2014 the mandate signer (${permissionSigner}) must approve in the browser\u2026`
|
|
44165
|
+
)
|
|
44166
|
+
);
|
|
44167
|
+
const response = await channel.requestSignature({
|
|
44168
|
+
type: "transaction",
|
|
44169
|
+
kind: "arbitrary-tx",
|
|
44170
|
+
title: `Configure "${label}"`,
|
|
44171
|
+
description: `Write per-account bounds on the shared permission ${singleton}.
|
|
44172
|
+
You (the mandate signer) send the transaction \u2014 configureDirect requires msg.sender to be the permissionSigner.`,
|
|
44173
|
+
chainId: project.chainId,
|
|
44174
|
+
to: singleton,
|
|
44175
|
+
data: configureDirectData,
|
|
44176
|
+
details: [
|
|
44177
|
+
{ label: "SMA", value: sma },
|
|
44178
|
+
{ label: "Singleton", value: singleton },
|
|
44179
|
+
{ label: "Template", value: options.template ?? "(raw blob)" },
|
|
44180
|
+
{ label: "Mandate signer", value: permissionSigner },
|
|
44181
|
+
{ label: "Config blob (bytes)", value: String(Math.floor((blob.length - 2) / 2)) },
|
|
44182
|
+
...decoded ? Object.entries(decoded).map(([k, v]) => ({
|
|
44183
|
+
label: k,
|
|
44184
|
+
value: Array.isArray(v) ? v.join(", ") : String(v)
|
|
44185
|
+
})) : []
|
|
44186
|
+
]
|
|
44187
|
+
});
|
|
44188
|
+
if (response.status === "rejected") {
|
|
44189
|
+
throw new Error(`User rejected configure: ${response.reason ?? "no reason given"}`);
|
|
44190
|
+
}
|
|
44191
|
+
if (response.status !== "signed") {
|
|
44192
|
+
throw new Error(`Expected a signed transaction, got: ${response.status}`);
|
|
44193
|
+
}
|
|
44194
|
+
say(() => console.log("Waiting for confirmation\u2026"));
|
|
44195
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: response.txHash });
|
|
44196
|
+
if (receipt.status !== "success") {
|
|
44197
|
+
throw new Error(`configureDirect transaction failed (tx ${response.txHash})`);
|
|
44198
|
+
}
|
|
44199
|
+
const configuredNow = await publicClient.readContract({
|
|
44200
|
+
address: singleton,
|
|
44201
|
+
abi: ConfigurablePermissionAbi,
|
|
44202
|
+
functionName: "isConfigured",
|
|
44203
|
+
args: [sma]
|
|
44204
|
+
});
|
|
44205
|
+
if (!configuredNow) {
|
|
44206
|
+
throw new Error(
|
|
44207
|
+
`Tx ${response.txHash} mined, but isConfigured(${sma}) is still false. Verify on-chain.`
|
|
44208
|
+
);
|
|
44209
|
+
}
|
|
44210
|
+
say(() => console.log("\u2713", `Configured ${singleton} for ${sma} (isConfigured == true).`));
|
|
44211
|
+
appendActivity({
|
|
44212
|
+
ts: nowIso(),
|
|
44213
|
+
actor: "owner",
|
|
44214
|
+
type: "permission_configured",
|
|
44215
|
+
permission: singleton,
|
|
44216
|
+
name: label,
|
|
44217
|
+
sma,
|
|
44218
|
+
txHash: response.txHash,
|
|
44219
|
+
chainId: project.chainId
|
|
44220
|
+
});
|
|
44221
|
+
emit(
|
|
44222
|
+
json,
|
|
44223
|
+
() => {
|
|
44224
|
+
console.log(
|
|
44225
|
+
`
|
|
44226
|
+
Next: prove it accepts/rejects the right calls before dispatching:
|
|
44227
|
+
sailor mandate simulate --address ${singleton} --sma ${sma} --calls ./probe.json`
|
|
44228
|
+
);
|
|
44229
|
+
},
|
|
44230
|
+
{
|
|
44231
|
+
status: "ok",
|
|
44232
|
+
singleton,
|
|
44233
|
+
sma,
|
|
44234
|
+
template: options.template,
|
|
44235
|
+
permissionSigner,
|
|
44236
|
+
txHash: response.txHash,
|
|
44237
|
+
blob,
|
|
44238
|
+
chainId: project.chainId
|
|
44239
|
+
}
|
|
44240
|
+
);
|
|
44241
|
+
}
|
|
44242
|
+
|
|
44243
|
+
// src/commands/mandate-simulate.ts
|
|
44244
|
+
var import_node_fs16 = require("node:fs");
|
|
43687
44245
|
init_esm2();
|
|
43688
44246
|
function parseExpect(raw, where) {
|
|
43689
44247
|
if (raw === void 0) return void 0;
|
|
@@ -43699,7 +44257,7 @@ function resolveSampleCalls(options) {
|
|
|
43699
44257
|
if (options.calls) {
|
|
43700
44258
|
let raw;
|
|
43701
44259
|
try {
|
|
43702
|
-
raw = JSON.parse((0,
|
|
44260
|
+
raw = JSON.parse((0, import_node_fs16.readFileSync)(options.calls, "utf8"));
|
|
43703
44261
|
} catch (err) {
|
|
43704
44262
|
throw new Error(`Could not read --calls file "${options.calls}": ${err.message}`);
|
|
43705
44263
|
}
|
|
@@ -43915,7 +44473,7 @@ async function mandateSimulate(options) {
|
|
|
43915
44473
|
}
|
|
43916
44474
|
|
|
43917
44475
|
// src/commands/rotate-signer.ts
|
|
43918
|
-
var
|
|
44476
|
+
var import_node_fs17 = require("node:fs");
|
|
43919
44477
|
init_esm2();
|
|
43920
44478
|
var PENDING_REATTACH_FILE = ["state", "pending-reattach.json"];
|
|
43921
44479
|
async function rotateSigner(options) {
|
|
@@ -44301,7 +44859,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
44301
44859
|
const keystore = await keyring.exportKeystore(password);
|
|
44302
44860
|
writeJsonFile(target, keystore, 384);
|
|
44303
44861
|
const perManagerPath = managerKeystorePath(keyring.address);
|
|
44304
|
-
(0,
|
|
44862
|
+
(0, import_node_fs17.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
44305
44863
|
writeJsonFile(perManagerPath, keystore, 384);
|
|
44306
44864
|
say(
|
|
44307
44865
|
() => console.log(
|
|
@@ -44313,7 +44871,7 @@ ensure the agent that signs dispatches holds this key.`
|
|
|
44313
44871
|
function promoteManagerKeystore(newManager, say) {
|
|
44314
44872
|
const stored = readJsonFile(managerKeystorePath(newManager));
|
|
44315
44873
|
if (!stored) return;
|
|
44316
|
-
(0,
|
|
44874
|
+
(0, import_node_fs17.mkdirSync)(sailPath("keys", "managers"), { recursive: true });
|
|
44317
44875
|
const activeTarget = keyPath("manager");
|
|
44318
44876
|
const displaced = readJsonFile(activeTarget);
|
|
44319
44877
|
if (displaced?.address) {
|
|
@@ -44365,7 +44923,7 @@ function writePending(pending) {
|
|
|
44365
44923
|
}
|
|
44366
44924
|
function clearPending() {
|
|
44367
44925
|
try {
|
|
44368
|
-
(0,
|
|
44926
|
+
(0, import_node_fs17.rmSync)(sailPath(...PENDING_REATTACH_FILE), { force: true });
|
|
44369
44927
|
} catch {
|
|
44370
44928
|
}
|
|
44371
44929
|
}
|
|
@@ -44464,12 +45022,12 @@ function ownerShow(options) {
|
|
|
44464
45022
|
}
|
|
44465
45023
|
|
|
44466
45024
|
// src/commands/run.ts
|
|
44467
|
-
var
|
|
44468
|
-
var
|
|
45025
|
+
var import_node_fs18 = __toESM(require("node:fs"), 1);
|
|
45026
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
44469
45027
|
var import_node_url = require("node:url");
|
|
44470
45028
|
init_esm2();
|
|
44471
45029
|
var DEFAULT_INTERVAL_SEC = 60;
|
|
44472
|
-
var sleep2 = (ms) => new Promise((
|
|
45030
|
+
var sleep2 = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
44473
45031
|
var ERC20_READ_ABI = [
|
|
44474
45032
|
{
|
|
44475
45033
|
type: "function",
|
|
@@ -44499,7 +45057,7 @@ var ERC20_READ_ABI = [
|
|
|
44499
45057
|
function loadAgentData(filePath) {
|
|
44500
45058
|
if (!filePath) return {};
|
|
44501
45059
|
try {
|
|
44502
|
-
const parsed = JSON.parse(
|
|
45060
|
+
const parsed = JSON.parse(import_node_fs18.default.readFileSync(filePath, "utf-8"));
|
|
44503
45061
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
44504
45062
|
} catch {
|
|
44505
45063
|
return {};
|
|
@@ -44508,8 +45066,8 @@ function loadAgentData(filePath) {
|
|
|
44508
45066
|
async function loadAgent() {
|
|
44509
45067
|
const candidates = ["src/agent.ts", "src/agent.js", "dist/agent.js", "dist/src/agent.js"];
|
|
44510
45068
|
for (const rel of candidates) {
|
|
44511
|
-
const abs =
|
|
44512
|
-
if (!
|
|
45069
|
+
const abs = import_node_path14.default.join(process.cwd(), rel);
|
|
45070
|
+
if (!import_node_fs18.default.existsSync(abs)) continue;
|
|
44513
45071
|
let mod2;
|
|
44514
45072
|
if (abs.endsWith(".ts")) {
|
|
44515
45073
|
const { tsImport } = await import("tsx/esm/api");
|
|
@@ -44804,7 +45362,7 @@ Configure the chain in the SDK chain registry or set KERNEL_ADDRESS in .sail/.en
|
|
|
44804
45362
|
if (isConjunctive && result.txHash) {
|
|
44805
45363
|
try {
|
|
44806
45364
|
await publicClient.waitForTransactionReceipt({ hash: result.txHash, timeout: 3e4 });
|
|
44807
|
-
await new Promise((
|
|
45365
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
44808
45366
|
} catch {
|
|
44809
45367
|
}
|
|
44810
45368
|
}
|
|
@@ -44985,9 +45543,9 @@ async function scan(options) {
|
|
|
44985
45543
|
|
|
44986
45544
|
// src/commands/service.ts
|
|
44987
45545
|
var import_node_child_process2 = require("node:child_process");
|
|
44988
|
-
var
|
|
45546
|
+
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
44989
45547
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
44990
|
-
var
|
|
45548
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
44991
45549
|
function sanitizeName(raw) {
|
|
44992
45550
|
const s = raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
44993
45551
|
return s || "agent";
|
|
@@ -45106,21 +45664,21 @@ function buildWindowsTaskXml(cfg) {
|
|
|
45106
45664
|
`;
|
|
45107
45665
|
}
|
|
45108
45666
|
function isTccProtected(projectDir, home = import_node_os.default.homedir()) {
|
|
45109
|
-
const rel =
|
|
45110
|
-
if (rel.startsWith("..") ||
|
|
45111
|
-
const top = rel.split(
|
|
45667
|
+
const rel = import_node_path15.default.relative(home, import_node_path15.default.resolve(projectDir));
|
|
45668
|
+
if (rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
|
|
45669
|
+
const top = rel.split(import_node_path15.default.sep)[0];
|
|
45112
45670
|
return ["Desktop", "Documents", "Downloads"].includes(top ?? "");
|
|
45113
45671
|
}
|
|
45114
45672
|
function resolveCliEntry() {
|
|
45115
45673
|
try {
|
|
45116
|
-
return
|
|
45674
|
+
return import_node_fs19.default.realpathSync(process.argv[1]);
|
|
45117
45675
|
} catch {
|
|
45118
|
-
return
|
|
45676
|
+
return import_node_path15.default.resolve(process.argv[1]);
|
|
45119
45677
|
}
|
|
45120
45678
|
}
|
|
45121
45679
|
function resolveProjectDir(explicit) {
|
|
45122
|
-
const dir =
|
|
45123
|
-
if (!
|
|
45680
|
+
const dir = import_node_path15.default.resolve(explicit ?? process.cwd());
|
|
45681
|
+
if (!import_node_fs19.default.existsSync(import_node_path15.default.join(dir, ".sail"))) {
|
|
45124
45682
|
throw new Error(
|
|
45125
45683
|
`No .sail/ found in ${dir}.
|
|
45126
45684
|
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 +45690,7 @@ function passphraseReadiness(projectDir) {
|
|
|
45132
45690
|
const account2 = (() => {
|
|
45133
45691
|
try {
|
|
45134
45692
|
return JSON.parse(
|
|
45135
|
-
|
|
45693
|
+
import_node_fs19.default.readFileSync(import_node_path15.default.join(projectDir, ".sail", "account.json"), "utf-8")
|
|
45136
45694
|
);
|
|
45137
45695
|
} catch {
|
|
45138
45696
|
return null;
|
|
@@ -45148,28 +45706,28 @@ function passphraseReadiness(projectDir) {
|
|
|
45148
45706
|
} finally {
|
|
45149
45707
|
process.chdir(prevCwd);
|
|
45150
45708
|
}
|
|
45151
|
-
const env = parseEnvFile(
|
|
45709
|
+
const env = parseEnvFile(import_node_path15.default.join(projectDir, ".sail", ".env.local"));
|
|
45152
45710
|
const passphraseInEnvFile = Boolean(env.SAIL_PASSPHRASE);
|
|
45153
45711
|
return { keystorePresent, passphraseInEnvFile, ready: keystorePresent && passphraseInEnvFile };
|
|
45154
45712
|
}
|
|
45155
45713
|
function buildConfig(opts) {
|
|
45156
45714
|
const projectDir = resolveProjectDir(opts.project);
|
|
45157
45715
|
return {
|
|
45158
|
-
projectName: sanitizeName(
|
|
45716
|
+
projectName: sanitizeName(import_node_path15.default.basename(projectDir)),
|
|
45159
45717
|
projectDir,
|
|
45160
45718
|
nodePath: process.execPath,
|
|
45161
45719
|
cliEntry: resolveCliEntry(),
|
|
45162
|
-
logPath:
|
|
45720
|
+
logPath: import_node_path15.default.join(projectDir, ".sail", "agent.log"),
|
|
45163
45721
|
interval: opts.interval != null ? Number(opts.interval) : void 0,
|
|
45164
45722
|
chain: opts.chain != null ? Number(opts.chain) : void 0,
|
|
45165
45723
|
restartSec: 30
|
|
45166
45724
|
};
|
|
45167
45725
|
}
|
|
45168
45726
|
function plistPath(projectName) {
|
|
45169
|
-
return
|
|
45727
|
+
return import_node_path15.default.join(import_node_os.default.homedir(), "Library", "LaunchAgents", `${launchdLabel(projectName)}.plist`);
|
|
45170
45728
|
}
|
|
45171
45729
|
function systemdPath(projectName) {
|
|
45172
|
-
return
|
|
45730
|
+
return import_node_path15.default.join(import_node_os.default.homedir(), ".config", "systemd", "user", systemdUnitName(projectName));
|
|
45173
45731
|
}
|
|
45174
45732
|
async function serviceInstall(opts = {}) {
|
|
45175
45733
|
const cfg = buildConfig(opts);
|
|
@@ -45193,12 +45751,12 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45193
45751
|
console.warn(`\u26A0 ${msg}
|
|
45194
45752
|
Proceeding because --force was given.`);
|
|
45195
45753
|
}
|
|
45196
|
-
|
|
45754
|
+
import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(cfg.logPath), { recursive: true });
|
|
45197
45755
|
if (platform === "darwin") {
|
|
45198
45756
|
const plist = buildLaunchdPlist(cfg);
|
|
45199
45757
|
const dest = plistPath(cfg.projectName);
|
|
45200
|
-
|
|
45201
|
-
|
|
45758
|
+
import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(dest), { recursive: true });
|
|
45759
|
+
import_node_fs19.default.writeFileSync(dest, plist);
|
|
45202
45760
|
const uid2 = process.getuid?.() ?? 0;
|
|
45203
45761
|
try {
|
|
45204
45762
|
try {
|
|
@@ -45217,8 +45775,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45217
45775
|
if (platform === "linux") {
|
|
45218
45776
|
const unit = buildSystemdUnit(cfg);
|
|
45219
45777
|
const dest = systemdPath(cfg.projectName);
|
|
45220
|
-
|
|
45221
|
-
|
|
45778
|
+
import_node_fs19.default.mkdirSync(import_node_path15.default.dirname(dest), { recursive: true });
|
|
45779
|
+
import_node_fs19.default.writeFileSync(dest, unit);
|
|
45222
45780
|
try {
|
|
45223
45781
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
45224
45782
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "enable", "--now", systemdUnitName(cfg.projectName)], {
|
|
@@ -45232,8 +45790,8 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45232
45790
|
}
|
|
45233
45791
|
if (platform === "win32") {
|
|
45234
45792
|
const xml = buildWindowsTaskXml(cfg);
|
|
45235
|
-
const dest =
|
|
45236
|
-
|
|
45793
|
+
const dest = import_node_path15.default.join(import_node_os.default.tmpdir(), `${windowsTaskName(cfg.projectName)}.xml`);
|
|
45794
|
+
import_node_fs19.default.writeFileSync(dest, xml, "utf-8");
|
|
45237
45795
|
try {
|
|
45238
45796
|
(0, import_node_child_process2.execFileSync)(
|
|
45239
45797
|
"schtasks",
|
|
@@ -45244,7 +45802,7 @@ Run "sailor keys generate" (and save the passphrase) or set it in .sail/.env.loc
|
|
|
45244
45802
|
throw new Error(`schtasks /Create failed: ${err.message}`);
|
|
45245
45803
|
} finally {
|
|
45246
45804
|
try {
|
|
45247
|
-
|
|
45805
|
+
import_node_fs19.default.rmSync(dest, { force: true });
|
|
45248
45806
|
} catch {
|
|
45249
45807
|
}
|
|
45250
45808
|
}
|
|
@@ -45270,14 +45828,14 @@ function okInstall(cfg, unit) {
|
|
|
45270
45828
|
);
|
|
45271
45829
|
}
|
|
45272
45830
|
async function serviceStatus(opts = {}) {
|
|
45273
|
-
const projectName = sanitizeName(
|
|
45831
|
+
const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
|
|
45274
45832
|
const platform = process.platform;
|
|
45275
45833
|
let installed = false;
|
|
45276
45834
|
let running = false;
|
|
45277
45835
|
let detail = "";
|
|
45278
45836
|
try {
|
|
45279
45837
|
if (platform === "darwin") {
|
|
45280
|
-
installed =
|
|
45838
|
+
installed = import_node_fs19.default.existsSync(plistPath(projectName));
|
|
45281
45839
|
const uid2 = process.getuid?.() ?? 0;
|
|
45282
45840
|
try {
|
|
45283
45841
|
detail = (0, import_node_child_process2.execFileSync)("launchctl", ["print", `gui/${uid2}/${launchdLabel(projectName)}`], {
|
|
@@ -45289,7 +45847,7 @@ async function serviceStatus(opts = {}) {
|
|
|
45289
45847
|
} catch {
|
|
45290
45848
|
}
|
|
45291
45849
|
} else if (platform === "linux") {
|
|
45292
|
-
installed =
|
|
45850
|
+
installed = import_node_fs19.default.existsSync(systemdPath(projectName));
|
|
45293
45851
|
try {
|
|
45294
45852
|
detail = (0, import_node_child_process2.execFileSync)("systemctl", ["--user", "is-active", systemdUnitName(projectName)], {
|
|
45295
45853
|
encoding: "utf-8",
|
|
@@ -45325,7 +45883,7 @@ async function serviceStatus(opts = {}) {
|
|
|
45325
45883
|
);
|
|
45326
45884
|
}
|
|
45327
45885
|
async function serviceStop(opts = {}) {
|
|
45328
|
-
const projectName = sanitizeName(
|
|
45886
|
+
const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
|
|
45329
45887
|
const platform = process.platform;
|
|
45330
45888
|
if (platform === "darwin") {
|
|
45331
45889
|
const uid2 = process.getuid?.() ?? 0;
|
|
@@ -45344,7 +45902,7 @@ async function serviceStop(opts = {}) {
|
|
|
45344
45902
|
});
|
|
45345
45903
|
}
|
|
45346
45904
|
async function serviceUninstall(opts = {}) {
|
|
45347
|
-
const projectName = sanitizeName(
|
|
45905
|
+
const projectName = sanitizeName(import_node_path15.default.basename(resolveProjectDir(opts.project)));
|
|
45348
45906
|
const platform = process.platform;
|
|
45349
45907
|
if (platform === "darwin") {
|
|
45350
45908
|
const uid2 = process.getuid?.() ?? 0;
|
|
@@ -45354,7 +45912,7 @@ async function serviceUninstall(opts = {}) {
|
|
|
45354
45912
|
});
|
|
45355
45913
|
} catch {
|
|
45356
45914
|
}
|
|
45357
|
-
|
|
45915
|
+
import_node_fs19.default.rmSync(plistPath(projectName), { force: true });
|
|
45358
45916
|
} else if (platform === "linux") {
|
|
45359
45917
|
try {
|
|
45360
45918
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "disable", "--now", systemdUnitName(projectName)], {
|
|
@@ -45362,7 +45920,7 @@ async function serviceUninstall(opts = {}) {
|
|
|
45362
45920
|
});
|
|
45363
45921
|
} catch {
|
|
45364
45922
|
}
|
|
45365
|
-
|
|
45923
|
+
import_node_fs19.default.rmSync(systemdPath(projectName), { force: true });
|
|
45366
45924
|
try {
|
|
45367
45925
|
(0, import_node_child_process2.execFileSync)("systemctl", ["--user", "daemon-reload"], { stdio: "ignore" });
|
|
45368
45926
|
} catch {
|
|
@@ -45380,21 +45938,21 @@ async function serviceUninstall(opts = {}) {
|
|
|
45380
45938
|
}
|
|
45381
45939
|
async function serviceLogs(opts = {}) {
|
|
45382
45940
|
const projectDir = resolveProjectDir(opts.project);
|
|
45383
|
-
const logPath =
|
|
45384
|
-
if (!
|
|
45941
|
+
const logPath = import_node_path15.default.join(projectDir, ".sail", "agent.log");
|
|
45942
|
+
if (!import_node_fs19.default.existsSync(logPath)) {
|
|
45385
45943
|
console.log(`No log yet at ${logPath}. The service writes here once it runs.`);
|
|
45386
45944
|
return;
|
|
45387
45945
|
}
|
|
45388
45946
|
if (opts.follow) {
|
|
45389
45947
|
if (process.platform === "win32") {
|
|
45390
|
-
console.log(
|
|
45948
|
+
console.log(import_node_fs19.default.readFileSync(logPath, "utf-8"));
|
|
45391
45949
|
console.log("(follow mode is not supported on Windows here \u2014 re-run to refresh)");
|
|
45392
45950
|
return;
|
|
45393
45951
|
}
|
|
45394
45952
|
(0, import_node_child_process2.execFileSync)("tail", ["-f", logPath], { stdio: "inherit" });
|
|
45395
45953
|
return;
|
|
45396
45954
|
}
|
|
45397
|
-
const lines =
|
|
45955
|
+
const lines = import_node_fs19.default.readFileSync(logPath, "utf-8").split("\n");
|
|
45398
45956
|
console.log(lines.slice(-200).join("\n"));
|
|
45399
45957
|
}
|
|
45400
45958
|
|
|
@@ -45550,14 +46108,14 @@ async function sessionResume(opts = {}) {
|
|
|
45550
46108
|
}
|
|
45551
46109
|
|
|
45552
46110
|
// src/commands/station.ts
|
|
45553
|
-
var
|
|
45554
|
-
var
|
|
45555
|
-
var RUNTIME_SERVER_FILE2 = (0,
|
|
46111
|
+
var import_node_fs20 = require("node:fs");
|
|
46112
|
+
var import_node_path16 = require("node:path");
|
|
46113
|
+
var RUNTIME_SERVER_FILE2 = (0, import_node_path16.join)(".sail", "runtime", "server.json");
|
|
45556
46114
|
function readState(projectRoot) {
|
|
45557
|
-
const file = (0,
|
|
45558
|
-
if (!(0,
|
|
46115
|
+
const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
46116
|
+
if (!(0, import_node_fs20.existsSync)(file)) return null;
|
|
45559
46117
|
try {
|
|
45560
|
-
return JSON.parse((0,
|
|
46118
|
+
return JSON.parse((0, import_node_fs20.readFileSync)(file, "utf8"));
|
|
45561
46119
|
} catch {
|
|
45562
46120
|
return null;
|
|
45563
46121
|
}
|
|
@@ -45629,9 +46187,9 @@ async function stationStop(options) {
|
|
|
45629
46187
|
}
|
|
45630
46188
|
const daemon = await discoverDaemon(projectRoot);
|
|
45631
46189
|
if (!daemon) {
|
|
45632
|
-
const file = (0,
|
|
46190
|
+
const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
45633
46191
|
try {
|
|
45634
|
-
if ((0,
|
|
46192
|
+
if ((0, import_node_fs20.existsSync)(file)) (0, import_node_fs20.rmSync)(file);
|
|
45635
46193
|
} catch {
|
|
45636
46194
|
}
|
|
45637
46195
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -45647,9 +46205,9 @@ async function stationStop(options) {
|
|
|
45647
46205
|
pid: state.pid
|
|
45648
46206
|
});
|
|
45649
46207
|
} catch {
|
|
45650
|
-
const file = (0,
|
|
46208
|
+
const file = (0, import_node_path16.join)(projectRoot, RUNTIME_SERVER_FILE2);
|
|
45651
46209
|
try {
|
|
45652
|
-
if ((0,
|
|
46210
|
+
if ((0, import_node_fs20.existsSync)(file)) (0, import_node_fs20.rmSync)(file);
|
|
45653
46211
|
} catch {
|
|
45654
46212
|
}
|
|
45655
46213
|
emit(options.json, () => console.log("Station process not found; cleared stale state."), {
|
|
@@ -45711,9 +46269,9 @@ async function status() {
|
|
|
45711
46269
|
|
|
45712
46270
|
// src/commands/ui.ts
|
|
45713
46271
|
var import_node_child_process5 = require("node:child_process");
|
|
45714
|
-
var
|
|
46272
|
+
var import_node_fs21 = __toESM(require("node:fs"), 1);
|
|
45715
46273
|
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
45716
|
-
var
|
|
46274
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
45717
46275
|
|
|
45718
46276
|
// src/lib/tailscale.ts
|
|
45719
46277
|
var import_node_child_process4 = require("node:child_process");
|
|
@@ -45759,12 +46317,12 @@ function tailscaleServeDown() {
|
|
|
45759
46317
|
}
|
|
45760
46318
|
|
|
45761
46319
|
// src/commands/ui.ts
|
|
45762
|
-
var UI_STATE_FILE =
|
|
46320
|
+
var UI_STATE_FILE = import_node_path17.default.join(".sail", "runtime", "ui.json");
|
|
45763
46321
|
function readState2(projectRoot) {
|
|
45764
|
-
const file =
|
|
45765
|
-
if (!
|
|
46322
|
+
const file = import_node_path17.default.join(projectRoot, UI_STATE_FILE);
|
|
46323
|
+
if (!import_node_fs21.default.existsSync(file)) return null;
|
|
45766
46324
|
try {
|
|
45767
|
-
return JSON.parse(
|
|
46325
|
+
return JSON.parse(import_node_fs21.default.readFileSync(file, "utf-8"));
|
|
45768
46326
|
} catch {
|
|
45769
46327
|
return null;
|
|
45770
46328
|
}
|
|
@@ -45772,7 +46330,7 @@ function readState2(projectRoot) {
|
|
|
45772
46330
|
function installedCliVersion() {
|
|
45773
46331
|
try {
|
|
45774
46332
|
const pkg = JSON.parse(
|
|
45775
|
-
|
|
46333
|
+
import_node_fs21.default.readFileSync(import_node_path17.default.join(packageRoot(), "package.json"), "utf-8")
|
|
45776
46334
|
);
|
|
45777
46335
|
return pkg.version ?? null;
|
|
45778
46336
|
} catch {
|
|
@@ -45799,16 +46357,16 @@ async function warnIfVersionSkew(port) {
|
|
|
45799
46357
|
}
|
|
45800
46358
|
function waitForPort(port, timeoutMs) {
|
|
45801
46359
|
const deadline = Date.now() + timeoutMs;
|
|
45802
|
-
return new Promise((
|
|
46360
|
+
return new Promise((resolve4) => {
|
|
45803
46361
|
const attempt = () => {
|
|
45804
46362
|
const socket = import_node_net2.default.connect(port, "127.0.0.1");
|
|
45805
46363
|
socket.once("connect", () => {
|
|
45806
46364
|
socket.destroy();
|
|
45807
|
-
|
|
46365
|
+
resolve4(true);
|
|
45808
46366
|
});
|
|
45809
46367
|
socket.once("error", () => {
|
|
45810
46368
|
socket.destroy();
|
|
45811
|
-
if (Date.now() > deadline)
|
|
46369
|
+
if (Date.now() > deadline) resolve4(false);
|
|
45812
46370
|
else setTimeout(attempt, 150);
|
|
45813
46371
|
});
|
|
45814
46372
|
};
|
|
@@ -45817,16 +46375,16 @@ function waitForPort(port, timeoutMs) {
|
|
|
45817
46375
|
}
|
|
45818
46376
|
async function uiCommand(opts = {}) {
|
|
45819
46377
|
const distDir = cliDistDir();
|
|
45820
|
-
const uiDistDir =
|
|
45821
|
-
const serverBundle =
|
|
46378
|
+
const uiDistDir = import_node_path17.default.join(packageRoot(), "packages", "ui", "dist");
|
|
46379
|
+
const serverBundle = import_node_path17.default.resolve(distDir, "server.cjs");
|
|
45822
46380
|
const projectRoot = process.cwd();
|
|
45823
|
-
const sailDir2 =
|
|
46381
|
+
const sailDir2 = import_node_path17.default.join(projectRoot, ".sail");
|
|
45824
46382
|
const envPort = Number(process.env.PORT);
|
|
45825
46383
|
const port = await findFreePort(Number.isInteger(envPort) && envPort > 0 && envPort <= 65535 ? envPort : projectPort(projectRoot));
|
|
45826
|
-
if (!
|
|
46384
|
+
if (!import_node_fs21.default.existsSync(serverBundle)) {
|
|
45827
46385
|
throw new Error(`Server bundle not found at ${serverBundle}. Re-run the sailor build.`);
|
|
45828
46386
|
}
|
|
45829
|
-
if (!
|
|
46387
|
+
if (!import_node_fs21.default.existsSync(import_node_path17.default.join(uiDistDir, "index.html"))) {
|
|
45830
46388
|
throw new Error(`UI dist not found at ${uiDistDir}. Re-run the sailor build.`);
|
|
45831
46389
|
}
|
|
45832
46390
|
let tailnetUrl = null;
|
|
@@ -45856,10 +46414,10 @@ async function uiCommand(opts = {}) {
|
|
|
45856
46414
|
await warnIfVersionSkew(existing.port);
|
|
45857
46415
|
return;
|
|
45858
46416
|
}
|
|
45859
|
-
const runtimeDir =
|
|
45860
|
-
|
|
45861
|
-
const logFile =
|
|
45862
|
-
const logFd =
|
|
46417
|
+
const runtimeDir = import_node_path17.default.join(projectRoot, ".sail", "runtime");
|
|
46418
|
+
import_node_fs21.default.mkdirSync(runtimeDir, { recursive: true });
|
|
46419
|
+
const logFile = import_node_path17.default.join(runtimeDir, "ui.log");
|
|
46420
|
+
const logFd = import_node_fs21.default.openSync(logFile, "a");
|
|
45863
46421
|
const corsOrigins = [process.env.SAILOR_CORS_ORIGINS, tailnetUrl].filter(Boolean).join(",");
|
|
45864
46422
|
const child = (0, import_node_child_process5.spawn)(process.execPath, [serverBundle], {
|
|
45865
46423
|
detached: true,
|
|
@@ -45874,7 +46432,7 @@ async function uiCommand(opts = {}) {
|
|
|
45874
46432
|
}
|
|
45875
46433
|
});
|
|
45876
46434
|
child.unref();
|
|
45877
|
-
|
|
46435
|
+
import_node_fs21.default.closeSync(logFd);
|
|
45878
46436
|
const READY_TIMEOUT_MS = 1e4;
|
|
45879
46437
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
45880
46438
|
let ready = false;
|
|
@@ -45888,14 +46446,14 @@ async function uiCommand(opts = {}) {
|
|
|
45888
46446
|
if (!ready) {
|
|
45889
46447
|
let tail = "";
|
|
45890
46448
|
try {
|
|
45891
|
-
tail =
|
|
46449
|
+
tail = import_node_fs21.default.readFileSync(logFile, "utf-8").split("\n").filter(Boolean).slice(-15).join("\n");
|
|
45892
46450
|
} catch {
|
|
45893
46451
|
}
|
|
45894
46452
|
throw new Error(
|
|
45895
46453
|
`Sailor UI failed to start within ${READY_TIMEOUT_MS / 1e3}s on port ${port}.` + (tail ? `
|
|
45896
46454
|
|
|
45897
46455
|
Server output:
|
|
45898
|
-
${tail}` : ` See ${
|
|
46456
|
+
${tail}` : ` See ${import_node_path17.default.relative(projectRoot, logFile)}.`)
|
|
45899
46457
|
);
|
|
45900
46458
|
}
|
|
45901
46459
|
let exposed = false;
|
|
@@ -45910,8 +46468,8 @@ ${tail}` : ` See ${import_node_path16.default.relative(projectRoot, logFile)}.`)
|
|
|
45910
46468
|
);
|
|
45911
46469
|
}
|
|
45912
46470
|
}
|
|
45913
|
-
|
|
45914
|
-
|
|
46471
|
+
import_node_fs21.default.writeFileSync(
|
|
46472
|
+
import_node_path17.default.join(projectRoot, UI_STATE_FILE),
|
|
45915
46473
|
JSON.stringify({ pid: child.pid, port, startedAt: (/* @__PURE__ */ new Date()).toISOString(), exposed }, null, 2)
|
|
45916
46474
|
);
|
|
45917
46475
|
console.log(`Sailor UI started at http://localhost:${port} (pid ${child.pid})`);
|
|
@@ -45924,7 +46482,7 @@ async function uiStatus() {
|
|
|
45924
46482
|
console.log(`\u25CF running http://localhost:${state.port} (pid ${state.pid})`);
|
|
45925
46483
|
await warnIfVersionSkew(state.port);
|
|
45926
46484
|
} else {
|
|
45927
|
-
if (state)
|
|
46485
|
+
if (state) import_node_fs21.default.rmSync(import_node_path17.default.join(process.cwd(), UI_STATE_FILE), { force: true });
|
|
45928
46486
|
console.log("\u25CB Sailor UI is not running");
|
|
45929
46487
|
}
|
|
45930
46488
|
}
|
|
@@ -45936,7 +46494,7 @@ function uiStop() {
|
|
|
45936
46494
|
return;
|
|
45937
46495
|
}
|
|
45938
46496
|
if (!isProcessAlive(state.pid)) {
|
|
45939
|
-
|
|
46497
|
+
import_node_fs21.default.rmSync(import_node_path17.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
45940
46498
|
console.log("Sailor UI is not running (stale state file removed).");
|
|
45941
46499
|
return;
|
|
45942
46500
|
}
|
|
@@ -45945,14 +46503,14 @@ function uiStop() {
|
|
|
45945
46503
|
tailscaleServeDown();
|
|
45946
46504
|
console.log("Tailnet exposure removed.");
|
|
45947
46505
|
}
|
|
45948
|
-
|
|
46506
|
+
import_node_fs21.default.rmSync(import_node_path17.default.join(projectRoot, UI_STATE_FILE), { force: true });
|
|
45949
46507
|
console.log(`Stopped Sailor UI (pid ${state.pid}).`);
|
|
45950
46508
|
}
|
|
45951
46509
|
|
|
45952
46510
|
// src/index.ts
|
|
45953
46511
|
function cliVersion() {
|
|
45954
46512
|
try {
|
|
45955
|
-
const pkg = JSON.parse((0,
|
|
46513
|
+
const pkg = JSON.parse((0, import_node_fs22.readFileSync)((0, import_node_path18.join)(packageRoot(), "package.json"), "utf-8"));
|
|
45956
46514
|
return pkg.version ?? "0.0.0";
|
|
45957
46515
|
} catch {
|
|
45958
46516
|
return "0.0.0";
|
|
@@ -46023,6 +46581,9 @@ mandate.command("attach").description("Register one or more already-deployed per
|
|
|
46023
46581
|
"--address <mandateOrName>",
|
|
46024
46582
|
"Permission address or locally-tracked name; or a comma-separated list of addresses to register together in one signature"
|
|
46025
46583
|
).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));
|
|
46584
|
+
mandate.command("configure").description(
|
|
46585
|
+
"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."
|
|
46586
|
+
).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
46587
|
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
46588
|
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
46589
|
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));
|