@dev.sail.money/sailor 0.0.2 → 1.0.0-38
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 +43 -15
- package/README.md +217 -126
- package/examples/permissions/BoundedApproveAndCallBatch.sol +179 -0
- package/examples/permissions/BoundedBet_Limitless_Base.sol +8 -7
- package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +13 -13
- package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +50 -39
- package/examples/permissions/BoundedStake_Venice_Base.sol +85 -0
- package/examples/permissions/BoundedSupply_AaveV3_Arbitrum.sol +82 -0
- package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +15 -12
- package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +14 -8
- package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +6 -6
- package/examples/permissions/BoundedVault_ERC4626_Base.sol +97 -0
- package/examples/permissions/README.md +29 -2
- package/examples/permissions/SailCalldata.sol +118 -0
- package/examples/permissions/interfaces/IBatchPermission.sol +38 -0
- package/package.json +17 -12
- package/packages/cli/dist/index.cjs +4164 -2508
- package/packages/cli/dist/server.cjs +897 -1566
- package/packages/sdk/dist/chains.d.ts +12 -0
- package/packages/sdk/dist/chains.d.ts.map +1 -0
- package/packages/sdk/dist/chains.js +94 -0
- package/packages/sdk/dist/chains.js.map +1 -0
- package/packages/sdk/dist/deployments.d.ts +14 -7
- package/packages/sdk/dist/deployments.d.ts.map +1 -1
- package/packages/sdk/dist/deployments.js +132 -141
- package/packages/sdk/dist/deployments.js.map +1 -1
- package/packages/sdk/dist/index.d.ts +3 -2
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +3 -2
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +1 -1
- package/packages/sdk/dist/intelligence.js +1 -1
- package/packages/sdk/dist/lifi.d.ts +17 -0
- package/packages/sdk/dist/lifi.d.ts.map +1 -1
- package/packages/sdk/dist/lifi.js +24 -0
- package/packages/sdk/dist/lifi.js.map +1 -1
- package/packages/sdk/dist/safe.d.ts +83 -0
- package/packages/sdk/dist/safe.d.ts.map +1 -1
- package/packages/sdk/dist/safe.js +92 -1
- package/packages/sdk/dist/safe.js.map +1 -1
- package/packages/sdk/dist/templates/ammLiquidity.d.ts +24 -11
- package/packages/sdk/dist/templates/ammLiquidity.d.ts.map +1 -1
- package/packages/sdk/dist/templates/ammLiquidity.js +39 -31
- package/packages/sdk/dist/templates/ammLiquidity.js.map +1 -1
- package/packages/sdk/dist/templates/approveAndCallBatch.d.ts +24 -10
- package/packages/sdk/dist/templates/approveAndCallBatch.d.ts.map +1 -1
- package/packages/sdk/dist/templates/approveAndCallBatch.js +36 -23
- package/packages/sdk/dist/templates/approveAndCallBatch.js.map +1 -1
- package/packages/sdk/dist/templates/boundedBorrow.d.ts +19 -9
- package/packages/sdk/dist/templates/boundedBorrow.d.ts.map +1 -1
- package/packages/sdk/dist/templates/boundedBorrow.js +28 -19
- package/packages/sdk/dist/templates/boundedBorrow.js.map +1 -1
- package/packages/sdk/dist/templates/boundedSwap.d.ts +19 -9
- package/packages/sdk/dist/templates/boundedSwap.d.ts.map +1 -1
- package/packages/sdk/dist/templates/boundedSwap.js +30 -20
- package/packages/sdk/dist/templates/boundedSwap.js.map +1 -1
- package/packages/sdk/dist/templates/defiBundle.d.ts +35 -9
- package/packages/sdk/dist/templates/defiBundle.d.ts.map +1 -1
- package/packages/sdk/dist/templates/defiBundle.js +84 -22
- package/packages/sdk/dist/templates/defiBundle.js.map +1 -1
- package/packages/sdk/dist/templates/pendle.d.ts +23 -8
- package/packages/sdk/dist/templates/pendle.d.ts.map +1 -1
- package/packages/sdk/dist/templates/pendle.js +34 -14
- package/packages/sdk/dist/templates/pendle.js.map +1 -1
- package/packages/sdk/dist/templates/transferTarget.d.ts +11 -3
- package/packages/sdk/dist/templates/transferTarget.d.ts.map +1 -1
- package/packages/sdk/dist/templates/transferTarget.js +14 -7
- package/packages/sdk/dist/templates/transferTarget.js.map +1 -1
- package/packages/sdk/dist/types.d.ts +19 -1
- package/packages/sdk/dist/types.d.ts.map +1 -1
- package/packages/sdk/package.json +28 -0
- package/packages/ui/dist/assets/{add-DaJhwIBV.js → add-Dl1etsL9.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-BUxsqWXi.js → all-wallets-C0eHLOGG.js} +1 -1
- package/packages/ui/dist/assets/{app-store-DkltwTqE.js → app-store-B-VMDEZ3.js} +1 -1
- package/packages/ui/dist/assets/{apple-owVOeaIT.js → apple-DkDXzKns.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-D2mmNJve.js → arrow-bottom-DtPzuS76.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-CbNYijx-.js → arrow-bottom-circle-D7odSAO8.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-DJB61s4C.js → arrow-left-zJV9tpx0.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-BBrsQ9R4.js → arrow-right-BOREfe7o.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-Cil6bOc8.js → arrow-top-CipQc3Af.js} +1 -1
- package/packages/ui/dist/assets/{bank-CbwEmRo3.js → bank-C5s7eoV5.js} +1 -1
- package/packages/ui/dist/assets/{basic-CLNfjw3m.js → basic-D2es4Vq8.js} +1 -1
- package/packages/ui/dist/assets/{browser-B5TtF4Pb.js → browser-DITQWDC9.js} +1 -1
- package/packages/ui/dist/assets/{card-CO7BVB-C.js → card-C3DDkaYK.js} +1 -1
- package/packages/ui/dist/assets/{ccip-2W7K3_J3.js → ccip-UBXL3JiN.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-D9xGHzPE.js → checkmark-bold-D8yW0_K_.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-BEtSHq9m.js → checkmark-ngef3MAl.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-BDztht6i.js → chevron-bottom-C56BipDR.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-EV4GFNbc.js → chevron-left-BmIPtPl_.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-B4_bB9oR.js → chevron-right-BnySHQ8h.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-D54xPNzF.js → chevron-top-BDGZnNW3.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-DYUpAJJq.js → chrome-store-BYIqJZVF.js} +1 -1
- package/packages/ui/dist/assets/{clock-Ca1T1Soz.js → clock-Bl4mUHAM.js} +1 -1
- package/packages/ui/dist/assets/{close-BZqWjurK.js → close-B9rhEX6U.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-e6fl2XDo.js → coinPlaceholder-1cO0FQsl.js} +1 -1
- package/packages/ui/dist/assets/{compass-DCLC7zIh.js → compass-7i-VuXu2.js} +1 -1
- package/packages/ui/dist/assets/{copy-Th2AaD-O.js → copy-OqqXix2J.js} +1 -1
- package/packages/ui/dist/assets/{core-Ckx_cyuH.js → core-tX9kIIDJ.js} +3 -3
- package/packages/ui/dist/assets/cursor-BoyeQ9fN.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-BKHeABKB.js → cursor-transparent-5aoRH67u.js} +1 -1
- package/packages/ui/dist/assets/{desktop-CBjY8t6F.js → desktop-BaPXK9R6.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-DbSs2cli.js → disconnect-LlK5K1CF.js} +1 -1
- package/packages/ui/dist/assets/{discord-ZlLOAUkM.js → discord-BdcQNWY_.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-CKUrqWYN.js → etherscan-Bb-WxpO1.js} +1 -1
- package/packages/ui/dist/assets/{events-CiKP71cK.js → events-DjdZr6no.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-DA1QzFiO.js → exclamation-triangle-COx4VtPV.js} +1 -1
- package/packages/ui/dist/assets/{extension-BVJkmvpJ.js → extension-DF63DTWO.js} +1 -1
- package/packages/ui/dist/assets/{external-link-D_bsR7B2.js → external-link-DyghCkQu.js} +1 -1
- package/packages/ui/dist/assets/{facebook-CmFmhojx.js → facebook-Dcg4bZMR.js} +1 -1
- package/packages/ui/dist/assets/{fallback-Ofl6uSnB.js → fallback-DJIr_fH3.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-Co-M3Ss8.js → farcaster-BkmV5HjO.js} +1 -1
- package/packages/ui/dist/assets/{filters-B1WwNaFU.js → filters-DLHj1T_P.js} +1 -1
- package/packages/ui/dist/assets/{github-CP4fP6gn.js → github-BFDCgKrF.js} +1 -1
- package/packages/ui/dist/assets/{google-CsOIXJ6V.js → google-C08SpmIy.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-DiMkomdF.js → help-circle-DU1IFmWp.js} +1 -1
- package/packages/ui/dist/assets/{id-lmscL5LX.js → id-DtDRGf3L.js} +1 -1
- package/packages/ui/dist/assets/{image-B-ubJrY5.js → image-CgCXJEjT.js} +1 -1
- package/packages/ui/dist/assets/{index-Dbh5V1Z0.js → index-8chM4S5Y.js} +1 -1
- package/packages/ui/dist/assets/{index-BaukYv-x.js → index-B5sCtNuq.js} +1 -1
- package/packages/ui/dist/assets/{index-CF0KMmke.js → index-BBfBEazf.js} +3 -3
- package/packages/ui/dist/assets/{index-CZR1Qjhs.js → index-BhXPwltt.js} +1 -1
- package/packages/ui/dist/assets/index-Cm05Py20.css +1 -0
- package/packages/ui/dist/assets/{index-DVgfCzCo.js → index-D37bD6Yt.js} +1 -1
- package/packages/ui/dist/assets/index-DZfBh-cg.js +1775 -0
- package/packages/ui/dist/assets/{index.es-C78cE5SI.js → index.es-BEcNQEn-.js} +4 -4
- package/packages/ui/dist/assets/{info-Cqg57EVo.js → info-ClsdYA4P.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-DkeSWNKV.js → info-circle-DJmn4Bsv.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-DNlO4qKh.js → lightbulb-CXSftjXS.js} +1 -1
- package/packages/ui/dist/assets/{mail-kVQ8Jb9Y.js → mail-cdYKOl9P.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-CBalSvz7.js → metamask-sdk-Co3aIEln.js} +1 -1
- package/packages/ui/dist/assets/{mobile-BEteuhF7.js → mobile-DEHYlk8L.js} +1 -1
- package/packages/ui/dist/assets/{more-DBWmXQli.js → more-Cq_fo8pI.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-Dg1uUHiL.js → network-placeholder-_dLCK4xB.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-i3AHSiD9.js → nftPlaceholder-Dz4HKEr4.js} +1 -1
- package/packages/ui/dist/assets/{off-BtMm0fi2.js → off-B1k1lhkr.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-Cb5FlWWg.js → parseSignature-Cr0ptV2X.js} +1 -1
- package/packages/ui/dist/assets/{play-store-iKKkXa6a.js → play-store-lYqe4eeL.js} +1 -1
- package/packages/ui/dist/assets/{plus-CA5NaRtb.js → plus-QMgh1krr.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-D2kiqR7h.js → qr-code-ClVHbZWN.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-Dcme7R03.js → recycle-horizontal-CxGYnWid.js} +1 -1
- package/packages/ui/dist/assets/{refresh-Dega3sDp.js → refresh-CPysMza_.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-xNkksyWJ.js → reown-logo-OoL_zJd0.js} +1 -1
- package/packages/ui/dist/assets/{search-HYl7NO8x.js → search-2GaRbf1I.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-Cxd6_SiH.js → secp256k1-BrB8qSSy.js} +1 -1
- package/packages/ui/dist/assets/{send-CJU8CUAo.js → send-CC2UuIfD.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-IMUKiUre.js → swapHorizontal-BRqYwsqT.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-CNYnNJ9-.js → swapHorizontalBold-Bj0GSRq9.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-B9VxEYsT.js → swapHorizontalMedium-oLOjpU2A.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-Dz33l_Jh.js → swapHorizontalRoundedBold-TJ652QXb.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-CHUmjVJ0.js → swapVertical-e0NLyV3x.js} +1 -1
- package/packages/ui/dist/assets/{telegram-kl9S2mbU.js → telegram-WhJHVeoU.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-U5lhA1Am.js → three-dots-BlBAOyW-.js} +1 -1
- package/packages/ui/dist/assets/{twitch-KTEUWXEp.js → twitch-BH7vWmPc.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-BHiq8mRg.js → twitterIcon-As0Nkanp.js} +1 -1
- package/packages/ui/dist/assets/{verify-CfN-BXNd.js → verify-BEJ0QuLl.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-DwZccetj.js → verify-filled-B8Ww2N7z.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-CS-PFqPE.js → w3m-modal-5rOSZgOR.js} +1 -1
- package/packages/ui/dist/assets/{wallet-DVlGkhOY.js → wallet-CAfC3aml.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-CvR_iEWX.js → wallet-placeholder-4RZI464Z.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-8pZBDvVI.js → walletconnect-BiltKqAe.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-ylLEE0Yp.js → warning-circle-CI4jqpHo.js} +1 -1
- package/packages/ui/dist/assets/{x-C_TBsTMj.js → x-FBttjBWO.js} +1 -1
- package/packages/ui/dist/index.html +2 -2
- package/scripts/check-init.mjs +2 -3
- package/templates/custom-mandate/README.md +31 -0
- package/templates/custom-mandate/mandates/BoundedCallPermission.sol +8 -2
- package/templates/custom-mandate/mandates/SailCalldata.sol +118 -0
- package/templates/default/.env.example +20 -0
- package/templates/{dca-rebalancer → default}/.github/workflows/agent-tick.yml +8 -7
- package/templates/{dca-rebalancer → default}/.sail/config.json +2 -2
- package/templates/default/AGENTS.md +171 -0
- package/templates/default/README.md +16 -0
- package/templates/default/examples/dca/README.md +16 -0
- package/templates/default/examples/dca/agent.ts +174 -0
- package/templates/{dca-rebalancer/src → default/examples/dca}/mandate.ts +9 -31
- package/templates/{dca-rebalancer → default}/package.json +2 -2
- package/templates/default/src/agent.ts +37 -0
- package/templates/default/src/config.ts +24 -0
- package/templates/default/src/mandate.ts +22 -0
- package/templates/default/tsconfig.json +17 -0
- package/templates/lifi-permissions/README.md +1 -1
- package/packages/ui/dist/assets/cursor-DV7rOqbJ.js +0 -3
- package/packages/ui/dist/assets/index-CKxgNxS9.css +0 -1
- package/packages/ui/dist/assets/index-Q2Yai4Fe.js +0 -2103
- package/scripts/postinstall.js +0 -366
- package/templates/dca-rebalancer/.env.example +0 -6
- package/templates/dca-rebalancer/AGENTS.md +0 -246
- package/templates/dca-rebalancer/AGENT_PLAYBOOK.md +0 -110
- package/templates/dca-rebalancer/README.md +0 -16
- package/templates/dca-rebalancer/src/agent.ts +0 -253
- package/templates/dca-rebalancer/src/config.ts +0 -27
- package/templates/dca-rebalancer/tsconfig.json +0 -8
- /package/templates/{dca-rebalancer → default}/.cursor/rules +0 -0
- /package/templates/{dca-rebalancer → default}/.sail/.gitkeep +0 -0
- /package/templates/{dca-rebalancer → default}/.sail/README.md +0 -0
- /package/templates/{dca-rebalancer → default}/CLAUDE.md +0 -0
- /package/templates/{dca-rebalancer → default}/_gitignore +0 -0
- /package/templates/{dca-rebalancer → default}/docs/PERMISSION_MODEL.md +0 -0
- /package/templates/{dca-rebalancer → default}/ui/README.md +0 -0
package/AGENTS.md
CHANGED
|
@@ -8,11 +8,10 @@ tooling to create SMAs, register permission contracts, and run strategy agents.
|
|
|
8
8
|
|
|
9
9
|
| Package / path | Name | Role |
|
|
10
10
|
|---|---|---|
|
|
11
|
-
| `packages/sdk` | `@sail/sdk` | SailorClient, LocalKeyring, kernel ABIs, EIP-712 builders, deployment registry |
|
|
11
|
+
| `packages/sdk` | `@sail/sdk` | SailorClient, LocalKeyring, kernel ABIs, EIP-712 builders, deployment registry, per-chain address registry |
|
|
12
12
|
| `packages/cli` | `sailor` | CLI: init, keys, account, mandate, onboard, station, ui, run, session, scan, status, owner, doctor, capabilities |
|
|
13
|
-
| `packages/chains` | `@sail/chains` | Per-chain address registry (kernel, mandateFactory, governance) |
|
|
14
13
|
| `packages/ui` | `sailor-ui` | Local dashboard + browser-driven onboarding wizard at localhost:3333 |
|
|
15
|
-
| `templates/
|
|
14
|
+
| `templates/default` | — | Default agent starter: neutral blank scaffold + Foundry workspace + onboarding guide (AGENTS.md) |
|
|
16
15
|
| `templates/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
|
|
17
16
|
|
|
18
17
|
## Protocol roles
|
|
@@ -29,16 +28,15 @@ Use the user-facing terms in all CLI output, prompts, and errors. The code ident
|
|
|
29
28
|
|
|
30
29
|
## Dispatch model
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
All six chains share the same kernel at the same CREATE2 address, verified on-chain via `DISPATCH_TYPEHASH()`:
|
|
33
32
|
|
|
34
|
-
|
|
|
35
|
-
|
|
36
|
-
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
| Unichain 130 | `0xD985029960a9B7C2E7E38e102C448b8b8539B156` | **selective** | `0xbe50c539...` |
|
|
33
|
+
| Kernel (all 6 chains) | Model | DISPATCH_TYPEHASH |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `0x02ABC18B65A328de2e749F56ba79ACF2718a6659` | **selective** | `0xbe50c539...` |
|
|
36
|
+
|
|
37
|
+
Supported chains: Ethereum (1), Base (8453), Arbitrum (42161), Unichain (130), Base Sepolia (84532), Eth Sepolia (11155111).
|
|
40
38
|
|
|
41
|
-
All
|
|
39
|
+
All six kernels are live and bootstrapped (genesis allowlist set, `createAccount` verified working, zero fees). No templates are deployed against the current kernel on any chain yet — `knownTemplates` and `standaloneTemplates` are empty for all six entries. `packages/sdk/src/deployments.ts` is the canonical source of truth for kernel addresses, templates, and metadata.
|
|
42
40
|
|
|
43
41
|
**Always use `detectKernelCapabilities` for the real model** — it reads the on-chain typehash and
|
|
44
42
|
overrides the static label in `deployments.ts`. The static label is a fallback for offline use only.
|
|
@@ -57,11 +55,11 @@ Pass the detected value — never hardcode the type shape.
|
|
|
57
55
|
|
|
58
56
|
## Active addresses
|
|
59
57
|
|
|
60
|
-
All
|
|
58
|
+
All six chain records in `packages/sdk/src/deployments.ts` are live — no commented-out or pending
|
|
61
59
|
addresses remain. This file is the source of truth this guide mirrors.
|
|
62
60
|
|
|
63
61
|
- `packages/sdk/src/deployments.ts` — `SailDeployment` records; canonical source of truth
|
|
64
|
-
- `packages/
|
|
62
|
+
- `packages/sdk/src/chains.ts` — `ChainConfig` per chainId; canonical per-chain registry
|
|
65
63
|
|
|
66
64
|
## Key files
|
|
67
65
|
|
|
@@ -79,10 +77,10 @@ addresses remain. This file is the source of truth this guide mirrors.
|
|
|
79
77
|
|
|
80
78
|
```bash
|
|
81
79
|
pnpm install
|
|
82
|
-
pnpm build # builds all packages; dependency order: sdk →
|
|
80
|
+
pnpm build # builds all packages; dependency order: sdk → cli → ui
|
|
83
81
|
```
|
|
84
82
|
|
|
85
|
-
Build order matters — `cli` imports from `sdk
|
|
83
|
+
Build order matters — `cli` imports from `sdk`.
|
|
86
84
|
|
|
87
85
|
## Test
|
|
88
86
|
|
|
@@ -94,6 +92,36 @@ pnpm test:ui # playwright — requires pnpm build first
|
|
|
94
92
|
Test fixtures live in `packages/ui/test/fixtures/` — isolated directories with pre-canned `.sail/`
|
|
95
93
|
state; no real RPC needed.
|
|
96
94
|
|
|
95
|
+
## RPC configuration
|
|
96
|
+
|
|
97
|
+
RPC URLs are resolved by `packages/cli/src/lib/chain.ts` `getRpcUrl(chainId)` in this order (first match wins):
|
|
98
|
+
|
|
99
|
+
1. `.sail/.env.local` — chain-specific var (e.g. `BASE_RPC_URL`, `ARBITRUM_RPC_URL`)
|
|
100
|
+
2. `.sail/.env.local` — generic `RPC_URL`
|
|
101
|
+
3. Shell environment — chain-specific var
|
|
102
|
+
4. Shell environment — generic `RPC_URL`
|
|
103
|
+
|
|
104
|
+
Two valid patterns for `.sail/.env.local`:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
# Option A — single active chain
|
|
108
|
+
RPC_URL=https://your-base-endpoint
|
|
109
|
+
CHAIN_ID=8453
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
# Option B — per-chain (multi-chain projects; omit RPC_URL if all chains have a specific var)
|
|
114
|
+
CHAIN_ID=8453
|
|
115
|
+
BASE_RPC_URL=https://your-base-endpoint
|
|
116
|
+
ARBITRUM_RPC_URL=https://your-arbitrum-endpoint
|
|
117
|
+
UNICHAIN_RPC_URL=https://your-unichain-endpoint
|
|
118
|
+
ETH_MAINNET_RPC_URL=https://your-mainnet-endpoint
|
|
119
|
+
BASE_SEPOLIA_RPC_URL=https://your-base-sepolia-endpoint
|
|
120
|
+
SEPOLIA_RPC_URL=https://your-sepolia-endpoint
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Per-chain vars always take precedence for their specific chain, so multi-chain projects resolve each endpoint correctly. `sailor chains --verify` uses this to check every chain that has a configured RPC.
|
|
124
|
+
|
|
97
125
|
## Conventions
|
|
98
126
|
|
|
99
127
|
- `SAIL_DIR` — env var pointing to the project's `.sail/` directory (used by the UI server)
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Sailor
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> The operator toolkit for Sail Protocol — SDK, CLI, and local dashboard for building and running mandated agents.
|
|
4
4
|
|
|
5
|
-
Sailor is the operator layer for [Sail Protocol](
|
|
5
|
+
Sailor is the off-chain operator layer for [Sail Protocol](https://github.com/sail-money/SailProtocol): the tooling an operator uses to create a Separately Managed Account, register a mandate, and run a strategy agent against it. It wraps SailKernel dispatch, MandateFactory registration, and EIP-712 mandate signing behind a TypeScript SDK, a CLI, and a local dashboard. It does not deploy the protocol or author permission templates — those live in Sail Protocol. It targets already-deployed SailKernel instances and gives operators the tooling to drive them.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -10,39 +10,60 @@ Sailor is the operator layer for [Sail Protocol](../SailProtocol): the tooling a
|
|
|
10
10
|
|
|
11
11
|
| Package | Name | Role |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
| `packages/sdk` | `@sail/sdk` | TypeScript library
|
|
14
|
-
| `packages/cli` |
|
|
15
|
-
| `packages/
|
|
16
|
-
| `
|
|
17
|
-
| `templates/
|
|
18
|
-
| `templates/custom-mandate` | — | Solidity reference: allowlist mandate contracts (not a project template) |
|
|
13
|
+
| `packages/sdk` | `@sail.money/sdk` / `@sail.money/sailor/sdk` | TypeScript library: SailorClient, EIP-712 helpers, ABIs, deployment registry, chain registry |
|
|
14
|
+
| `packages/cli` | `@sail.money/sailor` | CLI for account setup, mandate signing, and agent execution |
|
|
15
|
+
| `packages/ui` | `sailor-ui` | Local dashboard running at localhost:3333 |
|
|
16
|
+
| `templates/default` | — | Default agent starter (neutral; what `sailor init` scaffolds) |
|
|
17
|
+
| `templates/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
|
|
19
18
|
| `templates/lifi-permissions` | — | Solidity reference: LiFi clone permission contracts (not a project template) |
|
|
20
19
|
|
|
21
20
|
---
|
|
22
21
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
## Protocol model
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
flowchart TD
|
|
26
|
+
Owner["**Owner**<br/>holds the Safe · signs the mandate"]
|
|
27
|
+
Manager["**Manager**<br/>agent · signs dispatches"]
|
|
28
|
+
SMA["**SMA**<br/>Safe · holds assets · executes"]
|
|
29
|
+
Mandate["**Mandate**<br/>set of permission contracts"]
|
|
30
|
+
Kernel["**Sail Kernel**<br/>evaluates permission · trusted core<br/>dispatches to Safe on success"]
|
|
31
|
+
|
|
32
|
+
Owner -- "01 deploys & owns" --> SMA
|
|
33
|
+
Owner -- "02 signs mandate (EIP-712)" --> Mandate
|
|
34
|
+
Owner -- "03 appoints · instant revocation" --> Manager
|
|
35
|
+
Manager -- "04 signs dispatch (EIP-712)" --> Kernel
|
|
36
|
+
Mandate -- "05 defines bounds" --> Kernel
|
|
37
|
+
Kernel -- "06 ✓ executes · ✗ outside mandate: reverts" --> SMA
|
|
38
|
+
```
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
2. **Deploy SMA** — a Safe registered with SailKernel, with the manager and permissionSigner addresses set at registration.
|
|
29
|
-
3. **Write a strategy** — an async `tick` function that receives a context and returns a list of intended dispatches.
|
|
30
|
-
4. **Sign a mandate** — a set of registered permissions that bound what the agent can do, authorized via EIP-712 by the permission signer through MetaMask or a local key.
|
|
31
|
-
5. **Dry-run** — the kernel's `previewBatch` confirms the named permission passes before anything executes on-chain.
|
|
32
|
-
6. **Run the agent** — locally on a cron schedule, or via GitHub Actions on a timer.
|
|
33
|
-
7. **Monitor** — the local dashboard on localhost:3333 reflects live mandate state, agent status, and activity.
|
|
40
|
+
Sailor is the operator tooling that drives the Manager/dispatch and mandate-registration flows (steps 02–05).
|
|
34
41
|
|
|
35
42
|
---
|
|
36
43
|
|
|
37
44
|
## Roles
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
Sail Protocol separates three authority roles. Sailor operates all of them:
|
|
40
47
|
|
|
41
48
|
| Role | Authority | Held by |
|
|
42
49
|
|---|---|---|
|
|
43
|
-
| **Owner** | Holds the Safe. Custody anchor. | The LP (Safe owner)
|
|
44
|
-
| **Permission Signer** |
|
|
45
|
-
| **Manager** | Executes dispatches within
|
|
50
|
+
| **Owner** | Holds the Safe. Custody anchor. Always self-custodial. | The LP (Safe owner) |
|
|
51
|
+
| **Permission Signer** | Authorizes the mandate. Signs registration and revocation via EIP-712. | Same as Owner, or a separate signing key |
|
|
52
|
+
| **Manager** | Executes dispatches within mandate bounds. Signs each dispatch. | The agent wallet — encrypted in `.sail/keys/manager.json` |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## How it works
|
|
57
|
+
|
|
58
|
+
The path from nothing to a running agent follows the protocol lifecycle:
|
|
59
|
+
|
|
60
|
+
1. **Deploy your SMA** — `sailor onboard --new-sma` creates the SMA on-chain. `sailor account predict` computes the deterministic address in advance. The same owner, permission signer, manager, and salt produce the same SMA address on every supported chain.
|
|
61
|
+
2. **Author your permissions** — describe what the agent may do. Permission contracts encode the bounds: tokens, amounts, venues, call targets. Author them in the scaffolded Foundry workspace.
|
|
62
|
+
3. **Simulate, deploy, and sign your mandate** — `sailor mandate simulate` probes a permission off-chain before authorizing it. `sailor mandate deploy --attach` deploys and registers it on-chain. `sailor mandate sign` builds and signs the registration payload against live on-chain state.
|
|
63
|
+
4. **Run** — `sailor run` executes the agent locally on a schedule, or via the GitHub Actions workflow the scaffold provides.
|
|
64
|
+
5. **Operate** — `sailor doctor` checks kernel health and gas balances; `sailor chains` lists supported chains and deployment addresses; `sailor session pause` instantly revokes dispatch rights without touching Safe custody.
|
|
65
|
+
|
|
66
|
+
Run `npx sailor init my-agent`, open the scaffolded folder in Claude Code, Cursor, or any AI coding assistant, and say **"start"**. The `AGENTS.md` in the project guides the assistant through all five stages.
|
|
46
67
|
|
|
47
68
|
---
|
|
48
69
|
|
|
@@ -50,13 +71,24 @@ Sailor operates the three roles Sail Protocol separates:
|
|
|
50
71
|
|
|
51
72
|
### Start a new agent project (recommended)
|
|
52
73
|
|
|
53
|
-
|
|
74
|
+
Create a folder, step into it, then install and init:
|
|
54
75
|
|
|
55
|
-
```
|
|
56
|
-
|
|
76
|
+
```bash
|
|
77
|
+
# bash / zsh / macOS
|
|
78
|
+
mkdir my-agent && cd my-agent && npm i @sail.money/sailor && npx sailor init
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```powershell
|
|
82
|
+
# PowerShell (Windows)
|
|
83
|
+
mkdir my-agent ; cd my-agent ; npm i @sail.money/sailor ; npx sailor init
|
|
57
84
|
```
|
|
58
85
|
|
|
59
|
-
Then
|
|
86
|
+
Then open the folder in your AI coding assistant and say **"start"**.
|
|
87
|
+
|
|
88
|
+
> **npx shortcut** — skips the explicit install; npm downloads sailor on the fly:
|
|
89
|
+
> ```sh
|
|
90
|
+
> mkdir my-agent && cd my-agent && npx sailor init
|
|
91
|
+
> ```
|
|
60
92
|
|
|
61
93
|
### Global CLI (for direct sailor commands)
|
|
62
94
|
|
|
@@ -71,30 +103,53 @@ sailor init my-agent
|
|
|
71
103
|
|
|
72
104
|
Prerequisites:
|
|
73
105
|
|
|
74
|
-
- Node.js 18+
|
|
75
|
-
- A wallet (MetaMask
|
|
106
|
+
- Node.js 18+
|
|
107
|
+
- A wallet (MetaMask, Rabby, Phantom, and more)
|
|
76
108
|
- An RPC URL (e.g. Alchemy free tier)
|
|
77
|
-
- A supported chain: **Base, Base Sepolia,
|
|
109
|
+
- A supported chain: **Ethereum, Base, Arbitrum, Unichain, Base Sepolia, or Eth Sepolia** — verified deployments are bundled in `@sail.money/sailor`.
|
|
110
|
+
|
|
111
|
+
### Recommended — assistant-driven
|
|
78
112
|
|
|
79
113
|
```bash
|
|
80
|
-
|
|
81
|
-
npm
|
|
114
|
+
# bash / zsh / macOS
|
|
115
|
+
mkdir my-agent && cd my-agent && npm i @sail.money/sailor && npx sailor init && npm install
|
|
116
|
+
```
|
|
82
117
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
118
|
+
```powershell
|
|
119
|
+
# PowerShell (Windows)
|
|
120
|
+
mkdir my-agent ; cd my-agent ; npm i @sail.money/sailor ; npx sailor init ; npm install
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Open this folder in Claude Code, Cursor, Codex, or any AI coding assistant and say **"start"**. The scaffolded `AGENTS.md` guides the assistant through all five stages — SMA deployment, strategy definition, mandate authoring, running, and automation. No manual steps required.
|
|
86
124
|
|
|
87
|
-
|
|
88
|
-
# generate the agent key, deploy your SMA):
|
|
89
|
-
sailor ui start # open http://localhost:3333 and follow steps 1–4
|
|
125
|
+
### Direct CLI reference
|
|
90
126
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
sailor
|
|
127
|
+
```bash
|
|
128
|
+
# Discovery
|
|
129
|
+
sailor chains # list supported chains and kernel addresses
|
|
130
|
+
sailor capabilities # what you can build on this chain — read-only, no gas
|
|
131
|
+
sailor doctor # kernel model + RPC reachability + gas balances
|
|
132
|
+
|
|
133
|
+
# SMA setup
|
|
134
|
+
sailor account predict # compute deterministic SMA address before deploying
|
|
135
|
+
sailor onboard --new-sma # deploy SMA and optionally attach a mandate
|
|
136
|
+
|
|
137
|
+
# Mandate lifecycle
|
|
138
|
+
sailor mandate simulate # probe a permission off-chain (no gas) before registering
|
|
139
|
+
sailor mandate sign # sign the mandate — reconciles against live on-chain state
|
|
140
|
+
sailor mandate deploy # deploy a Foundry-compiled permission contract
|
|
141
|
+
sailor mandate attach # register an already-deployed permission on an SMA
|
|
142
|
+
|
|
143
|
+
# Agent operation
|
|
144
|
+
sailor run --once # single tick — confirm it works before automating
|
|
145
|
+
sailor run # start the agent (continuous)
|
|
146
|
+
sailor keys export-ci # copy encrypted agent wallet to ci-keystore.json for CI
|
|
147
|
+
|
|
148
|
+
# Dashboard
|
|
149
|
+
sailor ui start # open http://localhost:3333
|
|
94
150
|
```
|
|
95
151
|
|
|
96
|
-
|
|
97
|
-
terminal command — see the scaffolded project's `AGENTS.md` for the full 8-step flow.
|
|
152
|
+
`sailor run` writes reverted transactions to stderr as `reverted: <txHash> (gas used: N)`; successful dispatches are appended to `.sail/activity.jsonl`.
|
|
98
153
|
|
|
99
154
|
---
|
|
100
155
|
|
|
@@ -106,7 +161,7 @@ writes into the **current directory**; pass a name to create a subdirectory.
|
|
|
106
161
|
```bash
|
|
107
162
|
sailor init # scaffold into cwd
|
|
108
163
|
sailor init my-agent # create ./my-agent/ and scaffold there
|
|
109
|
-
sailor init --template
|
|
164
|
+
sailor init --template default # explicit (same as default)
|
|
110
165
|
sailor init my-agent --template <name> # named subdirectory + specific template
|
|
111
166
|
```
|
|
112
167
|
|
|
@@ -114,7 +169,7 @@ sailor init my-agent --template <name> # named subdirectory + specific templat
|
|
|
114
169
|
|
|
115
170
|
| Template | Description |
|
|
116
171
|
|---|---|
|
|
117
|
-
| `
|
|
172
|
+
| `default` | Neutral agent starter. Includes a blank agent loop, Foundry workspace for permission contracts, GitHub Actions cron job, and the operator guide (`AGENTS.md`). For a complete worked example see `examples/dca/`. **Default.** |
|
|
118
173
|
|
|
119
174
|
### What makes a valid template
|
|
120
175
|
|
|
@@ -182,20 +237,19 @@ sailor ui stop
|
|
|
182
237
|
|
|
183
238
|
## Agent-driven onboarding & custom mandates
|
|
184
239
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
browser, and the agent submits the transactions it's allowed to.
|
|
240
|
+
On any of the six supported chains, an agent can drive the whole setup through
|
|
241
|
+
a browser **signing station**. The station is a local HTTP + WebSocket daemon
|
|
242
|
+
that bridges the CLI and the owner's wallet: the agent never holds the owner
|
|
243
|
+
key — it pushes signing requests, the owner approves them in the browser, and
|
|
244
|
+
the agent submits the transactions it's allowed to.
|
|
191
245
|
|
|
192
246
|
```bash
|
|
193
|
-
sailor keys generate # manager (agent) key
|
|
194
|
-
sailor station start &
|
|
247
|
+
sailor keys generate # create the manager (agent) key
|
|
248
|
+
sailor station start & # signing daemon (serves the UI)
|
|
195
249
|
# owner opens the printed URL once and connects their wallet
|
|
196
|
-
sailor owner connect
|
|
197
|
-
sailor scan
|
|
198
|
-
sailor onboard --new-sma
|
|
250
|
+
sailor owner connect # detect & persist the owner
|
|
251
|
+
sailor scan # discover the owner's Safes + state
|
|
252
|
+
sailor onboard --new-sma # create an SMA + (optionally) attach a mandate
|
|
199
253
|
```
|
|
200
254
|
|
|
201
255
|
Agents author their own permission contracts and deploy them from the scaffolded
|
|
@@ -217,35 +271,98 @@ a `RegisterPermission` EIP-712 message, then the agent submits
|
|
|
217
271
|
`--json` for headless agent use; set `SAIL_PASSPHRASE` to unlock the manager key
|
|
218
272
|
non-interactively.
|
|
219
273
|
|
|
274
|
+
`sailor mandate sign` reconciles against the live on-chain `getPermissions()` call
|
|
275
|
+
before building the mandate payload — permissions revoked on-chain are excluded even
|
|
276
|
+
if they remain in the local `.sail/state/mandates.json` (which is an append-only
|
|
277
|
+
historical record and is never modified by the reconciliation).
|
|
278
|
+
|
|
279
|
+
### GitHub Actions CI
|
|
280
|
+
|
|
281
|
+
The scaffolded `.github/workflows/agent-tick.yml` runs `sailor run --once` on a
|
|
282
|
+
cron schedule using `npm ci` (no pnpm required). Setup:
|
|
283
|
+
|
|
284
|
+
1. `sailor keys export-ci` — copies the encrypted agent wallet to `ci-keystore.json`
|
|
285
|
+
in the project root and allowlists it in `.gitignore`. The geth v3 keystore is
|
|
286
|
+
safe to commit; the raw private key is never exposed.
|
|
287
|
+
2. Commit `ci-keystore.json`, `.sail/account.json`, and `.sail/mandate.json`.
|
|
288
|
+
3. Add two repository secrets (Settings → Secrets → Actions):
|
|
289
|
+
- `SAIL_PASSPHRASE` — the passphrase that encrypts the agent wallet
|
|
290
|
+
- `RPC_URL` — your RPC endpoint
|
|
291
|
+
|
|
292
|
+
The workflow copies `ci-keystore.json` to `.sail/keys/manager.json`, then calls
|
|
293
|
+
`npx sailor run --once` with `SAIL_PASSPHRASE` set so the key is unlocked
|
|
294
|
+
non-interactively. No private key ever appears in the workflow file or in secrets.
|
|
295
|
+
|
|
220
296
|
---
|
|
221
297
|
|
|
222
|
-
##
|
|
298
|
+
## Packages
|
|
299
|
+
|
|
300
|
+
Sailor ships as a **single npm package** — the SDK is bundled inside it and exposed via a subpath export:
|
|
301
|
+
|
|
302
|
+
| Package | Contents |
|
|
303
|
+
|---|---|
|
|
304
|
+
| `@sail.money/sailor` | CLI binary, UI server, templates, examples, and SDK |
|
|
305
|
+
|
|
306
|
+
The SDK is available as a subpath export for use in agent code:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
import type { Agent, AgentContext, Dispatch } from '@sail.money/sailor/sdk'
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
The SDK is also published separately as `@sail.money/sdk` for projects that consume it independently of the CLI.
|
|
313
|
+
|
|
314
|
+
### npm (`publish-npm.yml`)
|
|
315
|
+
|
|
316
|
+
Published to the public npm registry under the `@sail.money` scope.
|
|
223
317
|
|
|
318
|
+
| Trigger | Package | Version | dist-tag |
|
|
319
|
+
|---|---|---|---|
|
|
320
|
+
| Tag push (`v*`) | `@sail.money/sailor` | `0.1.0` | `latest` |
|
|
321
|
+
| Manual dispatch | `@dev.sail.money/sailor` | `0.1.0-42` | `dev` |
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
npm install @sail.money/sailor # latest stable (tag push)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
For dev builds, the package name changes scope to `@dev.sail.money`. Use an alias so your import paths stay the same:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
npm install "@sail.money/sailor@npm:@dev.sail.money/sailor@dev"
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
This installs the latest dev build and makes it available as `@sail.money/sailor` locally — `@sail.money/sailor/sdk` imports continue to work unchanged.
|
|
334
|
+
|
|
335
|
+
### GitHub Packages (`publish.yml`)
|
|
336
|
+
|
|
337
|
+
Published to GitHub Packages under the `@sail-money` scope for internal testing — no public npm registry required.
|
|
338
|
+
|
|
339
|
+
| Trigger | Package | dist-tag |
|
|
340
|
+
|---|---|---|
|
|
341
|
+
| Merge to `main` | `@sail-money/sailor` | `latest` |
|
|
342
|
+
| Manual dispatch | `@sail-money/sailor-dev` | `dev` |
|
|
343
|
+
|
|
344
|
+
Both builds require an alias since the package scope differs from `@sail.money`:
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
npm install "@sail.money/sailor@npm:@sail-money/sailor@latest" --registry https://npm.pkg.github.com
|
|
348
|
+
npm install "@sail.money/sailor@npm:@sail-money/sailor-dev@dev" --registry https://npm.pkg.github.com
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Or pin in `package.json`:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
"dependencies": {
|
|
355
|
+
"@sail.money/sailor": "npm:@sail-money/sailor@latest"
|
|
356
|
+
}
|
|
224
357
|
```
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
│ EIP-712 mandate │ dispatch
|
|
231
|
-
▼ ▼
|
|
232
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
233
|
-
│ SailKernel │
|
|
234
|
-
│ (Sail Protocol) │
|
|
235
|
-
└─────────┬───────────────────────┬───────────────────────┬───────────┘
|
|
236
|
-
│ │ │
|
|
237
|
-
│ registration │ execution │ evaluation
|
|
238
|
-
▼ ▼ ▼
|
|
239
|
-
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
|
|
240
|
-
│ MandateFactory │ │ Safe │ │ Permissions │
|
|
241
|
-
│ (register perms) │ │ (custody) │ │ (named, per-call) │
|
|
242
|
-
└────────────────────┘ └────────────────────┘ └────────────────────┘
|
|
243
|
-
|
|
244
|
-
sailor CLI / @sail/sdk drive both signing paths above.
|
|
245
|
-
.sail/ (account · mandate · activity) ──→ sailor-ui (localhost:3333)
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
"dependencies": {
|
|
361
|
+
"@sail.money/sailor": "npm:@sail-money/sailor-dev@dev"
|
|
362
|
+
}
|
|
246
363
|
```
|
|
247
364
|
|
|
248
|
-
|
|
365
|
+
Either way, `@sail.money/sailor/sdk` imports work unchanged.
|
|
249
366
|
|
|
250
367
|
---
|
|
251
368
|
|
|
@@ -255,74 +372,48 @@ The CLI and SDK sit between the operator and SailKernel: they build the EIP-712
|
|
|
255
372
|
- The Owner key controls the Safe and is never read by Sailor. Mandate signing requires a deliberate action by the permission signer.
|
|
256
373
|
- The manager key is encrypted on disk using geth keystore v3 (scrypt + aes-128-ctr) and is never transmitted.
|
|
257
374
|
- The session can be paused instantly via `sailor session pause` or the dashboard stop button; this does not affect Safe custody.
|
|
375
|
+
- All addresses passed to the CLI are normalized with `getAddress()` (EIP-55 checksum). Mixed-case or lowercase inputs are accepted and canonicalized before any on-chain call or state write.
|
|
258
376
|
|
|
259
377
|
---
|
|
260
378
|
|
|
261
379
|
## State of the project
|
|
262
380
|
|
|
263
|
-
Sailor is functional and published as [`@sail.money/sailor`](https://www.npmjs.com/package/@sail.money/sailor) on npm (v0.0
|
|
381
|
+
Sailor is functional and published as [`@sail.money/sailor`](https://www.npmjs.com/package/@sail.money/sailor) on npm (v0.1.0). The SDK, CLI, keystore, mandate flows, agent runner, and dashboard are implemented and have been exercised end to end.
|
|
382
|
+
|
|
383
|
+
The Sail Protocol trusted core is deployed on six chains — Ethereum, Base, Arbitrum, Unichain, Base Sepolia, and Eth Sepolia — via CREATE2, with every core contract at the same address on every chain. All six run the selective dispatch model with zero fees and are bootstrapped with a genesis allowlist so `createAccount` is usable immediately. These deployments are under an ongoing external audit by [Octane Security](https://octane.security) and are not final — do not use them with funds you are not prepared to lose.
|
|
264
384
|
|
|
265
|
-
|
|
385
|
+
Permission templates have not yet been deployed against the current kernel on any chain; `knownTemplates` and `standaloneTemplates` are empty for all six chains in `packages/sdk/src/deployments.ts` and will be populated as templates are deployed and verified against the new kernel.
|
|
266
386
|
|
|
267
387
|
---
|
|
268
388
|
|
|
269
389
|
## Deployments
|
|
270
390
|
|
|
271
|
-
|
|
391
|
+
All core contracts are deployed at the same address on every supported chain via CREATE2 (commit `1199b33`, 2026-06-09). An SMA created with the same owner, permission signer, manager, fee policy, and salt has the same address on every supported chain.
|
|
272
392
|
|
|
273
|
-
###
|
|
393
|
+
### Core addresses (identical on all 6 chains)
|
|
274
394
|
|
|
275
395
|
| Contract | Address |
|
|
276
396
|
|---|---|
|
|
277
|
-
| SailKernel | `
|
|
278
|
-
| SailGovernance | `
|
|
279
|
-
|
|
|
280
|
-
|
|
|
281
|
-
| StandardFeePolicy | `
|
|
282
|
-
| SafeModuleEnabler | `
|
|
397
|
+
| SailKernel | `0x02ABC18B65A328de2e749F56ba79ACF2718a6659` |
|
|
398
|
+
| SailGovernance | `0x7A478118715791728BDE3bc7A4D7ECfdEB89C6EC` |
|
|
399
|
+
| TimelockController | `0xE48Ba8DB6d748adafD13155c3590f62e58a77f56` |
|
|
400
|
+
| MandateFactory | `0x14EDd6c2a56EfC0d71E215ab13094B9AF90543d2` |
|
|
401
|
+
| StandardFeePolicy | `0xe7B5901b839cFFDEd9D4108A22712C8BfdA1D80D` |
|
|
402
|
+
| SafeModuleEnabler | `0x7897Cb53a4be4a2eaAf46D60573C4Fd83b33fE1F` |
|
|
283
403
|
| Treasury | `0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6` |
|
|
284
404
|
|
|
285
|
-
|
|
405
|
+
These addresses are bundled in `@sail.money/sailor` and exposed via `getSailDeployment(chainId)` in the SDK. The Protocol repository is the canonical source of truth for deployment details — see [deployments/addresses.md](https://github.com/sail-money/Protocol/blob/main/deployments/addresses.md).
|
|
286
406
|
|
|
287
|
-
|
|
288
|
-
|---|---|
|
|
289
|
-
| SailKernel | `0x2716B12832DED0EF5688519c5Fe069EFc0374E02` |
|
|
290
|
-
| SailGovernance | `0xd6AbB7A1036ADc7958Abffec9Da03450c5a2Ec8e` |
|
|
291
|
-
| Timelock | `0x114CB7110C780f7E3a6093AfE0B52463a569857C` |
|
|
292
|
-
| PermissionFactory | `0x23681A8A4C9819D8EaB37E46B858da6F3c85E683` |
|
|
293
|
-
| StandardFeePolicy | `0xAdfB986D48480bC67a7cF3751d30599161632e0D` |
|
|
294
|
-
| SafeModuleEnabler | `0xabe2a6D03F592BC602cA1dBDCD885ba2493274f9` |
|
|
295
|
-
| Treasury | `0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6` |
|
|
296
|
-
|
|
297
|
-
### Base Sepolia (84532)
|
|
407
|
+
### Supported chains
|
|
298
408
|
|
|
299
|
-
|
|
|
409
|
+
| Chain | Chain ID |
|
|
300
410
|
|---|---|
|
|
301
|
-
|
|
|
302
|
-
|
|
|
303
|
-
|
|
|
304
|
-
|
|
|
305
|
-
|
|
|
306
|
-
|
|
|
307
|
-
| Treasury | `0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6` |
|
|
308
|
-
|
|
309
|
-
### Unichain (130)
|
|
310
|
-
|
|
311
|
-
First chain to ship the full permission-template suite (7 shared + 12 standalone, source-verified on [uniscan.xyz](https://uniscan.xyz)). Genesis allowlist bootstrap — onboarding usable without the 48h timelock.
|
|
312
|
-
|
|
313
|
-
| Contract | Address |
|
|
314
|
-
|---|---|
|
|
315
|
-
| SailKernel | `0xD985029960a9B7C2E7E38e102C448b8b8539B156` |
|
|
316
|
-
| SailGovernance | `0xAb5C90ECfF2763f6f20f8E553E3b8778dD9C349A` |
|
|
317
|
-
| Timelock | `0xd44FbBB37f01e235E0EE5386948F216d36D0CEf2` |
|
|
318
|
-
| PermissionFactory | `0x8edDb62Aa49CeB837abf2653be2d93Ad9Fe6777D` |
|
|
319
|
-
| StandardFeePolicy | `0x7bBA8BE3c01c972757aA4a230A00D58aB600A1F1` |
|
|
320
|
-
| SafeModuleEnabler | `0xFE9227A9F2baf704060c604466df354a5A137b9B` |
|
|
321
|
-
| Treasury | `0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6` |
|
|
322
|
-
|
|
323
|
-
The 19 template addresses are in `@sail/sdk` (`knownTemplates` + `standaloneTemplates` for chain 130).
|
|
324
|
-
|
|
325
|
-
Addresses are sourced from `@sail/sdk` (`packages/sdk/src/deployments.ts`), the canonical registry.
|
|
411
|
+
| Ethereum | 1 |
|
|
412
|
+
| Base | 8453 |
|
|
413
|
+
| Arbitrum | 42161 |
|
|
414
|
+
| Unichain | 130 |
|
|
415
|
+
| Base Sepolia | 84532 |
|
|
416
|
+
| Eth Sepolia | 11155111 |
|
|
326
417
|
|
|
327
418
|
---
|
|
328
419
|
|