@dev.sail.money/sailor 0.0.2

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.
Files changed (319) hide show
  1. package/AGENTS.md +111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +337 -0
  4. package/docs/PERMISSION_MODEL.md +93 -0
  5. package/examples/permissions/BoundedBet_Limitless_Base.sol +96 -0
  6. package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +94 -0
  7. package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +143 -0
  8. package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +113 -0
  9. package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +144 -0
  10. package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +73 -0
  11. package/examples/permissions/README.md +52 -0
  12. package/examples/permissions/foundry.toml +10 -0
  13. package/examples/permissions/interfaces/IPermission.sol +18 -0
  14. package/package.json +39 -0
  15. package/packages/cli/README.md +34 -0
  16. package/packages/cli/dist/index.cjs +42801 -0
  17. package/packages/cli/dist/server.cjs +51202 -0
  18. package/packages/sdk/README.md +65 -0
  19. package/packages/sdk/dist/abis/MandateFactory.d.ts +140 -0
  20. package/packages/sdk/dist/abis/MandateFactory.d.ts.map +1 -0
  21. package/packages/sdk/dist/abis/MandateFactory.js +93 -0
  22. package/packages/sdk/dist/abis/MandateFactory.js.map +1 -0
  23. package/packages/sdk/dist/abis/SailGovernance.d.ts +57 -0
  24. package/packages/sdk/dist/abis/SailGovernance.d.ts.map +1 -0
  25. package/packages/sdk/dist/abis/SailGovernance.js +52 -0
  26. package/packages/sdk/dist/abis/SailGovernance.js.map +1 -0
  27. package/packages/sdk/dist/abis/SailKernel.d.ts +466 -0
  28. package/packages/sdk/dist/abis/SailKernel.d.ts.map +1 -0
  29. package/packages/sdk/dist/abis/SailKernel.js +311 -0
  30. package/packages/sdk/dist/abis/SailKernel.js.map +1 -0
  31. package/packages/sdk/dist/abis/index.d.ts +4 -0
  32. package/packages/sdk/dist/abis/index.d.ts.map +1 -0
  33. package/packages/sdk/dist/abis/index.js +7 -0
  34. package/packages/sdk/dist/abis/index.js.map +1 -0
  35. package/packages/sdk/dist/capabilities.d.ts +77 -0
  36. package/packages/sdk/dist/capabilities.d.ts.map +1 -0
  37. package/packages/sdk/dist/capabilities.js +158 -0
  38. package/packages/sdk/dist/capabilities.js.map +1 -0
  39. package/packages/sdk/dist/client.d.ts +37 -0
  40. package/packages/sdk/dist/client.d.ts.map +1 -0
  41. package/packages/sdk/dist/client.js +646 -0
  42. package/packages/sdk/dist/client.js.map +1 -0
  43. package/packages/sdk/dist/deployments.d.ts +82 -0
  44. package/packages/sdk/dist/deployments.d.ts.map +1 -0
  45. package/packages/sdk/dist/deployments.js +197 -0
  46. package/packages/sdk/dist/deployments.js.map +1 -0
  47. package/packages/sdk/dist/discovery.d.ts +10 -0
  48. package/packages/sdk/dist/discovery.d.ts.map +1 -0
  49. package/packages/sdk/dist/discovery.js +41 -0
  50. package/packages/sdk/dist/discovery.js.map +1 -0
  51. package/packages/sdk/dist/eip712.d.ts +257 -0
  52. package/packages/sdk/dist/eip712.d.ts.map +1 -0
  53. package/packages/sdk/dist/eip712.js +255 -0
  54. package/packages/sdk/dist/eip712.js.map +1 -0
  55. package/packages/sdk/dist/errors.d.ts +47 -0
  56. package/packages/sdk/dist/errors.d.ts.map +1 -0
  57. package/packages/sdk/dist/errors.js +168 -0
  58. package/packages/sdk/dist/errors.js.map +1 -0
  59. package/packages/sdk/dist/fees.d.ts +16 -0
  60. package/packages/sdk/dist/fees.d.ts.map +1 -0
  61. package/packages/sdk/dist/fees.js +51 -0
  62. package/packages/sdk/dist/fees.js.map +1 -0
  63. package/packages/sdk/dist/index.d.ts +23 -0
  64. package/packages/sdk/dist/index.d.ts.map +1 -0
  65. package/packages/sdk/dist/index.js +16 -0
  66. package/packages/sdk/dist/index.js.map +1 -0
  67. package/packages/sdk/dist/intelligence.d.ts +923 -0
  68. package/packages/sdk/dist/intelligence.d.ts.map +1 -0
  69. package/packages/sdk/dist/intelligence.js +357 -0
  70. package/packages/sdk/dist/intelligence.js.map +1 -0
  71. package/packages/sdk/dist/keyring.d.ts +60 -0
  72. package/packages/sdk/dist/keyring.d.ts.map +1 -0
  73. package/packages/sdk/dist/keyring.js +159 -0
  74. package/packages/sdk/dist/keyring.js.map +1 -0
  75. package/packages/sdk/dist/lifi.d.ts +83 -0
  76. package/packages/sdk/dist/lifi.d.ts.map +1 -0
  77. package/packages/sdk/dist/lifi.js +69 -0
  78. package/packages/sdk/dist/lifi.js.map +1 -0
  79. package/packages/sdk/dist/safe.d.ts +158 -0
  80. package/packages/sdk/dist/safe.d.ts.map +1 -0
  81. package/packages/sdk/dist/safe.js +163 -0
  82. package/packages/sdk/dist/safe.js.map +1 -0
  83. package/packages/sdk/dist/signing.d.ts +106 -0
  84. package/packages/sdk/dist/signing.d.ts.map +1 -0
  85. package/packages/sdk/dist/signing.js +2 -0
  86. package/packages/sdk/dist/signing.js.map +1 -0
  87. package/packages/sdk/dist/templates/ammLiquidity.d.ts +16 -0
  88. package/packages/sdk/dist/templates/ammLiquidity.d.ts.map +1 -0
  89. package/packages/sdk/dist/templates/ammLiquidity.js +60 -0
  90. package/packages/sdk/dist/templates/ammLiquidity.js.map +1 -0
  91. package/packages/sdk/dist/templates/approveAndCallBatch.d.ts +14 -0
  92. package/packages/sdk/dist/templates/approveAndCallBatch.d.ts.map +1 -0
  93. package/packages/sdk/dist/templates/approveAndCallBatch.js +53 -0
  94. package/packages/sdk/dist/templates/approveAndCallBatch.js.map +1 -0
  95. package/packages/sdk/dist/templates/boundedBorrow.d.ts +16 -0
  96. package/packages/sdk/dist/templates/boundedBorrow.d.ts.map +1 -0
  97. package/packages/sdk/dist/templates/boundedBorrow.js +56 -0
  98. package/packages/sdk/dist/templates/boundedBorrow.js.map +1 -0
  99. package/packages/sdk/dist/templates/boundedSwap.d.ts +16 -0
  100. package/packages/sdk/dist/templates/boundedSwap.d.ts.map +1 -0
  101. package/packages/sdk/dist/templates/boundedSwap.js +56 -0
  102. package/packages/sdk/dist/templates/boundedSwap.js.map +1 -0
  103. package/packages/sdk/dist/templates/defiBundle.d.ts +14 -0
  104. package/packages/sdk/dist/templates/defiBundle.d.ts.map +1 -0
  105. package/packages/sdk/dist/templates/defiBundle.js +52 -0
  106. package/packages/sdk/dist/templates/defiBundle.js.map +1 -0
  107. package/packages/sdk/dist/templates/index.d.ts +15 -0
  108. package/packages/sdk/dist/templates/index.d.ts.map +1 -0
  109. package/packages/sdk/dist/templates/index.js +8 -0
  110. package/packages/sdk/dist/templates/index.js.map +1 -0
  111. package/packages/sdk/dist/templates/pendle.d.ts +14 -0
  112. package/packages/sdk/dist/templates/pendle.d.ts.map +1 -0
  113. package/packages/sdk/dist/templates/pendle.js +52 -0
  114. package/packages/sdk/dist/templates/pendle.js.map +1 -0
  115. package/packages/sdk/dist/templates/transferTarget.d.ts +10 -0
  116. package/packages/sdk/dist/templates/transferTarget.d.ts.map +1 -0
  117. package/packages/sdk/dist/templates/transferTarget.js +42 -0
  118. package/packages/sdk/dist/templates/transferTarget.js.map +1 -0
  119. package/packages/sdk/dist/types.d.ts +382 -0
  120. package/packages/sdk/dist/types.d.ts.map +1 -0
  121. package/packages/sdk/dist/types.js +2 -0
  122. package/packages/sdk/dist/types.js.map +1 -0
  123. package/packages/sdk/package.json +52 -0
  124. package/packages/ui/dist/assets/Arc-VDBY7LNS-BChRXCXW.js +1 -0
  125. package/packages/ui/dist/assets/Brave-BRAKJXDS-mq-Xo37j.js +1 -0
  126. package/packages/ui/dist/assets/Browser-76IHF3Y2-BMhRaC5Z.js +1 -0
  127. package/packages/ui/dist/assets/Chrome-65Q5P54Y-DR9MQEVr.js +1 -0
  128. package/packages/ui/dist/assets/Edge-XSPUTORV-DEoZslQE.js +1 -0
  129. package/packages/ui/dist/assets/Firefox-AAHGJQIP-Bp_Hm04m.js +1 -0
  130. package/packages/ui/dist/assets/Linux-OO4TNCLJ-B0aw93n9.js +1 -0
  131. package/packages/ui/dist/assets/Macos-MW4AE7LN-Vvm8Drw3.js +1 -0
  132. package/packages/ui/dist/assets/Opera-KQZLSACL-Cwv5MDFy.js +1 -0
  133. package/packages/ui/dist/assets/Safari-ZPL37GXR-C4Ggg6rz.js +1 -0
  134. package/packages/ui/dist/assets/Windows-PPTHQER6-BlyV2p7Y.js +1 -0
  135. package/packages/ui/dist/assets/add-DaJhwIBV.js +15 -0
  136. package/packages/ui/dist/assets/all-wallets-BUxsqWXi.js +6 -0
  137. package/packages/ui/dist/assets/apechain-SX5YFU6N-q5qBv-mp.js +1 -0
  138. package/packages/ui/dist/assets/app-store-DkltwTqE.js +17 -0
  139. package/packages/ui/dist/assets/apple-owVOeaIT.js +18 -0
  140. package/packages/ui/dist/assets/ar_AR-LIPSOZP5-BQrIDibT.js +1519 -0
  141. package/packages/ui/dist/assets/arbitrum-WURIBY6W-CqVkHBr5.js +1 -0
  142. package/packages/ui/dist/assets/arrow-bottom-D2mmNJve.js +8 -0
  143. package/packages/ui/dist/assets/arrow-bottom-circle-CbNYijx-.js +11 -0
  144. package/packages/ui/dist/assets/arrow-left-DJB61s4C.js +8 -0
  145. package/packages/ui/dist/assets/arrow-right-BBrsQ9R4.js +8 -0
  146. package/packages/ui/dist/assets/arrow-top-Cil6bOc8.js +8 -0
  147. package/packages/ui/dist/assets/assets-Q6ZU7ZJ5-P8HioiAD.js +1 -0
  148. package/packages/ui/dist/assets/avalanche-KOMJD3XY-Dsn_JPR4.js +1 -0
  149. package/packages/ui/dist/assets/bank-CbwEmRo3.js +14 -0
  150. package/packages/ui/dist/assets/base-OAXLRA4F-CoYTVIiL.js +1 -0
  151. package/packages/ui/dist/assets/base-QS6CYWIN-CsjdbWCf.js +1 -0
  152. package/packages/ui/dist/assets/basic-CLNfjw3m.js +2128 -0
  153. package/packages/ui/dist/assets/berachain-NJECWIVC-DumxnFvf.js +1 -0
  154. package/packages/ui/dist/assets/blast-V555OVXZ-BbhJh1tj.js +1 -0
  155. package/packages/ui/dist/assets/browser-B5TtF4Pb.js +14 -0
  156. package/packages/ui/dist/assets/bsc-N647EYR2-B2nLKXWV.js +1 -0
  157. package/packages/ui/dist/assets/card-CO7BVB-C.js +14 -0
  158. package/packages/ui/dist/assets/ccip-2W7K3_J3.js +1 -0
  159. package/packages/ui/dist/assets/celo-GEP4TUHG-CenIBYLU.js +1 -0
  160. package/packages/ui/dist/assets/checkmark-BEtSHq9m.js +11 -0
  161. package/packages/ui/dist/assets/checkmark-bold-D9xGHzPE.js +8 -0
  162. package/packages/ui/dist/assets/chevron-bottom-BDztht6i.js +8 -0
  163. package/packages/ui/dist/assets/chevron-left-EV4GFNbc.js +8 -0
  164. package/packages/ui/dist/assets/chevron-right-B4_bB9oR.js +8 -0
  165. package/packages/ui/dist/assets/chevron-top-D54xPNzF.js +8 -0
  166. package/packages/ui/dist/assets/chrome-store-DYUpAJJq.js +61 -0
  167. package/packages/ui/dist/assets/clock-Ca1T1Soz.js +8 -0
  168. package/packages/ui/dist/assets/close-BZqWjurK.js +8 -0
  169. package/packages/ui/dist/assets/coinPlaceholder-e6fl2XDo.js +8 -0
  170. package/packages/ui/dist/assets/compass-DCLC7zIh.js +8 -0
  171. package/packages/ui/dist/assets/connect-UA7M4XW6-IY3X6Bmr.js +1 -0
  172. package/packages/ui/dist/assets/copy-Th2AaD-O.js +15 -0
  173. package/packages/ui/dist/assets/core-Ckx_cyuH.js +907 -0
  174. package/packages/ui/dist/assets/create-FASO7PVG-D_rvSpre.js +1 -0
  175. package/packages/ui/dist/assets/cronos-HJPAQTAE-BEOvlOC4.js +1 -0
  176. package/packages/ui/dist/assets/cursor-DV7rOqbJ.js +3 -0
  177. package/packages/ui/dist/assets/cursor-transparent-BKHeABKB.js +12 -0
  178. package/packages/ui/dist/assets/de_DE-YE3KOFHU-BRt5ztUe.js +1519 -0
  179. package/packages/ui/dist/assets/degen-FQQ4XGHB-CeHTs88l.js +1 -0
  180. package/packages/ui/dist/assets/desktop-CBjY8t6F.js +9 -0
  181. package/packages/ui/dist/assets/disconnect-DbSs2cli.js +8 -0
  182. package/packages/ui/dist/assets/discord-ZlLOAUkM.js +17 -0
  183. package/packages/ui/dist/assets/es_419-7LMPU7G4-DH7rM0yQ.js +1519 -0
  184. package/packages/ui/dist/assets/ethereum-RGGVA4PY-SWGOlkuk.js +1 -0
  185. package/packages/ui/dist/assets/etherscan-CKUrqWYN.js +6 -0
  186. package/packages/ui/dist/assets/events-CiKP71cK.js +1 -0
  187. package/packages/ui/dist/assets/exclamation-triangle-DA1QzFiO.js +4 -0
  188. package/packages/ui/dist/assets/extension-BVJkmvpJ.js +8 -0
  189. package/packages/ui/dist/assets/external-link-D_bsR7B2.js +8 -0
  190. package/packages/ui/dist/assets/facebook-CmFmhojx.js +26 -0
  191. package/packages/ui/dist/assets/fallback-Ofl6uSnB.js +1 -0
  192. package/packages/ui/dist/assets/farcaster-Co-M3Ss8.js +12 -0
  193. package/packages/ui/dist/assets/filters-B1WwNaFU.js +8 -0
  194. package/packages/ui/dist/assets/flow-5FQJFCTK-CUie2reO.js +1 -0
  195. package/packages/ui/dist/assets/fr_FR-VBJP3ZLL-B-_ocunw.js +1519 -0
  196. package/packages/ui/dist/assets/github-CP4fP6gn.js +18 -0
  197. package/packages/ui/dist/assets/gnosis-37ZC4RBL-B137OtHZ.js +1 -0
  198. package/packages/ui/dist/assets/google-CsOIXJ6V.js +18 -0
  199. package/packages/ui/dist/assets/gravity-J5YQHTYH-Bj6B0uod.js +1 -0
  200. package/packages/ui/dist/assets/hardhat-TX56IT5N-CV1FY-wE.js +1 -0
  201. package/packages/ui/dist/assets/help-circle-DiMkomdF.js +12 -0
  202. package/packages/ui/dist/assets/hi_IN-WBVD5XYI-D73g2UFs.js +1519 -0
  203. package/packages/ui/dist/assets/hyperevm-VKPAA4SA-CHwraEsx.js +1 -0
  204. package/packages/ui/dist/assets/id-lmscL5LX.js +12 -0
  205. package/packages/ui/dist/assets/id_ID-SBYANJ7G-Cjpa4ay6.js +1519 -0
  206. package/packages/ui/dist/assets/image-B-ubJrY5.js +4 -0
  207. package/packages/ui/dist/assets/index-BaukYv-x.js +16 -0
  208. package/packages/ui/dist/assets/index-CF0KMmke.js +395 -0
  209. package/packages/ui/dist/assets/index-CKxgNxS9.css +1 -0
  210. package/packages/ui/dist/assets/index-CZR1Qjhs.js +1 -0
  211. package/packages/ui/dist/assets/index-DVgfCzCo.js +1 -0
  212. package/packages/ui/dist/assets/index-Dbh5V1Z0.js +1 -0
  213. package/packages/ui/dist/assets/index-Q2Yai4Fe.js +2103 -0
  214. package/packages/ui/dist/assets/index.es-C78cE5SI.js +26 -0
  215. package/packages/ui/dist/assets/info-Cqg57EVo.js +3 -0
  216. package/packages/ui/dist/assets/info-circle-DkeSWNKV.js +12 -0
  217. package/packages/ui/dist/assets/ink-FZMYZWHG-62p-5IK5.js +1 -0
  218. package/packages/ui/dist/assets/ja_JP-ZRMWJV3I-DXbifiMm.js +1519 -0
  219. package/packages/ui/dist/assets/kaia-65D2U3PU-JmuLQ4gC.js +1 -0
  220. package/packages/ui/dist/assets/ko_KR-FR54RFUG-upinSHjQ.js +1519 -0
  221. package/packages/ui/dist/assets/lightbulb-DNlO4qKh.js +3 -0
  222. package/packages/ui/dist/assets/linea-QRMVQ5DY-DuI3vv0d.js +1 -0
  223. package/packages/ui/dist/assets/login-UP3DZBGS-Db_wM5oQ.js +1 -0
  224. package/packages/ui/dist/assets/mail-kVQ8Jb9Y.js +8 -0
  225. package/packages/ui/dist/assets/manta-SI27YFEJ-CpVOKa06.js +1 -0
  226. package/packages/ui/dist/assets/mantle-CKIUT334-DR2WgqzU.js +1 -0
  227. package/packages/ui/dist/assets/metaMaskWallet-EI6MED72-D5HFOsnz.js +1 -0
  228. package/packages/ui/dist/assets/metamask-sdk-CBalSvz7.js +542 -0
  229. package/packages/ui/dist/assets/mobile-BEteuhF7.js +9 -0
  230. package/packages/ui/dist/assets/monad-4KWC6TSS-DVXSkpiz.js +1 -0
  231. package/packages/ui/dist/assets/more-DBWmXQli.js +11 -0
  232. package/packages/ui/dist/assets/ms_MY-EZSGYYYQ-4cPLK-3L.js +1519 -0
  233. package/packages/ui/dist/assets/native-CJ5et6AR.js +1 -0
  234. package/packages/ui/dist/assets/network-placeholder-Dg1uUHiL.js +14 -0
  235. package/packages/ui/dist/assets/nftPlaceholder-i3AHSiD9.js +8 -0
  236. package/packages/ui/dist/assets/off-BtMm0fi2.js +8 -0
  237. package/packages/ui/dist/assets/optimism-HAF2GUT7-ec6Nqxs9.js +1 -0
  238. package/packages/ui/dist/assets/parseSignature-Cb5FlWWg.js +1 -0
  239. package/packages/ui/dist/assets/play-store-iKKkXa6a.js +32 -0
  240. package/packages/ui/dist/assets/plus-CA5NaRtb.js +13 -0
  241. package/packages/ui/dist/assets/polygon-WW6ZI7PM-DXlmm4L1.js +1 -0
  242. package/packages/ui/dist/assets/pt_BR-JQFQ3P4L-DOHfdcA2.js +1519 -0
  243. package/packages/ui/dist/assets/qr-code-D2kiqR7h.js +6 -0
  244. package/packages/ui/dist/assets/rainbowWallet-O26YNBMX-DUhYus-9.js +1 -0
  245. package/packages/ui/dist/assets/recycle-horizontal-Dcme7R03.js +9 -0
  246. package/packages/ui/dist/assets/refresh-Dega3sDp.js +8 -0
  247. package/packages/ui/dist/assets/refresh-S4T5V5GX-CwqIaaxK.js +1 -0
  248. package/packages/ui/dist/assets/reown-logo-xNkksyWJ.js +12 -0
  249. package/packages/ui/dist/assets/ronin-EMCPYXZT-N-QBHZdV.js +1 -0
  250. package/packages/ui/dist/assets/ru_RU-Z42UEJBP-Cvb2oWxQ.js +1519 -0
  251. package/packages/ui/dist/assets/safeWallet-5MNKTR5Z-D-5imDLD.js +1 -0
  252. package/packages/ui/dist/assets/sanko-RHQYXGM5-OX010CbN.js +1 -0
  253. package/packages/ui/dist/assets/scan-4UYSQ56Q-CjMz6-XC.js +1 -0
  254. package/packages/ui/dist/assets/scroll-5OBGQVOV-DJFECiai.js +1 -0
  255. package/packages/ui/dist/assets/search-HYl7NO8x.js +8 -0
  256. package/packages/ui/dist/assets/secp256k1-Cxd6_SiH.js +1 -0
  257. package/packages/ui/dist/assets/send-CJU8CUAo.js +15 -0
  258. package/packages/ui/dist/assets/sign-A7IJEUT5-CGsRnPrd.js +1 -0
  259. package/packages/ui/dist/assets/superposition-HG6MMR2Y-bRkgatRO.js +1 -0
  260. package/packages/ui/dist/assets/swapHorizontal-IMUKiUre.js +8 -0
  261. package/packages/ui/dist/assets/swapHorizontalBold-CNYnNJ9-.js +8 -0
  262. package/packages/ui/dist/assets/swapHorizontalMedium-B9VxEYsT.js +16 -0
  263. package/packages/ui/dist/assets/swapHorizontalRoundedBold-Dz33l_Jh.js +8 -0
  264. package/packages/ui/dist/assets/swapVertical-CHUmjVJ0.js +8 -0
  265. package/packages/ui/dist/assets/telegram-kl9S2mbU.js +16 -0
  266. package/packages/ui/dist/assets/th_TH-4YB4VSB2-BUipNP-V.js +1519 -0
  267. package/packages/ui/dist/assets/three-dots-U5lhA1Am.js +5 -0
  268. package/packages/ui/dist/assets/tr_TR-5FKHPPIO-D5jTpIm9.js +1519 -0
  269. package/packages/ui/dist/assets/twitch-KTEUWXEp.js +18 -0
  270. package/packages/ui/dist/assets/twitterIcon-BHiq8mRg.js +6 -0
  271. package/packages/ui/dist/assets/uk_UA-ZD4IBC52-DgnQrpzl.js +1519 -0
  272. package/packages/ui/dist/assets/unichain-C5BWO2ZY-BfguYsnu.js +1 -0
  273. package/packages/ui/dist/assets/verify-CfN-BXNd.js +8 -0
  274. package/packages/ui/dist/assets/verify-filled-DwZccetj.js +8 -0
  275. package/packages/ui/dist/assets/vi_VN-5EVRZKLY-x078672g.js +1519 -0
  276. package/packages/ui/dist/assets/w3m-modal-CS-PFqPE.js +642 -0
  277. package/packages/ui/dist/assets/wallet-DVlGkhOY.js +8 -0
  278. package/packages/ui/dist/assets/wallet-placeholder-CvR_iEWX.js +14 -0
  279. package/packages/ui/dist/assets/walletConnectWallet-YHWKVTDY-D3lyiczV.js +1 -0
  280. package/packages/ui/dist/assets/walletconnect-8pZBDvVI.js +30 -0
  281. package/packages/ui/dist/assets/warning-circle-ylLEE0Yp.js +12 -0
  282. package/packages/ui/dist/assets/x-C_TBsTMj.js +12 -0
  283. package/packages/ui/dist/assets/xdc-KJ3TDBYO-DNV6zchh.js +1 -0
  284. package/packages/ui/dist/assets/zetachain-TLDS5IPW-Udhyw16T.js +1 -0
  285. package/packages/ui/dist/assets/zh_CN-4XK5YJPR-Bt6Yz5Ek.js +1519 -0
  286. package/packages/ui/dist/assets/zh_HK-N4YN2WSI-Cvzl1V16.js +1519 -0
  287. package/packages/ui/dist/assets/zh_TW-CNCRXH6Z-BNelatfN.js +1519 -0
  288. package/packages/ui/dist/assets/zksync-DH7HK5U4-Dt4usFw6.js +1 -0
  289. package/packages/ui/dist/assets/zora-FYL5H3IO-iB4wygST.js +1 -0
  290. package/packages/ui/dist/index.html +14 -0
  291. package/scripts/check-docs.mjs +262 -0
  292. package/scripts/check-init.mjs +109 -0
  293. package/scripts/postinstall.js +366 -0
  294. package/templates/custom-mandate/.sail/contracts/interfaces/IPermission.sol +18 -0
  295. package/templates/custom-mandate/README.md +85 -0
  296. package/templates/custom-mandate/foundry.toml +8 -0
  297. package/templates/custom-mandate/mandates/BoundedCallPermission.sol +35 -0
  298. package/templates/custom-mandate/mandates/README.md +16 -0
  299. package/templates/dca-rebalancer/.cursor/rules +25 -0
  300. package/templates/dca-rebalancer/.env.example +6 -0
  301. package/templates/dca-rebalancer/.github/workflows/agent-tick.yml +32 -0
  302. package/templates/dca-rebalancer/.sail/.gitkeep +0 -0
  303. package/templates/dca-rebalancer/.sail/README.md +13 -0
  304. package/templates/dca-rebalancer/.sail/config.json +10 -0
  305. package/templates/dca-rebalancer/AGENTS.md +246 -0
  306. package/templates/dca-rebalancer/AGENT_PLAYBOOK.md +110 -0
  307. package/templates/dca-rebalancer/CLAUDE.md +2 -0
  308. package/templates/dca-rebalancer/README.md +16 -0
  309. package/templates/dca-rebalancer/_gitignore +13 -0
  310. package/templates/dca-rebalancer/docs/PERMISSION_MODEL.md +93 -0
  311. package/templates/dca-rebalancer/package.json +17 -0
  312. package/templates/dca-rebalancer/src/agent.ts +253 -0
  313. package/templates/dca-rebalancer/src/config.ts +27 -0
  314. package/templates/dca-rebalancer/src/mandate.ts +67 -0
  315. package/templates/dca-rebalancer/tsconfig.json +8 -0
  316. package/templates/dca-rebalancer/ui/README.md +3 -0
  317. package/templates/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +84 -0
  318. package/templates/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +97 -0
  319. package/templates/lifi-permissions/README.md +53 -0
