@dev.sail.money/sailor 0.0.2-12

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 +51201 -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
@@ -0,0 +1,366 @@
1
+ // @ts-check
2
+ /**
3
+ * Post-install script for the Sailor package.
4
+ *
5
+ * Runs automatically after `npm install` / `pnpm add`. Orchestrates:
6
+ * 1. sailor init — scaffold the .sail/ workspace (skipped if already done)
7
+ * 2. sailor station — start the signing daemon in background
8
+ * 3. sailor ui — start the dashboard server in background
9
+ * 4. browser launch — open the dashboard so the user hits the onboarding flow
10
+ *
11
+ * Every step is logged in a structured way so an automated agent can parse the
12
+ * output and know exactly which services are up, which failed, and where to send
13
+ * the user next.
14
+ */
15
+
16
+ "use strict";
17
+
18
+ const fs = require("node:fs");
19
+ const path = require("node:path");
20
+ const http = require("node:http");
21
+ const os = require("node:os");
22
+ const { execFileSync, spawn } = require("node:child_process");
23
+
24
+ // Directory where the user ran `npm install` / `pnpm add`
25
+ const initCwd = process.env.INIT_CWD || process.cwd();
26
+ const TAG = "[sailor]";
27
+
28
+ // ── Skip conditions ──────────────────────────────────────────────────────────
29
+
30
+ // Never run inside the Sailor monorepo itself
31
+ if (fs.existsSync(path.join(initCwd, "pnpm-workspace.yaml"))) process.exit(0);
32
+
33
+ // Opt-out env var
34
+ if (process.env.SAILOR_SKIP_INIT === "1") process.exit(0);
35
+
36
+ const cliBundle = path.join(__dirname, "..", "packages", "cli", "dist", "index.cjs");
37
+
38
+ if (!fs.existsSync(cliBundle)) {
39
+ console.warn(`${TAG} CLI bundle not found — skipping postinstall.`);
40
+ process.exit(0);
41
+ }
42
+
43
+ // ── Logging helpers ──────────────────────────────────────────────────────────
44
+
45
+ function log(msg) { console.log(`${TAG} ${msg}`); }
46
+ function ok(msg) { console.log(`${TAG} ✓ ${msg}`); }
47
+ function fail(msg){ console.error(`${TAG} ✗ ${msg}`); }
48
+ function sep(label) {
49
+ console.log(`${TAG} ${"─".repeat(52)}`);
50
+ if (label) console.log(`${TAG} ${label}`);
51
+ }
52
+
53
+ // ── Utilities ────────────────────────────────────────────────────────────────
54
+
55
+ function readJson(file) {
56
+ try { return JSON.parse(fs.readFileSync(file, "utf-8")); } catch { return null; }
57
+ }
58
+
59
+ function isAlive(pid) {
60
+ try { process.kill(pid, 0); return true; } catch { return false; }
61
+ }
62
+
63
+ /** Repeatedly calls fn() until it returns a non-null value or the timeout expires. */
64
+ function poll(fn, { timeout = 12_000, interval = 600 } = {}) {
65
+ return new Promise((resolve) => {
66
+ const deadline = Date.now() + timeout;
67
+ function attempt() {
68
+ Promise.resolve(fn()).then((result) => {
69
+ if (result != null) { resolve(result); return; }
70
+ if (Date.now() >= deadline) { resolve(null); return; }
71
+ setTimeout(attempt, interval);
72
+ });
73
+ }
74
+ attempt();
75
+ });
76
+ }
77
+
78
+ /** Returns true if any HTTP response arrives from url (any status = server is up). */
79
+ function httpPing(url) {
80
+ return new Promise((resolve) => {
81
+ try {
82
+ const req = http.get(url, { timeout: 2500 }, (res) => {
83
+ res.resume();
84
+ resolve(true);
85
+ });
86
+ req.on("error", () => resolve(false));
87
+ req.on("timeout", () => { req.destroy(); resolve(false); });
88
+ } catch { resolve(false); }
89
+ });
90
+ }
91
+
92
+ /** Open the user's default browser (best-effort, non-fatal). */
93
+ function openBrowser(url) {
94
+ try {
95
+ const platform = os.platform();
96
+ if (platform === "darwin") {
97
+ spawn("open", [url], { stdio: "ignore", detached: true }).unref();
98
+ } else if (platform === "win32") {
99
+ // `start ""` avoids treating the URL as a window title
100
+ spawn("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true }).unref();
101
+ } else {
102
+ spawn("xdg-open", [url], { stdio: "ignore", detached: true }).unref();
103
+ }
104
+ } catch { /* best-effort */ }
105
+ }
106
+
107
+ // ── Shared status object (machine-readable summary at the end) ───────────────
108
+
109
+ const status = {
110
+ init: { state: "skipped", detail: "" },
111
+ station: { state: "not-started", detail: "" },
112
+ ui: { state: "not-started", detail: "" },
113
+ uiUrl: /** @type {string|null} */ (null),
114
+ errors: /** @type {string[]} */ ([]),
115
+ };
116
+
117
+ // ── Step 1: init ─────────────────────────────────────────────────────────────
118
+
119
+ async function step1Init() {
120
+ sep("Step 1 — init");
121
+
122
+ const configExists = fs.existsSync(path.join(initCwd, ".sail", "config.json"));
123
+
124
+ if (configExists) {
125
+ ok("Project already initialized — skipping init.");
126
+ status.init = { state: "already-initialized", detail: path.join(initCwd, ".sail", "config.json") };
127
+ return true;
128
+ }
129
+
130
+ log("Running sailor init…");
131
+ try {
132
+ execFileSync(process.execPath, [cliBundle, "init"], {
133
+ cwd: initCwd,
134
+ stdio: "inherit",
135
+ });
136
+ ok("Init complete.");
137
+ status.init = { state: "ok", detail: "" };
138
+ return true;
139
+ } catch (err) {
140
+ fail("sailor init exited with an error. Run `sailor init` manually to complete setup.");
141
+ const msg = err instanceof Error ? err.message : String(err);
142
+ status.init = { state: "error", detail: msg };
143
+ status.errors.push(`init: ${msg}`);
144
+ return false;
145
+ }
146
+ }
147
+
148
+ // ── Step 2: signing station ───────────────────────────────────────────────────
149
+
150
+ async function step2Station() {
151
+ sep("Step 2 — signing station");
152
+
153
+ const stateFile = path.join(initCwd, ".sail", "runtime", "server.json");
154
+ const existing = readJson(stateFile);
155
+
156
+ // Already running?
157
+ if (existing && existing.pid && isAlive(existing.pid)) {
158
+ ok(`Station already running at ${existing.url} (pid ${existing.pid})`);
159
+ status.station = { state: "already-running", detail: existing.url };
160
+ return;
161
+ }
162
+
163
+ // Remove stale state file if present
164
+ if (existing) {
165
+ try { fs.rmSync(stateFile, { force: true }); } catch { /* ignore */ }
166
+ }
167
+
168
+ log("Starting signing station in background…");
169
+
170
+ // station start blocks (keeps the process alive), so we must spawn it detached.
171
+ const child = spawn(process.execPath, [cliBundle, "station", "start"], {
172
+ cwd: initCwd,
173
+ detached: true,
174
+ stdio: "ignore",
175
+ });
176
+ child.unref();
177
+
178
+ // Poll until the state file appears and /config responds
179
+ const state = await poll(async () => {
180
+ const s = readJson(stateFile);
181
+ if (!s || !s.url || !s.pid) return null;
182
+ if (!isAlive(s.pid)) return null;
183
+ const up = await httpPing(`${s.url}/config`);
184
+ return up ? s : null;
185
+ }, { timeout: 15_000 });
186
+
187
+ if (state) {
188
+ ok(`Station running at ${state.url} (pid ${state.pid})`);
189
+ status.station = { state: "running", detail: state.url };
190
+ } else {
191
+ fail("Station did not come up within 15 s.");
192
+ fail("Start it manually with: sailor station start");
193
+ status.station = { state: "error", detail: "timed out" };
194
+ status.errors.push("station: timed out waiting for /config to respond");
195
+ }
196
+ }
197
+
198
+ // ── Step 3: dashboard UI ──────────────────────────────────────────────────────
199
+
200
+ async function step3Ui() {
201
+ sep("Step 3 — dashboard UI");
202
+
203
+ const stateFile = path.join(initCwd, ".sail", "runtime", "ui.json");
204
+ const existing = readJson(stateFile);
205
+
206
+ // Already running?
207
+ if (existing && existing.pid && isAlive(existing.pid)) {
208
+ const url = `http://localhost:${existing.port}`;
209
+ ok(`UI already running at ${url} (pid ${existing.pid})`);
210
+ status.ui = { state: "already-running", detail: url };
211
+ status.uiUrl = url;
212
+ return;
213
+ }
214
+
215
+ // Remove stale state file if present
216
+ if (existing) {
217
+ try { fs.rmSync(stateFile, { force: true }); } catch { /* ignore */ }
218
+ }
219
+
220
+ log("Starting Sailor UI in background…");
221
+
222
+ // uiCommand() spawns the server process itself and returns quickly (~300 ms).
223
+ try {
224
+ execFileSync(process.execPath, [cliBundle, "ui"], {
225
+ cwd: initCwd,
226
+ stdio: "pipe", // suppress duplicate "Sailor UI started" output; we log our own
227
+ });
228
+ } catch (err) {
229
+ const msg = err instanceof Error ? err.message : String(err);
230
+ fail(`UI start failed: ${msg}`);
231
+ status.ui = { state: "error", detail: msg };
232
+ status.errors.push(`ui: ${msg}`);
233
+ return;
234
+ }
235
+
236
+ // uiCommand writes the state file before returning; read it immediately.
237
+ const state = readJson(stateFile);
238
+ if (!state || !state.port) {
239
+ fail("UI state file missing after start. Run `sailor ui` manually.");
240
+ status.ui = { state: "error", detail: "state file missing" };
241
+ status.errors.push("ui: .sail/runtime/ui.json not written after start");
242
+ return;
243
+ }
244
+
245
+ const url = `http://localhost:${state.port}`;
246
+
247
+ // Wait until the server is actually serving (it may need a moment to bind).
248
+ const up = await poll(() => httpPing(url), { timeout: 10_000, interval: 500 });
249
+
250
+ if (up) {
251
+ ok(`UI running at ${url} (pid ${state.pid})`);
252
+ status.ui = { state: "running", detail: url };
253
+ status.uiUrl = url;
254
+ } else {
255
+ fail(`UI process started (pid ${state.pid}) but not responding at ${url}.`);
256
+ fail("Run `sailor ui status` to check.");
257
+ status.ui = { state: "degraded", detail: url };
258
+ status.uiUrl = url; // still try to open the browser — maybe it comes up in time
259
+ status.errors.push(`ui: process alive but HTTP not responding at ${url}`);
260
+ }
261
+ }
262
+
263
+ // ── Step 4: open browser ──────────────────────────────────────────────────────
264
+
265
+ async function step4Browser() {
266
+ if (!status.uiUrl) return;
267
+ sep("Step 4 — opening browser");
268
+ log(`Opening ${status.uiUrl} …`);
269
+ openBrowser(status.uiUrl);
270
+ }
271
+
272
+ // ── Final summary ─────────────────────────────────────────────────────────────
273
+
274
+ function printSummary() {
275
+ const icon = (s) =>
276
+ ({ ok: "✓", "already-initialized": "✓", "already-running": "✓", running: "✓",
277
+ skipped: "–", error: "✗", degraded: "⚠", "not-started": "–" })[s] ?? "?";
278
+
279
+ sep("SAILOR SETUP — STATUS SUMMARY");
280
+ log(` init: ${icon(status.init.state)} ${status.init.state}${status.init.detail ? " (" + status.init.detail + ")" : ""}`);
281
+ log(` station: ${icon(status.station.state)} ${status.station.detail || status.station.state}`);
282
+ log(` ui: ${icon(status.ui.state)} ${status.ui.detail || status.ui.state}`);
283
+
284
+ if (status.errors.length) {
285
+ log("");
286
+ log(" Errors encountered:");
287
+ status.errors.forEach((e) => log(` • ${e}`));
288
+ }
289
+
290
+ sep();
291
+
292
+ if (status.uiUrl) {
293
+ log(` → Onboarding: ${status.uiUrl}`);
294
+ log(` Open the URL above to connect your wallet and complete setup.`);
295
+ } else {
296
+ log(` → Run \`sailor ui\` to start the dashboard.`);
297
+ log(` → Run \`sailor station start\` to start the signing daemon.`);
298
+ log(` → Then open the dashboard URL to complete onboarding.`);
299
+ }
300
+
301
+ sep();
302
+ printAgentInstructions();
303
+ }
304
+
305
+ function printAgentInstructions() {
306
+ const uiUrl = status.uiUrl ?? "<sailor ui URL — run `sailor ui` to get it>";
307
+ const L = (msg = "") => console.log(`${TAG} ${msg}`);
308
+
309
+ L("╔══════════════════════════════════════════════════════╗");
310
+ L("║ IF YOU ARE AN AI AGENT ║");
311
+ L("╚══════════════════════════════════════════════════════╝");
312
+ L();
313
+ L(" Sailor has been installed and its services are running.");
314
+ L(" Your job now is to guide the USER through onboarding.");
315
+ L();
316
+ L(" ── Step 1: ask the user these questions ────────────────");
317
+ L();
318
+ L(" 1. Which network do you want to deploy your SMA on?");
319
+ L(" (e.g. Base, Arbitrum One, Ethereum mainnet, …)");
320
+ L();
321
+ L(" 2. Do you have an RPC URL for that network?");
322
+ L(" If not, suggest a free provider: Alchemy, Infura, Ankr.");
323
+ L(" Once they have it: write it to .sail/.env.local as RPC_URL=<url>");
324
+ L();
325
+ L(" 3. Do you have a funded wallet (MetaMask or similar)?");
326
+ L(" They will need gas on the chosen network to deploy the SMA.");
327
+ L();
328
+ L(" ── Step 2: send the user to the browser ────────────────");
329
+ L();
330
+ L(` Dashboard: ${uiUrl}`);
331
+ L();
332
+ L(" Tell them to open the URL and complete these 3 browser steps:");
333
+ L(" a. Connect their wallet");
334
+ L(" b. Deploy their SMA (requires gas on the chosen network)");
335
+ L(" c. Create the agent wallet");
336
+ L();
337
+ L(" The signing station is running — browser requests will be");
338
+ L(" routed through it automatically.");
339
+ L();
340
+ L(" ── Step 3: once browser steps are done ─────────────────");
341
+ L();
342
+ L(" Ask the user to describe their strategy (what the agent");
343
+ L(" should do, with what limits). Then:");
344
+ L(" • Build the mandate contract: sailor mandate deploy …");
345
+ L(" • Verify everything is healthy: sailor doctor");
346
+ L(" • Set up automation (local or GitHub Actions)");
347
+ L();
348
+ L(" Run `sailor capabilities` for a full list of what this");
349
+ L(" kernel version supports (no wallet, no gas needed).");
350
+ L();
351
+ L("══════════════════════════════════════════════════════════");
352
+ }
353
+
354
+ // ── Main ──────────────────────────────────────────────────────────────────────
355
+
356
+ (async () => {
357
+ await step1Init();
358
+
359
+ // Start station and UI concurrently — they are independent of each other.
360
+ // Station is discovered by the UI at runtime via .sail/runtime/server.json.
361
+ // We attempt both even if init failed, in case the project was partially set up.
362
+ await Promise.all([step2Station(), step3Ui()]);
363
+
364
+ await step4Browser();
365
+ printSummary();
366
+ })();
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ struct Context {
5
+ address account;
6
+ address manager;
7
+ address submitter;
8
+ address target;
9
+ bytes4 selector;
10
+ uint256 value;
11
+ uint256 blockTimestamp;
12
+ uint256 blockNumber;
13
+ }
14
+
15
+ interface IPermission {
16
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool);
17
+ function discriminator() external view returns (bytes32);
18
+ }
@@ -0,0 +1,85 @@
1
+ # Write Your Own Permission — Sail Protocol
2
+
3
+ Sail Protocol accepts ANY contract implementing `IPermission`. There is no fixed set of
4
+ permission types. `BoundedCallPermission` here is a general primitive; `examples/permissions/`
5
+ shows protocol-specific patterns. Every financial bound your mandate enforces should live in
6
+ Solidity — the kernel checks `evaluate()` on every dispatch. The agent's TypeScript can be changed
7
+ without your signature; the permission contract cannot. You own what you deploy.
8
+
9
+ ---
10
+
11
+ Sailor does not ship a blessed library of financial permission contracts. You author, review, and
12
+ deploy your own `IPermission` contract, and Sailor makes deploying and registering it easy.
13
+
14
+ ## What a permission contract is
15
+
16
+ A permission contract is an on-chain policy that the SailKernel consults before it lets your agent
17
+ (the manager) execute any transaction from your SMA. On every dispatch the kernel calls
18
+ `evaluate(txData, ctx)` on each registered permission via `staticcall` — return `true` to allow the
19
+ call, `false` to block it. The contract holds your rules (allowed targets, size caps, token
20
+ allowlists, time windows, …) so the agent can only ever act inside the bounds you deployed.
21
+
22
+ ## The IPermission interface
23
+
24
+ ```solidity
25
+ interface IPermission {
26
+ function evaluate(bytes calldata txData, Context calldata ctx) external view returns (bool);
27
+ function discriminator() external view returns (bytes32);
28
+ }
29
+
30
+ struct Context {
31
+ address account; // the SMA (Safe) the dispatch executes from
32
+ address manager; // the delegated signer authorized to dispatch
33
+ address submitter; // the address that submitted the dispatch transaction
34
+ address target; // the contract the call is directed at
35
+ bytes4 selector; // the 4-byte function selector being called
36
+ uint256 value; // msg.value (native asset) sent with the call
37
+ uint256 blockTimestamp; // block.timestamp at evaluation
38
+ uint256 blockNumber; // block.number at evaluation
39
+ }
40
+ ```
41
+
42
+ - `evaluate` — your policy. Return `true` to permit the call, `false` to block it. Runs under a
43
+ 100k-gas `staticcall`; a revert or gas overage is treated as `false`.
44
+ - `discriminator` — a stable `bytes32` name for your permission (e.g. `keccak256("MyMandate")`).
45
+
46
+ Keep all policy parameters constructor-configured so each deployment is a complete, reviewable
47
+ policy before it is attached to the SMA.
48
+
49
+ ## Workflow
50
+
51
+ ```bash
52
+ # 1. Write your contract in mandates/ (start from BoundedCallPermission.sol)
53
+ # 2. Compile
54
+ forge build
55
+
56
+ # 3. Deploy and attach in one step
57
+ sailor mandate deploy --contract <Name> --attach --sma <SMA>
58
+ ```
59
+
60
+ Or deploy first and attach later (two-step):
61
+
62
+ ```bash
63
+ sailor mandate deploy --contract <Name> # prints the deployed address
64
+ sailor mandate attach --address <deployedAddress> --sma <SMA>
65
+ ```
66
+
67
+ Both attach paths open the browser signing station so the owner authorizes the registration
68
+ (EIP-712 `RegisterPermission`); the agent submits the on-chain transaction.
69
+
70
+ ## Prerequisites
71
+
72
+ - [Foundry](https://book.getfoundry.sh/getting-started/installation)
73
+ - An existing Sailor agent (created with `sailor init`)
74
+
75
+ ## Responsibility
76
+
77
+ > **You are responsible for the correctness of your permission logic. Sailor registers whatever
78
+ > contract address you provide. A bug can block all agent activity or authorize transactions you did
79
+ > not intend. Review carefully before attaching.**
80
+
81
+ ## Structure
82
+
83
+ - `foundry.toml` — Foundry config with `@sail/` remapping to `.sail/contracts/`
84
+ - `.sail/contracts/interfaces/IPermission.sol` — interface copy (matches SailProtocol)
85
+ - `mandates/BoundedCallPermission.sol` — general primitive: allowlisted targets, optional selector filter, max ETH value
@@ -0,0 +1,8 @@
1
+ [profile.default]
2
+ src = "mandates"
3
+ out = "out"
4
+ libs = ["lib"]
5
+ remappings = ["@sail/=.sail/contracts/"]
6
+ solc = "0.8.26"
7
+ optimizer = true
8
+ optimizer_runs = 200
@@ -0,0 +1,35 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
5
+
6
+ /// @title BoundedCallPermission
7
+ /// @notice General-purpose IPermission primitive. Bounds the universal properties of any call:
8
+ /// allowed targets, allowed selectors, and max ETH value. Protocol-agnostic.
9
+ /// For calldata-parameter bounds (amount caps, recipient checks, slippage), write a
10
+ /// protocol-specific permission — see examples/permissions/ for the pattern per protocol.
11
+ /// @dev Deploy one instance per SMA with constructor-configured parameters.
12
+ contract BoundedCallPermission is IPermission {
13
+ bytes32 private constant DISCRIMINATOR = keccak256("BoundedCallPermission");
14
+
15
+ mapping(address => bool) public isAllowedTarget;
16
+ mapping(bytes4 => bool) public isAllowedSelector;
17
+ bool public immutable SELECTOR_FILTERING;
18
+ uint256 public immutable MAX_VALUE;
19
+
20
+ constructor(address[] memory allowedTargets, bytes4[] memory allowedSelectors, uint256 maxValue) {
21
+ for (uint256 i = 0; i < allowedTargets.length; i++) isAllowedTarget[allowedTargets[i]] = true;
22
+ SELECTOR_FILTERING = allowedSelectors.length > 0;
23
+ for (uint256 i = 0; i < allowedSelectors.length; i++) isAllowedSelector[allowedSelectors[i]] = true;
24
+ MAX_VALUE = maxValue;
25
+ }
26
+
27
+ function evaluate(bytes calldata, Context calldata ctx) external view returns (bool) {
28
+ if (!isAllowedTarget[ctx.target]) return false;
29
+ if (SELECTOR_FILTERING && !isAllowedSelector[ctx.selector]) return false;
30
+ if (ctx.value > MAX_VALUE) return false;
31
+ return true;
32
+ }
33
+
34
+ function discriminator() external pure returns (bytes32) { return DISCRIMINATOR; }
35
+ }
@@ -0,0 +1,16 @@
1
+ # Mandates
2
+
3
+ Solidity permission contracts live here. Each contract implements `@sail/interfaces/IPermission.sol`.
4
+ The SailKernel calls `evaluate(txData, ctx)` before any manager dispatch. Return `true` to permit,
5
+ `false` to block.
6
+
7
+ ## Workflow
8
+
9
+ ```bash
10
+ forge build
11
+ sailor mandate prepare
12
+ sailor ui
13
+ ```
14
+
15
+ Keep all policy parameters constructor-configured so each deployment has a complete, reviewable
16
+ policy before it is attached to the SMA.
@@ -0,0 +1,25 @@
1
+ # Sail Agent Project
2
+
3
+ You are an AI assistant helping the user set up and operate a Sail Protocol SMA (Separately Managed Account) using the Sailor toolkit.
4
+
5
+ **Read `AGENTS.md` first.** It is the canonical guide — voice, stage-by-stage workflow, permission authoring, deployment, and automation.
6
+
7
+ ## Quick reference
8
+
9
+ | File | Purpose |
10
+ |------|---------|
11
+ | `AGENTS.md` | Full operator guide — start here |
12
+ | `.sail/config.json` | Project config (chain, contracts) |
13
+ | `.sail/account.json` | Active SMA address |
14
+ | `.sail/.env.local` | RPC URL and passphrase — never commit |
15
+ | `.sail/keys/manager.json` | Encrypted agent key |
16
+ | `.sail/activity.jsonl` | Agent decision journal |
17
+ | `mandates/` | Solidity permission contracts |
18
+ | `examples/permissions/` | Protocol-specific permission patterns |
19
+ | `docs/PERMISSION_MODEL.md` | Conjunctive vs selective kernel deep-dive |
20
+
21
+ ## Rules
22
+ - Work through AGENTS.md stages in order — never skip
23
+ - Always ask before any action that costs gas or moves funds
24
+ - The browser UI at localhost:3333 is required for mandate signing and monitoring
25
+ - `SAIL_PASSPHRASE` unlocks the manager key headlessly for `sailor run`
@@ -0,0 +1,6 @@
1
+ # Sailor agent environment
2
+ RPC_URL=https://your-rpc-endpoint
3
+ CHAIN_ID=8453
4
+
5
+ # Optional for non-interactive runs
6
+ # SAIL_PASSPHRASE=change-me-to-a-strong-passphrase
@@ -0,0 +1,32 @@
1
+ name: Agent Tick
2
+
3
+ on:
4
+ schedule:
5
+ # Every Monday at 09:00 UTC
6
+ - cron: "0 9 * * 1"
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ tick:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - uses: pnpm/action-setup@v4
16
+ with:
17
+ version: 9
18
+
19
+ - uses: actions/setup-node@v4
20
+ with:
21
+ node-version: 20
22
+ cache: "pnpm"
23
+
24
+ - name: Install dependencies
25
+ run: pnpm install --frozen-lockfile
26
+
27
+ - name: Run agent tick
28
+ env:
29
+ RPC_URL: ${{ secrets.RPC_URL }}
30
+ MANAGER_KEY: ${{ secrets.MANAGER_KEY }}
31
+ CHAIN_ID: ${{ vars.CHAIN_ID || '8453' }}
32
+ run: npx sailor run --once
File without changes
@@ -0,0 +1,13 @@
1
+ # Sailor Project Workspace
2
+
3
+ This folder is the local workspace for one Sailor agent deployment.
4
+
5
+ ## Layout
6
+
7
+ - `config.json` is the project manifest: name, chain, and state location.
8
+ - `keys/` stores encrypted local signing keys. Never commit these files.
9
+ - `runtime/` is for local UI and signing handoff state.
10
+ - `state/` is for persistent agent state, audit logs, and tx history.
11
+
12
+ AI coding agents should read the project's `AGENTS.md` and this folder's `config.json`
13
+ before changing strategy code or running commands that touch funds.
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 1,
3
+ "name": "dca-rebalancer",
4
+ "chainId": 8453,
5
+ "stateDir": ".sail/state",
6
+ "contracts": {
7
+ "kernel": "",
8
+ "mandateFactory": ""
9
+ }
10
+ }