@dev.sail.money/sailor 1.3.0-95 → 1.3.0-98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -0
- package/package.json +2 -3
- package/packages/cli/dist/index.cjs +168 -76
- package/packages/cli/dist/server.cjs +57 -63
- package/packages/sdk/dist/abis/SailGovernance.d.ts +6 -5
- package/packages/sdk/dist/abis/SailGovernance.d.ts.map +1 -1
- package/packages/sdk/dist/abis/SailGovernance.js +6 -5
- package/packages/sdk/dist/abis/SailGovernance.js.map +1 -1
- package/packages/sdk/dist/fees.d.ts +58 -10
- package/packages/sdk/dist/fees.d.ts.map +1 -1
- package/packages/sdk/dist/fees.js +73 -41
- package/packages/sdk/dist/fees.js.map +1 -1
- package/packages/sdk/dist/index.d.ts +2 -1
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +1 -1
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +7 -2
- package/packages/sdk/dist/intelligence.d.ts.map +1 -1
- package/packages/sdk/dist/intelligence.js +2 -2
- package/packages/sdk/dist/intelligence.js.map +1 -1
- package/packages/sdk/dist/signing.d.ts +14 -0
- package/packages/sdk/dist/signing.d.ts.map +1 -1
- package/packages/ui/dist/assets/{add-CLs0-B0p.js → add-BX5reKtK.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-CDOk28sj.js → all-wallets-IZ3PlVF-.js} +1 -1
- package/packages/ui/dist/assets/{app-store-DVzpi1qN.js → app-store-ARgRdMdF.js} +1 -1
- package/packages/ui/dist/assets/{apple-C9U9iH1l.js → apple-VCaqsI9w.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-DjQ4jGMe.js → arrow-bottom-Cwptw8fW.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-jxial9Si.js → arrow-bottom-circle-h5vFiZ2I.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-BjAyI8D1.js → arrow-left-bM1TRcV9.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-BlFO4Tcx.js → arrow-right-BYd_N4Jr.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-DJ3oh3DH.js → arrow-top-CLUnwVE2.js} +1 -1
- package/packages/ui/dist/assets/{bank-B98it1qN.js → bank-6c28yOM9.js} +1 -1
- package/packages/ui/dist/assets/{basic-DsgeyPNu.js → basic-CJnbTfSd.js} +1 -1
- package/packages/ui/dist/assets/{browser-j4vCeHwE.js → browser-CDKlxM3D.js} +1 -1
- package/packages/ui/dist/assets/{card-CzxbMvEd.js → card-DQdED02q.js} +1 -1
- package/packages/ui/dist/assets/{ccip-U9yiu_EK.js → ccip-BL7RIPfY.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-D5sWBbk3.js → checkmark-JoRNVoFV.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-BW6w3KCC.js → checkmark-bold-B6bGHVIs.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-BbHhmTQq.js → chevron-bottom-BMCelIEu.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-D8BDH4Wo.js → chevron-left-ryPLhHCc.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-BQuQk5zc.js → chevron-right-CdDNRv7f.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-1oeSXkx4.js → chevron-top-BxWIjjGk.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-B1OMtzC-.js → chrome-store-D-fiJ9qJ.js} +1 -1
- package/packages/ui/dist/assets/{clock-e0HueehS.js → clock-xCPkzwjj.js} +1 -1
- package/packages/ui/dist/assets/{close-Cy1ytr26.js → close-BkqmPpWG.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-DqJu3ZPV.js → coinPlaceholder-PIvN9oq_.js} +1 -1
- package/packages/ui/dist/assets/{compass-XDz_N2Hg.js → compass-CW5kWcxW.js} +1 -1
- package/packages/ui/dist/assets/{copy-DmDo3Nob.js → copy-DUZlAQJJ.js} +1 -1
- package/packages/ui/dist/assets/{core-DbkMGSYW.js → core-von2c1sc.js} +3 -3
- package/packages/ui/dist/assets/cursor-BzRVY7BD.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-DF2aA10D.js → cursor-transparent-BUAMB0G1.js} +1 -1
- package/packages/ui/dist/assets/{desktop-CVydOWLn.js → desktop-BxdlwV8P.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-BuN2Whnz.js → disconnect-GelNh3mn.js} +1 -1
- package/packages/ui/dist/assets/{discord-DMNPvTB2.js → discord-N0jnxkzC.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-CacW-93f.js → etherscan-B41u7wF4.js} +1 -1
- package/packages/ui/dist/assets/{events-CZkVDFih.js → events-C9icG2YB.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-B26hIvqO.js → exclamation-triangle-BWJC56FC.js} +1 -1
- package/packages/ui/dist/assets/{extension-B7rI0gv7.js → extension-G6I6oogw.js} +1 -1
- package/packages/ui/dist/assets/{external-link-CX8skCbH.js → external-link-BPaGQf4a.js} +1 -1
- package/packages/ui/dist/assets/{facebook-BDqbE6kl.js → facebook-47twy32b.js} +1 -1
- package/packages/ui/dist/assets/{fallback-DWQYKf3l.js → fallback-BTfJeGjh.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-zQ3oQzZ8.js → farcaster-DYqnqCqs.js} +1 -1
- package/packages/ui/dist/assets/{filters-DCglZYsM.js → filters-dF6xeJnE.js} +1 -1
- package/packages/ui/dist/assets/{github-BH-BYjss.js → github-DbW4Ihz2.js} +1 -1
- package/packages/ui/dist/assets/{google-DYFWxZbC.js → google-TKm7G8LF.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-BXH_DtZ_.js → help-circle-CY3qTmsG.js} +1 -1
- package/packages/ui/dist/assets/{id-Dr2yTeX1.js → id-JpHW4q14.js} +1 -1
- package/packages/ui/dist/assets/{image-DeJey1Eg.js → image-Dip2fG98.js} +1 -1
- package/packages/ui/dist/assets/{index-BP-UuQ8g.js → index-BGJ_8fMk.js} +1 -1
- package/packages/ui/dist/assets/{index-C55-Ne92.js → index-Bq3PAopp.js} +1 -1
- package/packages/ui/dist/assets/{index-BksbyFjf.js → index-C4_cA5XW.js} +1 -1
- package/packages/ui/dist/assets/{index-uSdXE5b_.js → index-CaDN0gL4.js} +1 -1
- package/packages/ui/dist/assets/index-DLElIcBr.js +1789 -0
- package/packages/ui/dist/assets/index-lhNfD4jA.css +1 -0
- package/packages/ui/dist/assets/{index-DVjAiPHI.js → index-q0mGElxZ.js} +3 -3
- package/packages/ui/dist/assets/{index.es-dZlNPpfR.js → index.es-BaCKS_tW.js} +4 -4
- package/packages/ui/dist/assets/{info-B91pD5Rw.js → info-B1enFsqh.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-CySl3_on.js → info-circle-D4j3FISs.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-wwG8LQLo.js → lightbulb-DZbKr-vS.js} +1 -1
- package/packages/ui/dist/assets/{mail-D617YZ8y.js → mail-D-TO_uVQ.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-RbLbxUgF.js → metamask-sdk-DljW3QD1.js} +1 -1
- package/packages/ui/dist/assets/{mobile-CD9KlA0m.js → mobile-Bkmwzav2.js} +1 -1
- package/packages/ui/dist/assets/{more-BQ_rpPXo.js → more-D1_I_jiB.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-BA7nl9e6.js → network-placeholder-DUaFjoXh.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-D1EaaeDn.js → nftPlaceholder-Cc0iUryh.js} +1 -1
- package/packages/ui/dist/assets/{off-DnGG35_w.js → off-BvX71sse.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-E29x8poM.js → parseSignature-BAS-wKoj.js} +1 -1
- package/packages/ui/dist/assets/{play-store-C5u2FvYB.js → play-store-XzLbtbTd.js} +1 -1
- package/packages/ui/dist/assets/{plus-CM4xJkvI.js → plus-B77_RmYR.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-kM3FUIdR.js → qr-code-BNeIhB1d.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-DWrRWIBM.js → recycle-horizontal-B9sX-yty.js} +1 -1
- package/packages/ui/dist/assets/{refresh-CztbjK2d.js → refresh-BWRygnjm.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-DUHEIodF.js → reown-logo-DCAEsGFm.js} +1 -1
- package/packages/ui/dist/assets/{search-BJtb4mn1.js → search-ZXIqrawS.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-BjrTZpQx.js → secp256k1-Doz05h4g.js} +1 -1
- package/packages/ui/dist/assets/{send-B3_kavG1.js → send-BQcO0jNC.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-BrF9POiv.js → swapHorizontal-4yZEzz2K.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-Dgf8OjXj.js → swapHorizontalBold-DxBKu3sl.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-C6wX0JZj.js → swapHorizontalMedium-DAQYJ2JK.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-DTAVw6oF.js → swapHorizontalRoundedBold-CUlZzFJ6.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-KGlTFNoi.js → swapVertical-CjWHAaDM.js} +1 -1
- package/packages/ui/dist/assets/{telegram-DnLrK-4y.js → telegram-JBeabiJP.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-C6_oMJfw.js → three-dots-D3R8OjSx.js} +1 -1
- package/packages/ui/dist/assets/{twitch-DvPqPD4f.js → twitch-1f9z7xVO.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-BZdk82Am.js → twitterIcon-BW7n2xnp.js} +1 -1
- package/packages/ui/dist/assets/{verify-CbESD5G0.js → verify-Cs5owI38.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-BRjTrLxw.js → verify-filled-Ci5sx5qS.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-D9b2TGHc.js → w3m-modal-DnWtss8u.js} +1 -1
- package/packages/ui/dist/assets/{wallet-B87E5UId.js → wallet-MaGNqaW-.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-DmssSbYf.js → wallet-placeholder-kTOy12_L.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-CZkLKWMZ.js → walletconnect-CyuP92jg.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-BPTpHB1P.js → warning-circle-BImUCdpG.js} +1 -1
- package/packages/ui/dist/assets/{x-D_dEtEDU.js → x-II45JHpV.js} +1 -1
- package/packages/ui/dist/index.html +2 -2
- package/scripts/check-docs.mjs +1 -1
- package/templates/default/.agents/skills/sail-mandates/SKILL.md +12 -0
- package/templates/default/.agents/skills/sail-onboarding/SKILL.md +33 -34
- package/templates/default/.agents/skills/sail-overview/SKILL.md +100 -0
- package/templates/default/.agents/skills/sail-project-info/SKILL.md +2 -0
- package/templates/default/.agents/skills/sail-sailor/SKILL.md +190 -0
- package/templates/default/.agents/skills/sail-setup/SKILL.md +38 -0
- package/templates/default/.gitlab-ci.yml +58 -0
- package/templates/default/AGENTS.md +12 -87
- package/packages/cli/dist/mcp.cjs +0 -15534
- package/packages/ui/dist/assets/cursor-DRFqL8nZ.js +0 -3
- package/packages/ui/dist/assets/index-D6_Zei-R.js +0 -1790
- package/packages/ui/dist/assets/index-DZ2C2rHq.css +0 -1
package/AGENTS.md
CHANGED
|
@@ -73,8 +73,11 @@ addresses remain. This file is the source of truth this guide mirrors.
|
|
|
73
73
|
| `packages/cli/src/commands/onboard.ts` | SMA creation + permission registration flow |
|
|
74
74
|
| `packages/cli/src/commands/mandate-contracts.ts` | Deploy / attach / revoke permission contracts |
|
|
75
75
|
| `packages/cli/src/lib/mandates.ts` | `MandateStore` — `.sail/state/mandates.json` source of truth |
|
|
76
|
+
| `packages/sdk/src/fees.ts` | `readPermissionRegistrationFee` (live governance read) + per-permission fee math/disclosure/preflight |
|
|
76
77
|
| `packages/ui/server.js` | Local API + WebSocket proxy; signing station relay |
|
|
77
78
|
|
|
79
|
+
Per-permission registration fee (read live from governance, surfaced at sign time / activity / preflight): see `templates/default/.agents/skills/sail-mandates/SKILL.md` → "Registration fee".
|
|
80
|
+
|
|
78
81
|
## Build
|
|
79
82
|
|
|
80
83
|
```bash
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev.sail.money/sailor",
|
|
3
|
-
"version": "1.3.0-
|
|
3
|
+
"version": "1.3.0-98",
|
|
4
4
|
"description": "Operator toolkit for Sail Protocol",
|
|
5
5
|
"bin": {
|
|
6
|
-
"sailor": "packages/cli/dist/index.cjs"
|
|
7
|
-
"sailor-mcp": "packages/cli/dist/mcp.cjs"
|
|
6
|
+
"sailor": "packages/cli/dist/index.cjs"
|
|
8
7
|
},
|
|
9
8
|
"exports": {
|
|
10
9
|
"./sdk": {
|
|
@@ -4581,8 +4581,8 @@ var init_encoding = __esm({
|
|
|
4581
4581
|
"../../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/errors/encoding.js"() {
|
|
4582
4582
|
init_base();
|
|
4583
4583
|
IntegerOutOfRangeError = class extends BaseError2 {
|
|
4584
|
-
constructor({ max, min
|
|
4585
|
-
super(`Number "${value}" is not in safe ${size5 ? `${size5 * 8}-bit ${signed ? "signed" : "unsigned"} ` : ""}integer range ${max ? `(${
|
|
4584
|
+
constructor({ max, min, signed, size: size5, value }) {
|
|
4585
|
+
super(`Number "${value}" is not in safe ${size5 ? `${size5 * 8}-bit ${signed ? "signed" : "unsigned"} ` : ""}integer range ${max ? `(${min} to ${max})` : `(above ${min})`}`, { name: "IntegerOutOfRangeError" });
|
|
4586
4586
|
}
|
|
4587
4587
|
};
|
|
4588
4588
|
InvalidBytesBooleanError = class extends BaseError2 {
|
|
@@ -4945,9 +4945,9 @@ function aexists(instance, checkFinished = true) {
|
|
|
4945
4945
|
}
|
|
4946
4946
|
function aoutput(out, instance) {
|
|
4947
4947
|
abytes(out);
|
|
4948
|
-
const
|
|
4949
|
-
if (out.length <
|
|
4950
|
-
throw new Error("digestInto() expects output buffer of length at least " +
|
|
4948
|
+
const min = instance.outputLen;
|
|
4949
|
+
if (out.length < min) {
|
|
4950
|
+
throw new Error("digestInto() expects output buffer of length at least " + min);
|
|
4951
4951
|
}
|
|
4952
4952
|
}
|
|
4953
4953
|
function u32(arr) {
|
|
@@ -5751,11 +5751,11 @@ function encodeBool(value) {
|
|
|
5751
5751
|
function encodeNumber(value, { signed, size: size5 = 256 }) {
|
|
5752
5752
|
if (typeof size5 === "number") {
|
|
5753
5753
|
const max = 2n ** (BigInt(size5) - (signed ? 1n : 0n)) - 1n;
|
|
5754
|
-
const
|
|
5755
|
-
if (value > max || value <
|
|
5754
|
+
const min = signed ? -max - 1n : 0n;
|
|
5755
|
+
if (value > max || value < min)
|
|
5756
5756
|
throw new IntegerOutOfRangeError({
|
|
5757
5757
|
max: max.toString(),
|
|
5758
|
-
min:
|
|
5758
|
+
min: min.toString(),
|
|
5759
5759
|
signed,
|
|
5760
5760
|
size: size5 / 8,
|
|
5761
5761
|
value: value.toString()
|
|
@@ -8574,12 +8574,12 @@ function utf8ToBytes2(str) {
|
|
|
8574
8574
|
throw new Error("string expected");
|
|
8575
8575
|
return new Uint8Array(new TextEncoder().encode(str));
|
|
8576
8576
|
}
|
|
8577
|
-
function inRange(n,
|
|
8578
|
-
return isPosBig(n) && isPosBig(
|
|
8577
|
+
function inRange(n, min, max) {
|
|
8578
|
+
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
|
|
8579
8579
|
}
|
|
8580
|
-
function aInRange(title, n,
|
|
8581
|
-
if (!inRange(n,
|
|
8582
|
-
throw new Error("expected valid " + title + ": " +
|
|
8580
|
+
function aInRange(title, n, min, max) {
|
|
8581
|
+
if (!inRange(n, min, max))
|
|
8582
|
+
throw new Error("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n);
|
|
8583
8583
|
}
|
|
8584
8584
|
function bitLen(n) {
|
|
8585
8585
|
let len;
|
|
@@ -13526,8 +13526,8 @@ var init_Hex = __esm({
|
|
|
13526
13526
|
encoder4 = /* @__PURE__ */ new TextEncoder();
|
|
13527
13527
|
hexes4 = /* @__PURE__ */ Array.from({ length: 256 }, (_v, i) => i.toString(16).padStart(2, "0"));
|
|
13528
13528
|
IntegerOutOfRangeError2 = class extends BaseError3 {
|
|
13529
|
-
constructor({ max, min
|
|
13530
|
-
super(`Number \`${value}\` is not in safe${size5 ? ` ${size5 * 8}-bit` : ""}${signed ? " signed" : " unsigned"} integer range ${max ? `(\`${
|
|
13529
|
+
constructor({ max, min, signed, size: size5, value }) {
|
|
13530
|
+
super(`Number \`${value}\` is not in safe${size5 ? ` ${size5 * 8}-bit` : ""}${signed ? " signed" : " unsigned"} integer range ${max ? `(\`${min}\` to \`${max}\`)` : `(above \`${min}\`)`}`);
|
|
13531
13531
|
Object.defineProperty(this, "name", {
|
|
13532
13532
|
enumerable: true,
|
|
13533
13533
|
configurable: true,
|
|
@@ -25269,11 +25269,11 @@ function encodeBoolean(value) {
|
|
|
25269
25269
|
function encodeNumber2(value, { signed, size: size5 }) {
|
|
25270
25270
|
if (typeof size5 === "number") {
|
|
25271
25271
|
const max = 2n ** (BigInt(size5) - (signed ? 1n : 0n)) - 1n;
|
|
25272
|
-
const
|
|
25273
|
-
if (value > max || value <
|
|
25272
|
+
const min = signed ? -max - 1n : 0n;
|
|
25273
|
+
if (value > max || value < min)
|
|
25274
25274
|
throw new IntegerOutOfRangeError2({
|
|
25275
25275
|
max: max.toString(),
|
|
25276
|
-
min:
|
|
25276
|
+
min: min.toString(),
|
|
25277
25277
|
signed,
|
|
25278
25278
|
size: size5 / 8,
|
|
25279
25279
|
value: value.toString()
|
|
@@ -37811,38 +37811,43 @@ async function discoverSafesForOwner(owner2, chainId) {
|
|
|
37811
37811
|
}
|
|
37812
37812
|
|
|
37813
37813
|
// ../sdk/dist/fees.js
|
|
37814
|
-
|
|
37815
|
-
|
|
37814
|
+
init_esm2();
|
|
37815
|
+
async function readPermissionRegistrationFee(publicClient, governance) {
|
|
37816
|
+
return publicClient.readContract({
|
|
37817
|
+
address: governance,
|
|
37818
|
+
abi: SailGovernanceAbi,
|
|
37819
|
+
functionName: "permissionRegistrationFee"
|
|
37820
|
+
});
|
|
37816
37821
|
}
|
|
37817
|
-
async function
|
|
37818
|
-
|
|
37819
|
-
|
|
37820
|
-
|
|
37821
|
-
|
|
37822
|
-
|
|
37823
|
-
|
|
37824
|
-
|
|
37825
|
-
|
|
37826
|
-
|
|
37827
|
-
|
|
37828
|
-
|
|
37829
|
-
|
|
37830
|
-
|
|
37831
|
-
|
|
37832
|
-
|
|
37833
|
-
|
|
37834
|
-
|
|
37835
|
-
|
|
37836
|
-
|
|
37837
|
-
|
|
37838
|
-
|
|
37839
|
-
|
|
37840
|
-
|
|
37841
|
-
|
|
37842
|
-
|
|
37843
|
-
|
|
37844
|
-
|
|
37845
|
-
});
|
|
37822
|
+
async function estimateMandateRegistrationFee(publicClient, governance, permissions) {
|
|
37823
|
+
const flatFeeWei = await readPermissionRegistrationFee(publicClient, governance);
|
|
37824
|
+
const perPermission = permissions.map((permission) => ({ permission, feeWei: flatFeeWei }));
|
|
37825
|
+
const totalWei = flatFeeWei * BigInt(permissions.length);
|
|
37826
|
+
return { totalWei, perPermission };
|
|
37827
|
+
}
|
|
37828
|
+
function describeMandateFee(estimate) {
|
|
37829
|
+
const count = estimate.perPermission.length;
|
|
37830
|
+
if (count === 0)
|
|
37831
|
+
return "Registration fee: 0 ETH (no new permissions to register)";
|
|
37832
|
+
const noun = count === 1 ? "permission" : "permissions";
|
|
37833
|
+
const perFeeWei = estimate.perPermission[0].feeWei;
|
|
37834
|
+
return `Registration fee: ${formatEther(estimate.totalWei)} ETH (${count} ${noun} \xD7 ${formatEther(perFeeWei)} ETH)`;
|
|
37835
|
+
}
|
|
37836
|
+
var RegistrationFeeError = class extends Error {
|
|
37837
|
+
/** Total fee required (wei). */
|
|
37838
|
+
requiredWei;
|
|
37839
|
+
/** Signer balance available (wei). */
|
|
37840
|
+
balanceWei;
|
|
37841
|
+
constructor(message, requiredWei, balanceWei) {
|
|
37842
|
+
super(message);
|
|
37843
|
+
this.name = "RegistrationFeeError";
|
|
37844
|
+
this.requiredWei = requiredWei;
|
|
37845
|
+
this.balanceWei = balanceWei;
|
|
37846
|
+
}
|
|
37847
|
+
};
|
|
37848
|
+
function assertFeeAffordable(balanceWei, totalFeeWei) {
|
|
37849
|
+
if (balanceWei < totalFeeWei) {
|
|
37850
|
+
throw new RegistrationFeeError(`Insufficient ETH for the ${formatEther(totalFeeWei)} ETH registration fee; signer balance is ${formatEther(balanceWei)} ETH.`, totalFeeWei, balanceWei);
|
|
37846
37851
|
}
|
|
37847
37852
|
}
|
|
37848
37853
|
|
|
@@ -41441,6 +41446,21 @@ var MandateStore = class {
|
|
|
41441
41446
|
|
|
41442
41447
|
// src/commands/onboard.ts
|
|
41443
41448
|
init_esm2();
|
|
41449
|
+
|
|
41450
|
+
// src/lib/registration-fee.ts
|
|
41451
|
+
function registrationGate(args) {
|
|
41452
|
+
const { estimate, agentBalanceWei } = args;
|
|
41453
|
+
if (agentBalanceWei !== void 0) {
|
|
41454
|
+
assertFeeAffordable(agentBalanceWei, estimate.totalWei);
|
|
41455
|
+
}
|
|
41456
|
+
return {
|
|
41457
|
+
totalFeeWei: estimate.totalWei,
|
|
41458
|
+
permissionCount: estimate.perPermission.length,
|
|
41459
|
+
disclosure: describeMandateFee(estimate)
|
|
41460
|
+
};
|
|
41461
|
+
}
|
|
41462
|
+
|
|
41463
|
+
// src/commands/onboard.ts
|
|
41444
41464
|
async function onboard(options) {
|
|
41445
41465
|
if (!ProjectContext.exists()) {
|
|
41446
41466
|
emit(options.json, () => console.log('No Sailor project found. Run "sailor init" first.'), {
|
|
@@ -41819,6 +41839,17 @@ async function attachMandate(project, channel, publicClient, agentSigner, smaAdd
|
|
|
41819
41839
|
hasDeadline: registerPermissionHasDeadline,
|
|
41820
41840
|
deadline: registrationDeadline
|
|
41821
41841
|
});
|
|
41842
|
+
const feeEstimate = await estimateMandateRegistrationFee(
|
|
41843
|
+
publicClient,
|
|
41844
|
+
project.contracts.governance,
|
|
41845
|
+
[templateAddress]
|
|
41846
|
+
);
|
|
41847
|
+
const fee = feeEstimate.totalWei;
|
|
41848
|
+
const agentBalanceWei = await publicClient.getBalance({
|
|
41849
|
+
address: agentSigner.viemAccount.address
|
|
41850
|
+
});
|
|
41851
|
+
const gate = registrationGate({ estimate: feeEstimate, agentBalanceWei });
|
|
41852
|
+
say(() => console.log(gate.disclosure));
|
|
41822
41853
|
say(() => console.log(`
|
|
41823
41854
|
Pushing signing request for "${template.label}" permission\u2026`));
|
|
41824
41855
|
say(
|
|
@@ -41841,6 +41872,13 @@ Pushing signing request for "${template.label}" permission\u2026`));
|
|
|
41841
41872
|
{ label: "Mandate signer", value: permissionSigner }
|
|
41842
41873
|
],
|
|
41843
41874
|
explanation: permExplanation,
|
|
41875
|
+
// Disclose the fee in the signing card so the owner sees what the agent
|
|
41876
|
+
// will pay before signing. Only included when non-zero or when there is a
|
|
41877
|
+
// fee to disclose (zero-fee chains pass 0 ETH, still informative).
|
|
41878
|
+
registrationFee: {
|
|
41879
|
+
totalEth: formatEther(fee),
|
|
41880
|
+
permissionCount: 1
|
|
41881
|
+
},
|
|
41844
41882
|
typedData
|
|
41845
41883
|
});
|
|
41846
41884
|
if (response.status === "rejected") {
|
|
@@ -41867,12 +41905,6 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
41867
41905
|
} catch (err) {
|
|
41868
41906
|
if (err.message.startsWith("Security:")) throw err;
|
|
41869
41907
|
}
|
|
41870
|
-
say(() => console.log("Estimating permission fee\u2026"));
|
|
41871
|
-
const fee = await estimatePermissionFee(
|
|
41872
|
-
publicClient,
|
|
41873
|
-
project.contracts.governance,
|
|
41874
|
-
templateAddress
|
|
41875
|
-
);
|
|
41876
41908
|
say(() => console.log(`Submitting mandate registration (agent pays gas; fee ${fee} wei)\u2026`));
|
|
41877
41909
|
const walletClient = createWalletClient({
|
|
41878
41910
|
account: agentSigner.viemAccount,
|
|
@@ -41922,7 +41954,10 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
41922
41954
|
name: template.label,
|
|
41923
41955
|
sma: smaAddress,
|
|
41924
41956
|
txHash,
|
|
41925
|
-
chainId: project.chainId
|
|
41957
|
+
chainId: project.chainId,
|
|
41958
|
+
// Registration fee actually paid by the agent for this permission.
|
|
41959
|
+
fee: fee.toString(),
|
|
41960
|
+
feeEth: formatEther(fee)
|
|
41926
41961
|
});
|
|
41927
41962
|
return txHash;
|
|
41928
41963
|
}
|
|
@@ -42339,6 +42374,7 @@ ${spec.label} clone (${options.template})`);
|
|
|
42339
42374
|
hasDeadline: registerPermissionHasDeadline,
|
|
42340
42375
|
deadline
|
|
42341
42376
|
});
|
|
42377
|
+
const fee = await readPermissionRegistrationFee(publicClient, project.contracts.governance);
|
|
42342
42378
|
const label = options.label ?? `${spec.label} (${options.template})`;
|
|
42343
42379
|
say(
|
|
42344
42380
|
() => console.log(
|
|
@@ -42358,6 +42394,10 @@ ${spec.label} clone (${options.template})`);
|
|
|
42358
42394
|
{ label: "Mandate signer", value: permissionSigner },
|
|
42359
42395
|
...spec.describe(initParams)
|
|
42360
42396
|
],
|
|
42397
|
+
registrationFee: {
|
|
42398
|
+
totalEth: formatEther(fee),
|
|
42399
|
+
permissionCount: 1
|
|
42400
|
+
},
|
|
42361
42401
|
typedData
|
|
42362
42402
|
});
|
|
42363
42403
|
if (response.status === "rejected") {
|
|
@@ -42384,7 +42424,6 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
42384
42424
|
} catch (err) {
|
|
42385
42425
|
if (err.message.startsWith("Security:")) throw err;
|
|
42386
42426
|
}
|
|
42387
|
-
const fee = await estimatePermissionFee(publicClient, project.contracts.governance, clone);
|
|
42388
42427
|
if (!registerPermissionHasDeadline || deadline === void 0) {
|
|
42389
42428
|
throw new Error(
|
|
42390
42429
|
"deploy-clone requires a selective kernel (RegisterPermission with deadline). This chain's kernel does not match."
|
|
@@ -42437,7 +42476,10 @@ Connect the owner wallet (mandate signer) in the browser \u2014 the agent wallet
|
|
|
42437
42476
|
name: storedClone.name,
|
|
42438
42477
|
sma,
|
|
42439
42478
|
txHash,
|
|
42440
|
-
chainId: project.chainId
|
|
42479
|
+
chainId: project.chainId,
|
|
42480
|
+
// Registration fee actually paid by the agent for this permission.
|
|
42481
|
+
fee: fee.toString(),
|
|
42482
|
+
feeEth: formatEther(fee)
|
|
42441
42483
|
});
|
|
42442
42484
|
emit(json, () => {
|
|
42443
42485
|
}, {
|
|
@@ -42756,6 +42798,8 @@ Attaching ${permissions.length} permissions in one signature \u2014 the mandate
|
|
|
42756
42798
|
explanation: (rec ? explainPermission(rec.name, rec.sourcePath) : null) ?? void 0
|
|
42757
42799
|
};
|
|
42758
42800
|
});
|
|
42801
|
+
const flatFee = await readPermissionRegistrationFee(publicClient, project.contracts.governance);
|
|
42802
|
+
const fee = flatFee * BigInt(permissions.length);
|
|
42759
42803
|
const response = await channel.requestSignature({
|
|
42760
42804
|
type: "typed-data",
|
|
42761
42805
|
kind: "register-permission",
|
|
@@ -42768,6 +42812,11 @@ Attaching ${permissions.length} permissions in one signature \u2014 the mandate
|
|
|
42768
42812
|
{ label: "Mandate signer", value: permissionSigner }
|
|
42769
42813
|
],
|
|
42770
42814
|
permissions: permExplanations,
|
|
42815
|
+
registrationFee: {
|
|
42816
|
+
totalEth: formatEther(fee),
|
|
42817
|
+
permissionCount: permissions.length,
|
|
42818
|
+
...permissions.length > 1 ? { perPermissionEth: formatEther(flatFee) } : {}
|
|
42819
|
+
},
|
|
42771
42820
|
typedData
|
|
42772
42821
|
});
|
|
42773
42822
|
if (response.status === "rejected") {
|
|
@@ -42776,10 +42825,6 @@ Attaching ${permissions.length} permissions in one signature \u2014 the mandate
|
|
|
42776
42825
|
if (response.status !== "signature") {
|
|
42777
42826
|
throw new Error(`Expected an EIP-712 signature response, got: ${response.status}`);
|
|
42778
42827
|
}
|
|
42779
|
-
let fee = 0n;
|
|
42780
|
-
for (const permission of permissions) {
|
|
42781
|
-
fee += await estimatePermissionFee(publicClient, project.contracts.governance, permission);
|
|
42782
|
-
}
|
|
42783
42828
|
const chain2 = getChainById(project.chainId);
|
|
42784
42829
|
const walletClient = createWalletClient({
|
|
42785
42830
|
account: agentSigner.viemAccount,
|
|
@@ -42812,7 +42857,10 @@ Attaching ${permissions.length} permissions in one signature \u2014 the mandate
|
|
|
42812
42857
|
permission,
|
|
42813
42858
|
sma,
|
|
42814
42859
|
txHash,
|
|
42815
|
-
chainId: project.chainId
|
|
42860
|
+
chainId: project.chainId,
|
|
42861
|
+
// Each permission in the batch is charged the same flat fee.
|
|
42862
|
+
fee: flatFee.toString(),
|
|
42863
|
+
feeEth: formatEther(flatFee)
|
|
42816
42864
|
});
|
|
42817
42865
|
say(() => {
|
|
42818
42866
|
if (!present) {
|
|
@@ -43024,6 +43072,35 @@ function runForgeBuild() {
|
|
|
43024
43072
|
|
|
43025
43073
|
// src/commands/mandate.ts
|
|
43026
43074
|
init_esm2();
|
|
43075
|
+
function chargeablePermissions(tracked) {
|
|
43076
|
+
return tracked.filter((p) => !p.revokedOnChain && !p.registeredOnSma);
|
|
43077
|
+
}
|
|
43078
|
+
async function liveMandateFee(chainId, permissionAddresses) {
|
|
43079
|
+
if (permissionAddresses.length === 0) return { totalWei: 0n, perPermission: [] };
|
|
43080
|
+
try {
|
|
43081
|
+
const deployment = getSailDeployment(chainId);
|
|
43082
|
+
const rpcUrl = getRpcUrl(chainId) ?? getChainById(chainId).rpcUrls.default.http[0];
|
|
43083
|
+
const pc = createPublicClient({ chain: getChainById(chainId), transport: http(rpcUrl) });
|
|
43084
|
+
return await estimateMandateRegistrationFee(
|
|
43085
|
+
pc,
|
|
43086
|
+
deployment.governance,
|
|
43087
|
+
permissionAddresses
|
|
43088
|
+
);
|
|
43089
|
+
} catch {
|
|
43090
|
+
return null;
|
|
43091
|
+
}
|
|
43092
|
+
}
|
|
43093
|
+
function draftFeeFromEstimate(estimate) {
|
|
43094
|
+
const perFeeWei = estimate.perPermission[0]?.feeWei ?? 0n;
|
|
43095
|
+
return {
|
|
43096
|
+
perPermissionWei: perFeeWei.toString(),
|
|
43097
|
+
perPermissionEth: formatEther(perFeeWei),
|
|
43098
|
+
totalWei: estimate.totalWei.toString(),
|
|
43099
|
+
totalEth: formatEther(estimate.totalWei),
|
|
43100
|
+
permissionCount: estimate.perPermission.length,
|
|
43101
|
+
disclosure: describeMandateFee(estimate)
|
|
43102
|
+
};
|
|
43103
|
+
}
|
|
43027
43104
|
function resolveActiveChain(account2) {
|
|
43028
43105
|
try {
|
|
43029
43106
|
const project = new ProjectContext();
|
|
@@ -43096,19 +43173,28 @@ ${permissions.length} permission(s) tracked for SMA ${account2.safe}:
|
|
|
43096
43173
|
console.log(` ${status2}`);
|
|
43097
43174
|
}
|
|
43098
43175
|
const store = new MandateStore();
|
|
43176
|
+
const chargeable = chargeablePermissions(permissions);
|
|
43177
|
+
const draftPermissions = chargeable.map((p) => {
|
|
43178
|
+
const mandate2 = store.find(p.address);
|
|
43179
|
+
const explanation = explainPermission(p.label, mandate2?.sourcePath) ?? void 0;
|
|
43180
|
+
return { address: p.address, label: p.label, explanation };
|
|
43181
|
+
});
|
|
43182
|
+
let registrationFee;
|
|
43183
|
+
const unregisteredAddresses = chargeable.map((p) => p.address);
|
|
43184
|
+
if (unregisteredAddresses.length > 0) {
|
|
43185
|
+
const estimate = await liveMandateFee(chainId, unregisteredAddresses);
|
|
43186
|
+
if (estimate !== null) registrationFee = draftFeeFromEstimate(estimate);
|
|
43187
|
+
}
|
|
43099
43188
|
const draft = {
|
|
43100
43189
|
account: account2.safe,
|
|
43101
43190
|
chainId,
|
|
43102
|
-
|
|
43103
|
-
|
|
43104
|
-
|
|
43105
|
-
const mandate2 = store.find(p.address);
|
|
43106
|
-
const explanation = explainPermission(p.label, mandate2?.sourcePath) ?? void 0;
|
|
43107
|
-
return { address: p.address, label: p.label, explanation };
|
|
43108
|
-
}),
|
|
43109
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43191
|
+
permissions: draftPermissions,
|
|
43192
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43193
|
+
...registrationFee ? { registrationFee } : {}
|
|
43110
43194
|
};
|
|
43111
43195
|
writeJsonFile(sailPath("mandate-draft.json"), draft);
|
|
43196
|
+
if (registrationFee) console.log(`
|
|
43197
|
+
${registrationFee.disclosure}`);
|
|
43112
43198
|
console.log("\nDraft written to .sail/mandate-draft.json for the UI to display.");
|
|
43113
43199
|
}
|
|
43114
43200
|
async function mandateSign(opts = {}) {
|
|
@@ -43135,6 +43221,15 @@ Permissions tracked for SMA ${account2.safe}:
|
|
|
43135
43221
|
"\nNote: `sailor mandate sign` reviews and confirms the permissions attached to your SMA.\nOn-chain registration happens via `sailor mandate attach` (or `sailor mandate deploy --attach`)."
|
|
43136
43222
|
);
|
|
43137
43223
|
const activePermissions = permissions.filter((p) => !p.revokedOnChain);
|
|
43224
|
+
const unregistered = chargeablePermissions(permissions);
|
|
43225
|
+
if (unregistered.length > 0) {
|
|
43226
|
+
const estimate = await liveMandateFee(chainId, unregistered.map((p) => p.address));
|
|
43227
|
+
if (estimate !== null) {
|
|
43228
|
+
console.log(`
|
|
43229
|
+
${describeMandateFee(estimate)}`);
|
|
43230
|
+
console.log(" Paid by the agent wallet on registration, per permission.");
|
|
43231
|
+
}
|
|
43232
|
+
}
|
|
43138
43233
|
const proceed = opts.yes || await confirm(
|
|
43139
43234
|
`Confirm these ${activePermissions.length} permission(s) are authorized for your SMA?`
|
|
43140
43235
|
);
|
|
@@ -43142,7 +43237,6 @@ Permissions tracked for SMA ${account2.safe}:
|
|
|
43142
43237
|
console.log("No permissions confirmed.");
|
|
43143
43238
|
return;
|
|
43144
43239
|
}
|
|
43145
|
-
const unregistered = activePermissions.filter((p) => !p.registeredOnSma);
|
|
43146
43240
|
if (unregistered.length === 0) {
|
|
43147
43241
|
console.log(`
|
|
43148
43242
|
\u2713 Confirmed ${activePermissions.length} permission(s) for ${account2.safe}.`);
|
|
@@ -43684,10 +43778,8 @@ Re-approving ${permissions.length} mandate(s) \u2014 the mandate signer (${permi
|
|
|
43684
43778
|
if (response.status !== "signature") {
|
|
43685
43779
|
throw new Error(`Expected an EIP-712 signature response, got: ${response.status}`);
|
|
43686
43780
|
}
|
|
43687
|
-
|
|
43688
|
-
|
|
43689
|
-
fee += await estimatePermissionFee(publicClient, project.contracts.governance, permission);
|
|
43690
|
-
}
|
|
43781
|
+
const flatFee = await readPermissionRegistrationFee(publicClient, project.contracts.governance);
|
|
43782
|
+
const fee = flatFee * BigInt(permissions.length);
|
|
43691
43783
|
const agentSigner = await loadManagerSigner();
|
|
43692
43784
|
const chain2 = getChainById(project.chainId);
|
|
43693
43785
|
const walletClient = createWalletClient({
|