package/AGENTS.md ADDED
@@ -0,0 +1,111 @@
1
+ # Sailor — Codebase Guide
2
+
3
+ Sailor is the operator toolkit for Sail Protocol. It does **not** deploy the protocol or author
4
+ permission templates — it targets already-deployed SailKernel instances and gives operators the
5
+ tooling to create SMAs, register permission contracts, and run strategy agents.
6
+
7
+ ## Repo structure
8
+
9
+ | Package / path | Name | Role |
10
+ |---|---|---|
11
+ | `packages/sdk` | `@sail/sdk` | SailorClient, LocalKeyring, kernel ABIs, EIP-712 builders, deployment registry |
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
+ | `packages/ui` | `sailor-ui` | Local dashboard + browser-driven onboarding wizard at localhost:3333 |
15
+ | `templates/dca-rebalancer` | — | Default project scaffold: DCA rebalancer + Foundry workspace |
16
+ | `templates/custom-mandate` | — | Solidity reference: IPermission scaffold (not a project template) |
17
+
18
+ ## Protocol roles
19
+
20
+ The code uses internal identifiers that differ from user-facing terms:
21
+
22
+ | User-facing term | Code identifier | Meaning |
23
+ |---|---|---|
24
+ | Owner | `owner` | Holds the Safe; custody anchor; never touches the agent runtime |
25
+ | Mandate signer | `permissionSigner` | Authorizes permission registration via EIP-712 |
26
+ | Agent wallet | `manager` | Signs dispatches; key at `.sail/keys/manager.json` |
27
+
28
+ Use the user-facing terms in all CLI output, prompts, and errors. The code identifiers are internal.
29
+
30
+ ## Dispatch model
31
+
32
+ Active kernels vary by chain — verified on-chain via `DISPATCH_TYPEHASH()`:
33
+
34
+ | Chain | Kernel | Model | DISPATCH_TYPEHASH |
35
+ |---|---|---|---|
36
+ | Base 8453 | `0x6319d3dfDDe3804ba93D65752b00c52bFb05a1ab` | **selective** | `0xbe50c539...` |
37
+ | Base Sepolia 84532 | `0xf1D0F4C9893612627409948BAa9d82a01a373799` | **selective** | `0xbe50c539...` |
38
+ | Arbitrum 42161 | `0x2716B12832DED0EF5688519c5Fe069EFc0374E02` | **selective** | `0xbe50c539...` |
39
+ | Unichain 130 | `0xD985029960a9B7C2E7E38e102C448b8b8539B156` | **selective** | `0xbe50c539...` |
40
+
41
+ All four kernels are live and bootstrapped (genesis allowlist set, `createAccount` verified working, zero fees). Unichain (130) additionally has the full permission-template suite deployed and source-verified (7 shared + 12 standalone) — it is the only chain with templates so far; the other three have core only. `packages/sdk/src/deployments.ts` is the canonical source of truth for kernel addresses, templates, and metadata.
42
+
43
+ **Always use `detectKernelCapabilities` for the real model** — it reads the on-chain typehash and
44
+ overrides the static label in `deployments.ts`. The static label is a fallback for offline use only.
45
+
46
+ Type strings:
47
+ ```
48
+ conjunctive: Dispatch(address account,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
49
+ selective: Dispatch(address account,address permission,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)
50
+
51
+ conjunctive RegisterPermission: RegisterPermission(address account,address permission,uint256 nonce)
52
+ selective RegisterPermission: RegisterPermission(address account,address permission,uint256 nonce,uint256 deadline)
53
+ ```
54
+
55
+ `buildRegisterPermissionTypedData` accepts `hasDeadline` from `KernelCapabilities.registerPermissionHasDeadline`.
56
+ Pass the detected value — never hardcode the type shape.
57
+
58
+ ## Active addresses
59
+
60
+ All four chain records in `packages/sdk/src/deployments.ts` are live — no commented-out or pending
61
+ addresses remain. This file is the source of truth this guide mirrors.
62
+
63
+ - `packages/sdk/src/deployments.ts` — `SailDeployment` records; canonical source of truth
64
+ - `packages/chains/src/index.ts` — `ChainConfig` per chainId; kept in sync with deployments
65
+
66
+ ## Key files
67
+
68
+ | File | What it owns |
69
+ |---|---|
70
+ | `packages/sdk/src/deployments.ts` | Active + PENDING addresses, `dispatchModel` per chain |
71
+ | `packages/sdk/src/capabilities.ts` | On-chain typehash detection; capability cache |
72
+ | `packages/sdk/src/eip712.ts` | `buildRegisterPermissionTypedData`, `REGISTER_PERMISSION_TYPES` |
73
+ | `packages/cli/src/commands/onboard.ts` | SMA creation + permission registration flow |
74
+ | `packages/cli/src/commands/mandate-contracts.ts` | Deploy / attach / revoke permission contracts |
75
+ | `packages/cli/src/lib/mandates.ts` | `MandateStore` — `.sail/state/mandates.json` source of truth |
76
+ | `packages/ui/server.js` | Local API + WebSocket proxy; signing station relay |
77
+
78
+ ## Build
79
+
80
+ ```bash
81
+ pnpm install
82
+ pnpm build # builds all packages; dependency order: sdk → chains → cli → ui
83
+ ```
84
+
85
+ Build order matters — `cli` imports from `sdk` and `chains`.
86
+
87
+ ## Test
88
+
89
+ ```bash
90
+ pnpm test # vitest — no chain needed, ~1.3s
91
+ pnpm test:ui # playwright — requires pnpm build first
92
+ ```
93
+
94
+ Test fixtures live in `packages/ui/test/fixtures/` — isolated directories with pre-canned `.sail/`
95
+ state; no real RPC needed.
96
+
97
+ ## Conventions
98
+
99
+ - `SAIL_DIR` — env var pointing to the project's `.sail/` directory (used by the UI server)
100
+ - `SAIL_PASSPHRASE` — unlocks `.sail/keys/manager.json` headlessly; read from `.sail/.env.local`
101
+ - `SERVE_DIST=1` — makes the UI server serve the built React app at `/`
102
+ - All CLI commands support `--json` for machine-readable output
103
+ - Addresses in `.sail/` files stored checksummed; bigints as decimal strings
104
+
105
+ ## What NOT to do
106
+
107
+ - Do not change active kernel/mandateFactory/governance addresses without confirming on-chain state
108
+ - Do not use conjunctive EIP-712 type strings in new code
109
+ - Do not add new root-level markdown files to this repo
110
+ - Always run `pnpm build` before `pnpm test:ui`
111
+ - Do not commit `SAIL_PASSPHRASE` or private keys
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alejandro Dopico
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,337 @@
1
+ # Sailor
2
+
3
+ > A toolkit for building and operating Sail Protocol SMAs with AI agents.
4
+
5
+ Sailor is the operator layer for [Sail Protocol](../SailProtocol): the tooling an agent builder uses to create a Separately Managed Account, bound it with permissions, and run a strategy against it. It wraps the on-chain primitives — SailKernel dispatch, MandateFactory registration, EIP-712 mandate signing — behind a TypeScript SDK, a CLI, and a local dashboard. An agent is an async function that receives context and returns intended transactions; Sailor previews each through the kernel, executes the approved ones, and records what happened. It does not deploy the protocol or author new permission templates — that lives in Sail Protocol. It sits one level up: turning a deployed SailKernel into something an operator can actually drive.
6
+
7
+ ---
8
+
9
+ ## What's inside
10
+
11
+ | Package | Name | Role |
12
+ |---|---|---|
13
+ | `packages/sdk` | `@sail/sdk` | TypeScript library wrapping SailKernel and MandateFactory |
14
+ | `packages/cli` | `sailor` | CLI for account setup, mandate signing, and agent execution |
15
+ | `packages/chains` | `@sail/chains` | Per-chain address registry (EVM-compatible) |
16
+ | `packages/ui` | `sailor-ui` | Local dashboard running on localhost:3333 |
17
+ | `templates/dca-rebalancer` | — | Starter template: DCA portfolio rebalancer (default for `sailor init`) |
18
+ | `templates/custom-mandate` | — | Solidity reference: allowlist mandate contracts (not a project template) |
19
+ | `templates/lifi-permissions` | — | Solidity reference: LiFi clone permission contracts (not a project template) |
20
+
21
+ ---
22
+
23
+ ## How it works
24
+
25
+ The path from nothing to a running agent is seven steps:
26
+
27
+ 1. **Generate keys** — a manager key (the agent's dispatch signer) and a permissionSigner key, both generated and encrypted on disk.
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.
34
+
35
+ ---
36
+
37
+ ## Roles
38
+
39
+ Sailor operates the three roles Sail Protocol separates:
40
+
41
+ | Role | Authority | Held by |
42
+ |---|---|---|
43
+ | **Owner** | Holds the Safe. Custody anchor. | The LP (Safe owner) — same wallet as MetaMask |
44
+ | **Permission Signer** | Signs mandate registration and revocation via EIP-712. | Same as Owner, or a separate key |
45
+ | **Manager** | Executes dispatches within permitted bounds. Signs each dispatch. | The agent key — encrypted in `.sail/keys/manager.json` |
46
+
47
+ ---
48
+
49
+ ## Installation
50
+
51
+ ### Start a new agent project (recommended)
52
+
53
+ Open your AI coding assistant and run in its terminal:
54
+
55
+ ```sh
56
+ npx sailor init my-agent
57
+ ```
58
+
59
+ Then say **"start"** — your assistant takes it from there.
60
+
61
+ ### Global CLI (for direct sailor commands)
62
+
63
+ ```sh
64
+ npm install -g @sail.money/sailor
65
+ sailor init my-agent
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Quickstart
71
+
72
+ Prerequisites:
73
+
74
+ - Node.js 18+ (the CLI runs on 18; `pnpm install` needs Node 22+)
75
+ - A wallet (MetaMask or Rabby)
76
+ - An RPC URL (e.g. Alchemy free tier)
77
+ - A supported chain: **Base, Base Sepolia, Arbitrum, or Unichain** — these use the verified deployments bundled in `@sail/sdk`, so no `@sail/chains` entry is needed. Other chains require kernel + mandateFactory addresses in `@sail/chains` (see [State of the project](#state-of-the-project)).
78
+
79
+ ```bash
80
+ npx sailor init my-agent && cd my-agent
81
+ npm install # or `pnpm install` (needs Node 22+)
82
+
83
+ # 1. Ground yourself — read-only, no gas, no wallet:
84
+ sailor capabilities # what you can build on this chain
85
+ sailor doctor # kernel model + RPC reachability + gas balances
86
+
87
+ # 2. Set up the account in the browser wizard (choose chain, connect wallet,
88
+ # generate the agent key, deploy your SMA):
89
+ sailor ui start # open http://localhost:3333 and follow steps 1–4
90
+
91
+ # 3. Back in the terminal: configure .sail/.env.local, fund the agent key for gas,
92
+ sailor mandate prepare # draft permissions → approve in the browser
93
+ sailor run # start the agent (use --once for a single tick)
94
+ ```
95
+
96
+ The SMA is deployed through the browser wizard (it submits from your wallet), not a
97
+ terminal command — see the scaffolded project's `AGENTS.md` for the full 8-step flow.
98
+
99
+ ---
100
+
101
+ ## Templates
102
+
103
+ `sailor init` scaffolds a new agent project from a template. By default it
104
+ writes into the **current directory**; pass a name to create a subdirectory.
105
+
106
+ ```bash
107
+ sailor init # scaffold into cwd
108
+ sailor init my-agent # create ./my-agent/ and scaffold there
109
+ sailor init --template dca-rebalancer # explicit (same as default)
110
+ sailor init my-agent --template <name> # named subdirectory + specific template
111
+ ```
112
+
113
+ ### Available templates
114
+
115
+ | Template | Description |
116
+ |---|---|
117
+ | `dca-rebalancer` | Dollar-cost-averaging portfolio rebalancer. Includes a full agent loop, Foundry workspace for permission contracts, GitHub Actions cron job, and the operator guide (`AGENTS.md`). **Default.** |
118
+
119
+ ### What makes a valid template
120
+
121
+ A valid template is any directory under `templates/` that contains a
122
+ `package.json`. Directories without one (e.g. `custom-mandate`,
123
+ `lifi-permissions`) are Solidity reference sources, not project scaffolds, and
124
+ are excluded from the available list.
125
+
126
+ ### Adding a template
127
+
128
+ 1. Create a directory under `templates/<your-template-name>/`.
129
+ 2. Add a `package.json` (the `name` field is patched to the project name on
130
+ init).
131
+ 3. Add a `.sail/` workspace structure if the agent needs local state.
132
+ 4. The template will appear automatically in `sailor init --template <name>`.
133
+
134
+ Template files are bundled into the published `sailor` npm package via the
135
+ `files` field in the root `package.json`.
136
+
137
+ ---
138
+
139
+ ## Dashboard (`sailor ui`)
140
+
141
+ The Sailor dashboard is a local React app served at `http://localhost:3333`.
142
+ It shows live account state, mandate health, signer balances, and recent
143
+ activity — all read from the project's `.sail/` directory with no hosted
144
+ backend.
145
+
146
+ ### Commands
147
+
148
+ ```bash
149
+ sailor ui # start the dashboard (same as sailor ui start)
150
+ sailor ui start # start the dashboard at http://localhost:3333
151
+ sailor ui stop # stop the running dashboard
152
+ sailor ui status # show whether the dashboard is running + pid
153
+ ```
154
+
155
+ ### How it works
156
+
157
+ `sailor ui start` spawns a bundled Express server (`server.cjs`) that:
158
+
159
+ - Serves the pre-built React UI as static files on `/`
160
+ - Exposes a local API on `/api` that reads `.sail/` state from the current
161
+ working directory
162
+
163
+ The server PID is written to `.sail/runtime/ui.json` on start. `sailor ui stop`
164
+ reads that file, sends `SIGTERM` to the server process, and removes the file.
165
+ This means you can start the dashboard in one terminal and stop it from another.
166
+
167
+ ### Running in the background
168
+
169
+ ```bash
170
+ # macOS / Linux
171
+ sailor ui start &
172
+ sailor ui status # ● running http://localhost:3333 (pid 12345)
173
+ sailor ui stop # Stopped Sailor UI (pid 12345).
174
+
175
+ # Windows (PowerShell)
176
+ Start-Job { sailor ui start }
177
+ sailor ui status
178
+ sailor ui stop
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Agent-driven onboarding & custom mandates
184
+
185
+ For chains with a bundled Sail deployment (Base, Base Sepolia, Arbitrum, Unichain — shipped
186
+ in `@sail/sdk`, no `@sail/chains` entry required), an agent can drive the whole
187
+ setup through a browser **signing station**. The station is a local HTTP +
188
+ WebSocket daemon that bridges the CLI and the owner's wallet: the agent never
189
+ holds the owner key — it pushes signing requests, the owner approves them in the
190
+ browser, and the agent submits the transactions it's allowed to.
191
+
192
+ ```bash
193
+ sailor keys generate # manager (agent) key
194
+ sailor station start & # signing daemon (serves the UI)
195
+ # owner opens the printed URL once and connects their wallet
196
+ sailor owner connect # detect & persist the owner
197
+ sailor scan # discover the owner's Safes + state
198
+ sailor onboard --new-sma # create an SMA + (optionally) attach a mandate
199
+ ```
200
+
201
+ Agents author their own permission contracts and deploy them from the scaffolded
202
+ Foundry workspace (`mandates/`, with `@sail/interfaces/IPermission.sol` vendored
203
+ under `.sail/contracts/`):
204
+
205
+ ```bash
206
+ forge build
207
+ sailor mandate deploy --contract MyMandate \
208
+ --args '["0xPermissionSigner", ["0xTarget"]]' \
209
+ --attach --sma 0xSafe
210
+ ```
211
+
212
+ `deploy` emits a contract-creation signing request (the owner signs it in the
213
+ browser); the deployed address is read from the receipt and tracked in
214
+ `.sail/state/mandates.json`. `attach` reads the signer nonce, has the owner sign
215
+ a `RegisterPermission` EIP-712 message, then the agent submits
216
+ `kernel.registerPermission` with the exact registration fee. Every command takes
217
+ `--json` for headless agent use; set `SAIL_PASSPHRASE` to unlock the manager key
218
+ non-interactively.
219
+
220
+ ---
221
+
222
+ ## Architecture
223
+
224
+ ```
225
+ ┌────────────────────┐ ┌────────────────────┐
226
+ │ Permission Signer │ │ Manager/Agent │
227
+ │ MetaMask / local │ │ .sail/keys/manager │
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)
246
+ ```
247
+
248
+ The CLI and SDK sit between the operator and SailKernel: they build the EIP-712 payloads, submit dispatches, and read kernel state via viem. The permission signer authorizes the mandate — registration runs through MandateFactory — while the manager key signs each dispatch the kernel evaluates against a named permission before executing it through the Safe. All local state — the deployed account, the signed mandate, and the agent's activity log — lives under `.sail/` on disk, which the dashboard reads through a small local server. Sailor never holds the Owner key and runs no hosted backend; the wallet talks to the chain directly.
249
+
250
+ ---
251
+
252
+ ## Security model
253
+
254
+ - The agent signs dispatches; the kernel evaluates the named permission on every call. A permission returning false or exceeding its gas cap is treated as denial — fail-closed.
255
+ - The Owner key controls the Safe and is never read by Sailor. Mandate signing requires a deliberate action by the permission signer.
256
+ - The manager key is encrypted on disk using geth keystore v3 (scrypt + aes-128-ctr) and is never transmitted.
257
+ - The session can be paused instantly via `sailor session pause` or the dashboard stop button; this does not affect Safe custody.
258
+
259
+ ---
260
+
261
+ ## State of the project
262
+
263
+ Sailor is functional and published as [`@sail.money/sailor`](https://www.npmjs.com/package/@sail.money/sailor) on npm (v0.0.1). The SDK, CLI, keystore, mandate flows, agent runner, and dashboard are implemented and have been exercised end to end against Base Sepolia.
264
+
265
+ The Sail Protocol trusted core is deployed on Base, Base Sepolia, Arbitrum, and Unichain as staging deployments for testing ahead of a formal launch. All four run the selective dispatch model, with verified deployments bundled in `@sail/sdk`. 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. Permission templates are not yet deployed against the Base, Arbitrum, and Base Sepolia kernels; **Unichain** ships the full template suite (7 shared + 12 standalone, source-verified) and its template registries in `@sail/sdk` are populated. `@sail/chains` and the remaining template registries will be filled in as templates are deployed on the other chains and at mainnet launch.
266
+
267
+ ---
268
+
269
+ ## Deployments
270
+
271
+ The Sail Protocol trusted core is live on the following chains as **staging deployments** ahead of a formal launch, bundled in `@sail/sdk`. All run the selective dispatch model with zero fees. Permission templates are not yet deployed against the Base, Arbitrum, and Base Sepolia kernels; **Unichain** ships the full template suite (7 shared + 12 standalone, source-verified on uniscan.xyz) and has its onboarding allowlists seeded at genesis.
272
+
273
+ ### Base (8453)
274
+
275
+ | Contract | Address |
276
+ |---|---|
277
+ | SailKernel | `0x6319d3dfDDe3804ba93D65752b00c52bFb05a1ab` |
278
+ | SailGovernance | `0x7E897D919872b1587577617ffFC42113679d0C50` |
279
+ | Timelock | `0x8eC3Ca951E193C6E3713A70022454d7A1f083281` |
280
+ | PermissionFactory | `0x7724EACd97C8601d5AC244Aadbf76ad87353Ff31` |
281
+ | StandardFeePolicy | `0x65850a8D5050aeAade68289ff96c4F119a24B82e` |
282
+ | SafeModuleEnabler | `0xC84EdE78f93291A1fab19F51c4c7e938AB302Edf` |
283
+ | Treasury | `0xB01dCE443d052e44b7D13726c0EC9fFB7f5815B6` |
284
+
285
+ ### Arbitrum (42161)
286
+
287
+ | Contract | Address |
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)
298
+
299
+ | Contract | Address |
300
+ |---|---|
301
+ | SailKernel | `0xf1D0F4C9893612627409948BAa9d82a01a373799` |
302
+ | SailGovernance | `0xEaD44bC6999E7b00b9b2E11c1660248DC2a30993` |
303
+ | Timelock | `0x97B863e392C9859336788D5Ec454527d33C95B74` |
304
+ | PermissionFactory | `0xdfF6a2272F667cDf78Af4681b9c88A219998db95` |
305
+ | StandardFeePolicy | `0x05570F7973b46Eb9Ed4518422891EFC26BD58b97` |
306
+ | SafeModuleEnabler | `0xB2C2B52d94412e3472C9fb2B52186eA12a935869` |
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.
326
+
327
+ ---
328
+
329
+ ## Contributing
330
+
331
+ Sailor and Sail Protocol are separate repositories with separate concerns. Protocol questions — SailKernel internals, permission templates, MandateFactory, fee policies — belong in the [SailProtocol](../SailProtocol) repository. Sailor questions — the SDK, CLI, dashboard, and agent templates — belong here.
332
+
333
+ ---
334
+
335
+ ## License
336
+
337
+ MIT
@@ -0,0 +1,93 @@
1
+ # Sail permission model: conjunctive vs selective
2
+
3
+ The deployed SailKernel ships in **two incompatible dispatch models**. Which one a
4
+ chain runs changes how dispatches are signed *and* how permissions must be written.
5
+ Get this wrong and every dispatch reverts with an opaque selector. This is the single
6
+ most important thing to understand before operating an SMA.
7
+
8
+ ## TL;DR
9
+
10
+ | | **Conjunctive** (older) | **Selective** (newer) |
11
+ |---|---|---|
12
+ | Chains today (bundled kernels) | None — all bundled kernels moved to selective | Base (8453), Base Sepolia (84532), Arbitrum (42161), Unichain (130) |
13
+ | `dispatch(...)` | `(account, target, value, data, sig, deadline)` — **no `permission`** | `(account, permission, target, value, data, sig, deadline)` |
14
+ | Which permissions are checked | **ALL** registered permissions; **all must return true** | only the **one** permission named in the call |
15
+ | EIP-712 `Dispatch` struct | no `permission` field | includes `permission` |
16
+ | Batch (`dispatchBatch`/`previewBatch`) | **not available** | available |
17
+ | **Permission design rule** | **MUST pass through calls outside its domain** | may return false freely |
18
+
19
+ Don't guess from a version string — **detect it on-chain** (see below).
20
+
21
+ ## The conjunctive pass-through rule (the big footgun)
22
+
23
+ On a conjunctive kernel the kernel calls `evaluate(txData, ctx)` on **every**
24
+ registered permission and ANDs the results. A single `false` blocks the whole
25
+ dispatch (`PermissionDenied`).
26
+
27
+ So a permission that only cares about, say, approvals **must still return `true` for
28
+ every call it doesn't govern**:
29
+
30
+ ```solidity
31
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
32
+ // Pass through calls outside this permission's domain (conjunctive model).
33
+ if (ctx.selector != APPROVE) return true; // <-- without this line, this
34
+ // permission bricks swaps,
35
+ // transfers, everything.
36
+ // ...domain-specific checks for approve...
37
+ }
38
+ ```
39
+
40
+ A permission that returns `false` (or reverts, or runs out of gas — both treated as
41
+ `false`) on unrelated calls **bricks the entire account**: no dispatch of any kind
42
+ can pass. We hit exactly this during bring-up with permissions that "blocked each
43
+ other." The fix was to redeploy every permission with pass-through semantics.
44
+
45
+ Corollary: on a conjunctive kernel you **cannot** have two permissions that each
46
+ enforce a different token's approve — each would reject the other's token. To support
47
+ approving both DAI and USDC you need **one** approve permission that allows both (see
48
+ `templates/lifi-permissions/`), not two narrow ones.
49
+
50
+ Selective kernels don't have this problem: each dispatch names one permission and
51
+ only that one is consulted.
52
+
53
+ ## Detect the model on-chain
54
+
55
+ The SDK reads each kernel's public `DISPATCH_TYPEHASH` constant and matches it
56
+ against the canonical hashes for each model. Never assume.
57
+
58
+ ```ts
59
+ const caps = await client.capabilities();
60
+ // caps.dispatchModel: "conjunctive" | "selective"
61
+ // caps.dispatchTypehash, caps.source ("onchain-typehash" | "static-hint")
62
+ ```
63
+
64
+ Verified typehashes:
65
+
66
+ - conjunctive `DISPATCH_TYPEHASH` = `0x7510c80e…`
67
+ `Dispatch(address account,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)`
68
+ - selective `DISPATCH_TYPEHASH` =
69
+ `Dispatch(address account,address permission,address target,uint256 value,bytes32 dataHash,uint256 nonce,uint256 deadline)`
70
+
71
+ `client.dispatch.single(...)` already signs the correct struct and uses the correct
72
+ ABI for the detected model — you don't sign by hand. `client.dispatch.batch` /
73
+ `preview` throw a clear error on conjunctive kernels (no `dispatchBatch`).
74
+
75
+ ## Roles (unchanged across models)
76
+
77
+ | Role | Authority |
78
+ |------|-----------|
79
+ | **Owner** | Holds the Safe; custody anchor. |
80
+ | **Permission Signer** | Authorizes which `IPermission` contracts apply (EIP-712 `RegisterPermissions` / `RevokePermissions`). Signed in the browser signing station — the agent never holds this key. |
81
+ | **Manager** | Executes dispatches within the registered permissions (ECDSA / ERC-1271). The agent's hot key. |
82
+
83
+ ## Preflight before spending gas
84
+
85
+ Run `sailor doctor` (read-only, no gas, no keys):
86
+
87
+ - detects the dispatch model,
88
+ - lists registered permissions,
89
+ - on a conjunctive kernel, **probes each permission for pass-through** and flags any
90
+ that would brick dispatch.
91
+
92
+ See [AGENTS.md](../AGENTS.md) for the operational decision tree and the
93
+ revert failure-mode catalog.
@@ -0,0 +1,96 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ // ─────────────────────────────────────────────────────────────────────────────
5
+ // Protocol : Limitless
6
+ // Version : CTF-based prediction market (on-chain settlement on Base)
7
+ // NOT Polymarket (Polymarket's CLOB matches orders off-chain on Polygon —
8
+ // a permission cannot bound the orders your agent signs off-chain.
9
+ // Limitless settles bets on-chain on Base, so the kernel sees every action.)
10
+ // Chain : Base mainnet
11
+ //
12
+ // ⚠ WARNING — ABI UNVERIFIED ⚠
13
+ // The Limitless exchange contract address and bet-placement function signature
14
+ // below are based on published CTF exchange patterns and public documentation.
15
+ // They have NOT been independently verified against the deployed contracts.
16
+ // YOU MUST verify these before deploying with real funds:
17
+ // 1. Find the Limitless exchange contract address on Basescan.
18
+ // 2. Read its verified ABI and confirm the buy/place function signature.
19
+ // 3. Recompute the selector and update SEL_BUY.
20
+ // 4. Confirm the parameter layout matches BetParams below.
21
+ // Deploying this contract with an unverified ABI may silently PASS or FAIL
22
+ // all dispatches depending on whether the selector matches.
23
+ //
24
+ // ENFORCED ON-CHAIN (assuming verified ABI — see warning above):
25
+ // buy(bytes32 conditionId, uint256 amount, uint256 outcomeIndex)
26
+ // • target must be LIMITLESS_EXCHANGE
27
+ // • conditionId must be in ALLOWED_CONDITIONS
28
+ // • amount ≤ MAX_STAKE
29
+ // • outcomeIndex must be in ALLOWED_OUTCOMES
30
+ //
31
+ // NOT ENFORCED:
32
+ // • Market price / odds (on-chain prediction market prices fluctuate)
33
+ // • Timing / frequency of bets
34
+ //
35
+ // VERIFY BEFORE USE:
36
+ // • Confirm Limitless exchange address on Base (Basescan).
37
+ // • Confirm buy function signature and compute selector:
38
+ // keccak256("buy(bytes32,uint256,uint256)")[0:4] == 0x??? — verify on-chain.
39
+ // • Confirm conditionId encoding matches the deployed market IDs.
40
+ // • Update this contract if the ABI or parameter order differs.
41
+ // ─────────────────────────────────────────────────────────────────────────────
42
+
43
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
44
+
45
+ contract BoundedBet_Limitless_Base is IPermission {
46
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedBet_Limitless_Base");
47
+
48
+ /// @dev ⚠ UNVERIFIED — replace with verified Limitless exchange address on Base.
49
+ address public immutable LIMITLESS_EXCHANGE;
50
+ mapping(bytes32 => bool) public isAllowedCondition;
51
+ uint256 public immutable MAX_STAKE;
52
+ mapping(uint256 => bool) public isAllowedOutcome;
53
+
54
+ /// @dev ⚠ UNVERIFIED selector. Compute keccak256("buy(bytes32,uint256,uint256)")[0:4]
55
+ /// and confirm it matches the deployed Limitless exchange contract before use.
56
+ bytes4 private constant SEL_BUY = bytes4(keccak256("buy(bytes32,uint256,uint256)"));
57
+
58
+ /// @param limitlessExchange ⚠ VERIFY — Limitless CTF exchange address on Base
59
+ /// @param allowedConditions conditionIds (bytes32) of markets the agent may bet on
60
+ /// @param maxStake Per-bet stake cap in collateral base units
61
+ /// @param allowedOutcomes Outcome indices the agent may select (e.g. [0] for YES only)
62
+ constructor(
63
+ address limitlessExchange,
64
+ bytes32[] memory allowedConditions,
65
+ uint256 maxStake,
66
+ uint256[] memory allowedOutcomes
67
+ ) {
68
+ LIMITLESS_EXCHANGE = limitlessExchange;
69
+ MAX_STAKE = maxStake;
70
+ for (uint256 i = 0; i < allowedConditions.length; i++) {
71
+ isAllowedCondition[allowedConditions[i]] = true;
72
+ }
73
+ for (uint256 i = 0; i < allowedOutcomes.length; i++) {
74
+ isAllowedOutcome[allowedOutcomes[i]] = true;
75
+ }
76
+ }
77
+
78
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool) {
79
+ if (ctx.target != LIMITLESS_EXCHANGE) return false;
80
+ if (ctx.selector != SEL_BUY) return false;
81
+ if (txData.length < 4 + 3 * 32) return false;
82
+
83
+ // ⚠ Assumes: buy(bytes32 conditionId, uint256 amount, uint256 outcomeIndex)
84
+ // Verify parameter order against deployed contract ABI before use.
85
+ (bytes32 conditionId, uint256 amount, uint256 outcomeIndex) =
86
+ abi.decode(txData[4:], (bytes32, uint256, uint256));
87
+
88
+ if (!isAllowedCondition[conditionId]) return false;
89
+ if (amount > MAX_STAKE) return false;
90
+ if (!isAllowedOutcome[outcomeIndex]) return false;
91
+
92
+ return true;
93
+ }
94
+
95
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
96
+ }