rise-wallet 0.1.4-beta.2 → 0.2.29

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 (738) hide show
  1. package/README.md +64 -34
  2. package/dist/cli/Dialog.d.ts +35 -0
  3. package/dist/cli/Dialog.d.ts.map +1 -0
  4. package/dist/cli/Dialog.js +60 -0
  5. package/dist/cli/Dialog.js.map +1 -0
  6. package/dist/cli/Messenger.d.ts +8 -0
  7. package/dist/cli/Messenger.d.ts.map +1 -0
  8. package/dist/cli/Messenger.js +123 -0
  9. package/dist/cli/Messenger.js.map +1 -0
  10. package/dist/cli/bin/commands-o468kGU4.js +50 -0
  11. package/dist/cli/bin/index.js +9 -0
  12. package/dist/cli/index.d.ts +3 -0
  13. package/dist/cli/index.d.ts.map +1 -0
  14. package/dist/cli/index.js +3 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/cli/internal/commands.d.ts +13 -0
  17. package/dist/cli/internal/commands.d.ts.map +1 -0
  18. package/dist/cli/internal/commands.js +180 -0
  19. package/dist/cli/internal/commands.js.map +1 -0
  20. package/dist/cli/internal/context.d.ts +521 -0
  21. package/dist/cli/internal/context.d.ts.map +1 -0
  22. package/dist/cli/internal/context.js +38 -0
  23. package/dist/cli/internal/context.js.map +1 -0
  24. package/dist/cli/internal/http.d.ts +7 -0
  25. package/dist/cli/internal/http.d.ts.map +1 -0
  26. package/dist/cli/internal/http.js +17 -0
  27. package/dist/cli/internal/http.js.map +1 -0
  28. package/dist/cli/internal/utils.d.ts +7 -0
  29. package/dist/cli/internal/utils.d.ts.map +1 -0
  30. package/dist/cli/internal/utils.js +24 -0
  31. package/dist/cli/internal/utils.js.map +1 -0
  32. package/dist/core/Chains.d.ts +211 -0
  33. package/dist/core/Chains.d.ts.map +1 -0
  34. package/dist/core/Chains.js +20 -0
  35. package/dist/core/Chains.js.map +1 -0
  36. package/dist/core/Dialog.d.ts +308 -0
  37. package/dist/core/Dialog.d.ts.map +1 -0
  38. package/dist/core/Dialog.js +809 -0
  39. package/dist/core/Dialog.js.map +1 -0
  40. package/dist/core/Messenger.d.ts +165 -0
  41. package/dist/core/Messenger.d.ts.map +1 -0
  42. package/dist/core/Messenger.js +207 -0
  43. package/dist/core/Messenger.js.map +1 -0
  44. package/dist/core/Mode.d.ts +5 -0
  45. package/dist/core/Mode.d.ts.map +1 -0
  46. package/dist/core/Mode.js +5 -0
  47. package/dist/core/Mode.js.map +1 -0
  48. package/dist/core/Porto.d.ts +1609 -0
  49. package/dist/core/Porto.d.ts.map +1 -0
  50. package/dist/core/Porto.js +105 -0
  51. package/dist/core/Porto.js.map +1 -0
  52. package/dist/core/RpcSchema.d.ts +82 -0
  53. package/dist/core/RpcSchema.d.ts.map +1 -0
  54. package/dist/core/RpcSchema.js +2 -0
  55. package/dist/core/RpcSchema.js.map +1 -0
  56. package/dist/core/Storage.d.ts +15 -0
  57. package/dist/core/Storage.d.ts.map +1 -0
  58. package/dist/core/Storage.js +109 -0
  59. package/dist/core/Storage.js.map +1 -0
  60. package/dist/core/Transport.d.ts +23 -0
  61. package/dist/core/Transport.d.ts.map +1 -0
  62. package/dist/core/Transport.js +37 -0
  63. package/dist/core/Transport.js.map +1 -0
  64. package/dist/core/internal/_generated/chains.d.ts +2 -0
  65. package/dist/core/internal/_generated/chains.d.ts.map +1 -0
  66. package/dist/core/internal/_generated/chains.js +3 -0
  67. package/dist/core/internal/_generated/chains.js.map +1 -0
  68. package/dist/core/internal/_generated/contracts/EIP7702Proxy.d.ts +18 -0
  69. package/dist/core/internal/_generated/contracts/EIP7702Proxy.d.ts.map +1 -0
  70. package/dist/core/internal/_generated/contracts/EIP7702Proxy.js +24 -0
  71. package/dist/core/internal/_generated/contracts/EIP7702Proxy.js.map +1 -0
  72. package/dist/core/internal/_generated/contracts/Escrow.d.ts +256 -0
  73. package/dist/core/internal/_generated/contracts/Escrow.d.ts.map +1 -0
  74. package/dist/core/internal/_generated/contracts/Escrow.js +329 -0
  75. package/dist/core/internal/_generated/contracts/Escrow.js.map +1 -0
  76. package/dist/core/internal/_generated/contracts/ExperimentERC20.d.ts +440 -0
  77. package/dist/core/internal/_generated/contracts/ExperimentERC20.d.ts.map +1 -0
  78. package/dist/core/internal/_generated/contracts/ExperimentERC20.js +568 -0
  79. package/dist/core/internal/_generated/contracts/ExperimentERC20.js.map +1 -0
  80. package/dist/core/internal/_generated/contracts/ExperimentERC721.d.ts +456 -0
  81. package/dist/core/internal/_generated/contracts/ExperimentERC721.d.ts.map +1 -0
  82. package/dist/core/internal/_generated/contracts/ExperimentERC721.js +587 -0
  83. package/dist/core/internal/_generated/contracts/ExperimentERC721.js.map +1 -0
  84. package/dist/core/internal/_generated/contracts/GuardedExecutor.d.ts +482 -0
  85. package/dist/core/internal/_generated/contracts/GuardedExecutor.d.ts.map +1 -0
  86. package/dist/core/internal/_generated/contracts/GuardedExecutor.js +622 -0
  87. package/dist/core/internal/_generated/contracts/GuardedExecutor.js.map +1 -0
  88. package/dist/core/internal/_generated/contracts/ICallChecker.d.ts +25 -0
  89. package/dist/core/internal/_generated/contracts/ICallChecker.d.ts.map +1 -0
  90. package/dist/core/internal/_generated/contracts/ICallChecker.js +33 -0
  91. package/dist/core/internal/_generated/contracts/ICallChecker.js.map +1 -0
  92. package/dist/core/internal/_generated/contracts/ICommon.d.ts +3 -0
  93. package/dist/core/internal/_generated/contracts/ICommon.d.ts.map +1 -0
  94. package/dist/core/internal/_generated/contracts/ICommon.js +3 -0
  95. package/dist/core/internal/_generated/contracts/ICommon.js.map +1 -0
  96. package/dist/core/internal/_generated/contracts/IEscrow.d.ts +88 -0
  97. package/dist/core/internal/_generated/contracts/IEscrow.d.ts.map +1 -0
  98. package/dist/core/internal/_generated/contracts/IEscrow.js +113 -0
  99. package/dist/core/internal/_generated/contracts/IEscrow.js.map +1 -0
  100. package/dist/core/internal/_generated/contracts/IFunder.d.ts +61 -0
  101. package/dist/core/internal/_generated/contracts/IFunder.d.ts.map +1 -0
  102. package/dist/core/internal/_generated/contracts/IFunder.js +79 -0
  103. package/dist/core/internal/_generated/contracts/IFunder.js.map +1 -0
  104. package/dist/core/internal/_generated/contracts/IFunderV4.d.ts +34 -0
  105. package/dist/core/internal/_generated/contracts/IFunderV4.d.ts.map +1 -0
  106. package/dist/core/internal/_generated/contracts/IFunderV4.js +44 -0
  107. package/dist/core/internal/_generated/contracts/IFunderV4.js.map +1 -0
  108. package/dist/core/internal/_generated/contracts/IIthacaAccount.d.ts +81 -0
  109. package/dist/core/internal/_generated/contracts/IIthacaAccount.d.ts.map +1 -0
  110. package/dist/core/internal/_generated/contracts/IIthacaAccount.js +106 -0
  111. package/dist/core/internal/_generated/contracts/IIthacaAccount.js.map +1 -0
  112. package/dist/core/internal/_generated/contracts/IOAppCore.d.ts +108 -0
  113. package/dist/core/internal/_generated/contracts/IOAppCore.d.ts.map +1 -0
  114. package/dist/core/internal/_generated/contracts/IOAppCore.js +141 -0
  115. package/dist/core/internal/_generated/contracts/IOAppCore.js.map +1 -0
  116. package/dist/core/internal/_generated/contracts/IOAppMsgInspector.d.ts +33 -0
  117. package/dist/core/internal/_generated/contracts/IOAppMsgInspector.d.ts.map +1 -0
  118. package/dist/core/internal/_generated/contracts/IOAppMsgInspector.js +44 -0
  119. package/dist/core/internal/_generated/contracts/IOAppMsgInspector.js.map +1 -0
  120. package/dist/core/internal/_generated/contracts/IOAppReceiver.d.ts +122 -0
  121. package/dist/core/internal/_generated/contracts/IOAppReceiver.d.ts.map +1 -0
  122. package/dist/core/internal/_generated/contracts/IOAppReceiver.js +160 -0
  123. package/dist/core/internal/_generated/contracts/IOAppReceiver.js.map +1 -0
  124. package/dist/core/internal/_generated/contracts/IOrchestrator.d.ts +71 -0
  125. package/dist/core/internal/_generated/contracts/IOrchestrator.d.ts.map +1 -0
  126. package/dist/core/internal/_generated/contracts/IOrchestrator.js +94 -0
  127. package/dist/core/internal/_generated/contracts/IOrchestrator.js.map +1 -0
  128. package/dist/core/internal/_generated/contracts/ISettler.d.ts +39 -0
  129. package/dist/core/internal/_generated/contracts/ISettler.d.ts.map +1 -0
  130. package/dist/core/internal/_generated/contracts/ISettler.js +51 -0
  131. package/dist/core/internal/_generated/contracts/ISettler.js.map +1 -0
  132. package/dist/core/internal/_generated/contracts/ISigner.d.ts +25 -0
  133. package/dist/core/internal/_generated/contracts/ISigner.d.ts.map +1 -0
  134. package/dist/core/internal/_generated/contracts/ISigner.js +33 -0
  135. package/dist/core/internal/_generated/contracts/ISigner.js.map +1 -0
  136. package/dist/core/internal/_generated/contracts/IthacaAccount.d.ts +1121 -0
  137. package/dist/core/internal/_generated/contracts/IthacaAccount.d.ts.map +1 -0
  138. package/dist/core/internal/_generated/contracts/IthacaAccount.js +1453 -0
  139. package/dist/core/internal/_generated/contracts/IthacaAccount.js.map +1 -0
  140. package/dist/core/internal/_generated/contracts/IthacaAccountNew.d.ts +1121 -0
  141. package/dist/core/internal/_generated/contracts/IthacaAccountNew.d.ts.map +1 -0
  142. package/dist/core/internal/_generated/contracts/IthacaAccountNew.js +1453 -0
  143. package/dist/core/internal/_generated/contracts/IthacaAccountNew.js.map +1 -0
  144. package/dist/core/internal/_generated/contracts/IthacaAccountOld.d.ts +1121 -0
  145. package/dist/core/internal/_generated/contracts/IthacaAccountOld.d.ts.map +1 -0
  146. package/dist/core/internal/_generated/contracts/IthacaAccountOld.js +1453 -0
  147. package/dist/core/internal/_generated/contracts/IthacaAccountOld.js.map +1 -0
  148. package/dist/core/internal/_generated/contracts/LayerZeroSettler.d.ts +621 -0
  149. package/dist/core/internal/_generated/contracts/LayerZeroSettler.d.ts.map +1 -0
  150. package/dist/core/internal/_generated/contracts/LayerZeroSettler.js +810 -0
  151. package/dist/core/internal/_generated/contracts/LayerZeroSettler.js.map +1 -0
  152. package/dist/core/internal/_generated/contracts/LibNonce.d.ts +11 -0
  153. package/dist/core/internal/_generated/contracts/LibNonce.d.ts.map +1 -0
  154. package/dist/core/internal/_generated/contracts/LibNonce.js +14 -0
  155. package/dist/core/internal/_generated/contracts/LibNonce.js.map +1 -0
  156. package/dist/core/internal/_generated/contracts/LibTStack.d.ts +3 -0
  157. package/dist/core/internal/_generated/contracts/LibTStack.d.ts.map +1 -0
  158. package/dist/core/internal/_generated/contracts/LibTStack.js +3 -0
  159. package/dist/core/internal/_generated/contracts/LibTStack.js.map +1 -0
  160. package/dist/core/internal/_generated/contracts/MultiSigSigner.d.ts +157 -0
  161. package/dist/core/internal/_generated/contracts/MultiSigSigner.d.ts.map +1 -0
  162. package/dist/core/internal/_generated/contracts/MultiSigSigner.js +202 -0
  163. package/dist/core/internal/_generated/contracts/MultiSigSigner.js.map +1 -0
  164. package/dist/core/internal/_generated/contracts/OApp.d.ts +314 -0
  165. package/dist/core/internal/_generated/contracts/OApp.d.ts.map +1 -0
  166. package/dist/core/internal/_generated/contracts/OApp.js +411 -0
  167. package/dist/core/internal/_generated/contracts/OApp.js.map +1 -0
  168. package/dist/core/internal/_generated/contracts/OAppCore.d.ts +175 -0
  169. package/dist/core/internal/_generated/contracts/OAppCore.d.ts.map +1 -0
  170. package/dist/core/internal/_generated/contracts/OAppCore.js +228 -0
  171. package/dist/core/internal/_generated/contracts/OAppCore.js.map +1 -0
  172. package/dist/core/internal/_generated/contracts/OAppReceiver.d.ts +302 -0
  173. package/dist/core/internal/_generated/contracts/OAppReceiver.d.ts.map +1 -0
  174. package/dist/core/internal/_generated/contracts/OAppReceiver.js +395 -0
  175. package/dist/core/internal/_generated/contracts/OAppReceiver.js.map +1 -0
  176. package/dist/core/internal/_generated/contracts/OAppSender.d.ts +187 -0
  177. package/dist/core/internal/_generated/contracts/OAppSender.d.ts.map +1 -0
  178. package/dist/core/internal/_generated/contracts/OAppSender.js +244 -0
  179. package/dist/core/internal/_generated/contracts/OAppSender.js.map +1 -0
  180. package/dist/core/internal/_generated/contracts/Orchestrator.d.ts +302 -0
  181. package/dist/core/internal/_generated/contracts/Orchestrator.d.ts.map +1 -0
  182. package/dist/core/internal/_generated/contracts/Orchestrator.js +389 -0
  183. package/dist/core/internal/_generated/contracts/Orchestrator.js.map +1 -0
  184. package/dist/core/internal/_generated/contracts/SimpleFunder.d.ts +413 -0
  185. package/dist/core/internal/_generated/contracts/SimpleFunder.d.ts.map +1 -0
  186. package/dist/core/internal/_generated/contracts/SimpleFunder.js +533 -0
  187. package/dist/core/internal/_generated/contracts/SimpleFunder.js.map +1 -0
  188. package/dist/core/internal/_generated/contracts/SimpleSettler.d.ts +280 -0
  189. package/dist/core/internal/_generated/contracts/SimpleSettler.d.ts.map +1 -0
  190. package/dist/core/internal/_generated/contracts/SimpleSettler.js +359 -0
  191. package/dist/core/internal/_generated/contracts/SimpleSettler.js.map +1 -0
  192. package/dist/core/internal/_generated/contracts/Simulator.d.ts +131 -0
  193. package/dist/core/internal/_generated/contracts/Simulator.d.ts.map +1 -0
  194. package/dist/core/internal/_generated/contracts/Simulator.js +169 -0
  195. package/dist/core/internal/_generated/contracts/Simulator.js.map +1 -0
  196. package/dist/core/internal/_generated/contracts/TokenTransferLib.d.ts +3 -0
  197. package/dist/core/internal/_generated/contracts/TokenTransferLib.d.ts.map +1 -0
  198. package/dist/core/internal/_generated/contracts/TokenTransferLib.js +3 -0
  199. package/dist/core/internal/_generated/contracts/TokenTransferLib.js.map +1 -0
  200. package/dist/core/internal/call.d.ts +164 -0
  201. package/dist/core/internal/call.d.ts.map +1 -0
  202. package/dist/core/internal/call.js +115 -0
  203. package/dist/core/internal/call.js.map +1 -0
  204. package/dist/core/internal/erc8010.d.ts +18 -0
  205. package/dist/core/internal/erc8010.d.ts.map +1 -0
  206. package/dist/core/internal/erc8010.js +29 -0
  207. package/dist/core/internal/erc8010.js.map +1 -0
  208. package/dist/core/internal/intersectionObserver.d.ts +2 -0
  209. package/dist/core/internal/intersectionObserver.d.ts.map +1 -0
  210. package/dist/core/internal/intersectionObserver.js +5 -0
  211. package/dist/core/internal/intersectionObserver.js.map +1 -0
  212. package/dist/core/internal/logger.d.ts +22 -0
  213. package/dist/core/internal/logger.d.ts.map +1 -0
  214. package/dist/core/internal/logger.js +24 -0
  215. package/dist/core/internal/logger.js.map +1 -0
  216. package/dist/core/internal/mode.d.ts +345 -0
  217. package/dist/core/internal/mode.d.ts.map +1 -0
  218. package/dist/core/internal/mode.js +110 -0
  219. package/dist/core/internal/mode.js.map +1 -0
  220. package/dist/core/internal/modes/dialog.d.ts +800 -0
  221. package/dist/core/internal/modes/dialog.d.ts.map +1 -0
  222. package/dist/core/internal/modes/dialog.js +760 -0
  223. package/dist/core/internal/modes/dialog.js.map +1 -0
  224. package/dist/core/internal/modes/reactNative.d.ts +1402 -0
  225. package/dist/core/internal/modes/reactNative.d.ts.map +1 -0
  226. package/dist/core/internal/modes/reactNative.js +19 -0
  227. package/dist/core/internal/modes/reactNative.js.map +1 -0
  228. package/dist/core/internal/modes/relay.d.ts +685 -0
  229. package/dist/core/internal/modes/relay.d.ts.map +1 -0
  230. package/dist/core/internal/modes/relay.js +708 -0
  231. package/dist/core/internal/modes/relay.js.map +1 -0
  232. package/dist/core/internal/permissions.d.ts +60 -0
  233. package/dist/core/internal/permissions.d.ts.map +1 -0
  234. package/dist/core/internal/permissions.js +30 -0
  235. package/dist/core/internal/permissions.js.map +1 -0
  236. package/dist/core/internal/permissionsRequest.d.ts +72 -0
  237. package/dist/core/internal/permissionsRequest.d.ts.map +1 -0
  238. package/dist/core/internal/permissionsRequest.js +58 -0
  239. package/dist/core/internal/permissionsRequest.js.map +1 -0
  240. package/dist/core/internal/porto.d.ts +14 -0
  241. package/dist/core/internal/porto.d.ts.map +1 -0
  242. package/dist/core/internal/porto.js +2 -0
  243. package/dist/core/internal/porto.js.map +1 -0
  244. package/dist/core/internal/promise.d.ts +9 -0
  245. package/dist/core/internal/promise.d.ts.map +1 -0
  246. package/dist/core/internal/promise.js +11 -0
  247. package/dist/core/internal/promise.js.map +1 -0
  248. package/dist/core/internal/provider.d.ts +30 -0
  249. package/dist/core/internal/provider.d.ts.map +1 -0
  250. package/dist/core/internal/provider.js +944 -0
  251. package/dist/core/internal/provider.js.map +1 -0
  252. package/dist/core/internal/relay/rpcSchema.d.ts +76 -0
  253. package/dist/core/internal/relay/rpcSchema.d.ts.map +1 -0
  254. package/dist/core/internal/relay/rpcSchema.js +7 -0
  255. package/dist/core/internal/relay/rpcSchema.js.map +1 -0
  256. package/dist/core/internal/relay/schema/capabilities.d.ts +165 -0
  257. package/dist/core/internal/relay/schema/capabilities.d.ts.map +1 -0
  258. package/dist/core/internal/relay/schema/capabilities.js +112 -0
  259. package/dist/core/internal/relay/schema/capabilities.js.map +1 -0
  260. package/dist/core/internal/relay/schema/intent.d.ts +168 -0
  261. package/dist/core/internal/relay/schema/intent.d.ts.map +1 -0
  262. package/dist/core/internal/relay/schema/intent.js +170 -0
  263. package/dist/core/internal/relay/schema/intent.js.map +1 -0
  264. package/dist/core/internal/relay/schema/key.d.ts +44 -0
  265. package/dist/core/internal/relay/schema/key.d.ts.map +1 -0
  266. package/dist/core/internal/relay/schema/key.js +30 -0
  267. package/dist/core/internal/relay/schema/key.js.map +1 -0
  268. package/dist/core/internal/relay/schema/permission.d.ts +40 -0
  269. package/dist/core/internal/relay/schema/permission.d.ts.map +1 -0
  270. package/dist/core/internal/relay/schema/permission.js +29 -0
  271. package/dist/core/internal/relay/schema/permission.js.map +1 -0
  272. package/dist/core/internal/relay/schema/preCall.d.ts +63 -0
  273. package/dist/core/internal/relay/schema/preCall.d.ts.map +1 -0
  274. package/dist/core/internal/relay/schema/preCall.js +36 -0
  275. package/dist/core/internal/relay/schema/preCall.js.map +1 -0
  276. package/dist/core/internal/relay/schema/quotes.d.ts +370 -0
  277. package/dist/core/internal/relay/schema/quotes.d.ts.map +1 -0
  278. package/dist/core/internal/relay/schema/quotes.js +89 -0
  279. package/dist/core/internal/relay/schema/quotes.js.map +1 -0
  280. package/dist/core/internal/relay/schema/rpc.d.ts +1529 -0
  281. package/dist/core/internal/relay/schema/rpc.d.ts.map +1 -0
  282. package/dist/core/internal/relay/schema/rpc.js +638 -0
  283. package/dist/core/internal/relay/schema/rpc.js.map +1 -0
  284. package/dist/core/internal/relay/schema/token.d.ts +14 -0
  285. package/dist/core/internal/relay/schema/token.d.ts.map +1 -0
  286. package/dist/core/internal/relay/schema/token.js +13 -0
  287. package/dist/core/internal/relay/schema/token.js.map +1 -0
  288. package/dist/core/internal/requiredFunds.d.ts +19 -0
  289. package/dist/core/internal/requiredFunds.d.ts.map +1 -0
  290. package/dist/core/internal/requiredFunds.js +25 -0
  291. package/dist/core/internal/requiredFunds.js.map +1 -0
  292. package/dist/core/internal/schema/capabilities.d.ts +314 -0
  293. package/dist/core/internal/schema/capabilities.d.ts.map +1 -0
  294. package/dist/core/internal/schema/capabilities.js +133 -0
  295. package/dist/core/internal/schema/capabilities.js.map +1 -0
  296. package/dist/core/internal/schema/key.d.ts +165 -0
  297. package/dist/core/internal/schema/key.d.ts.map +1 -0
  298. package/dist/core/internal/schema/key.js +75 -0
  299. package/dist/core/internal/schema/key.js.map +1 -0
  300. package/dist/core/internal/schema/permissions.d.ts +103 -0
  301. package/dist/core/internal/schema/permissions.d.ts.map +1 -0
  302. package/dist/core/internal/schema/permissions.js +28 -0
  303. package/dist/core/internal/schema/permissions.js.map +1 -0
  304. package/dist/core/internal/schema/request.d.ts +938 -0
  305. package/dist/core/internal/schema/request.d.ts.map +1 -0
  306. package/dist/core/internal/schema/request.js +57 -0
  307. package/dist/core/internal/schema/request.js.map +1 -0
  308. package/dist/core/internal/schema/rpc.d.ts +3315 -0
  309. package/dist/core/internal/schema/rpc.d.ts.map +1 -0
  310. package/dist/core/internal/schema/rpc.js +599 -0
  311. package/dist/core/internal/schema/rpc.js.map +1 -0
  312. package/dist/core/internal/schema/token.d.ts +2 -0
  313. package/dist/core/internal/schema/token.d.ts.map +1 -0
  314. package/dist/core/internal/schema/token.js +2 -0
  315. package/dist/core/internal/schema/token.js.map +1 -0
  316. package/dist/core/internal/schema/utils.d.ts +19 -0
  317. package/dist/core/internal/schema/utils.d.ts.map +1 -0
  318. package/dist/core/internal/schema/utils.js +213 -0
  319. package/dist/core/internal/schema/utils.js.map +1 -0
  320. package/dist/core/internal/siwe.d.ts +33 -0
  321. package/dist/core/internal/siwe.d.ts.map +1 -0
  322. package/dist/core/internal/siwe.js +92 -0
  323. package/dist/core/internal/siwe.js.map +1 -0
  324. package/dist/core/internal/store.d.ts +3 -0
  325. package/dist/core/internal/store.d.ts.map +1 -0
  326. package/dist/core/internal/store.js +9 -0
  327. package/dist/core/internal/store.js.map +1 -0
  328. package/dist/core/internal/tokens.d.ts +58 -0
  329. package/dist/core/internal/tokens.d.ts.map +1 -0
  330. package/dist/core/internal/tokens.js +69 -0
  331. package/dist/core/internal/tokens.js.map +1 -0
  332. package/dist/core/internal/types.d.ts +299 -0
  333. package/dist/core/internal/types.d.ts.map +1 -0
  334. package/dist/core/internal/types.js +2 -0
  335. package/dist/core/internal/types.js.map +1 -0
  336. package/dist/core/internal/urlString.d.ts +2 -0
  337. package/dist/core/internal/urlString.d.ts.map +1 -0
  338. package/dist/core/internal/urlString.js +8 -0
  339. package/dist/core/internal/urlString.js.map +1 -0
  340. package/dist/core/internal/userAgent.d.ts +11 -0
  341. package/dist/core/internal/userAgent.d.ts.map +1 -0
  342. package/dist/core/internal/userAgent.js +19 -0
  343. package/dist/core/internal/userAgent.js.map +1 -0
  344. package/dist/core/internal/utils.d.ts +25 -0
  345. package/dist/core/internal/utils.d.ts.map +1 -0
  346. package/dist/core/internal/utils.js +62 -0
  347. package/dist/core/internal/utils.js.map +1 -0
  348. package/dist/core/react-native/Porto.d.ts +1481 -0
  349. package/dist/core/react-native/Porto.d.ts.map +1 -0
  350. package/dist/core/react-native/Porto.js +17 -0
  351. package/dist/core/react-native/Porto.js.map +1 -0
  352. package/dist/core/react-native/configure.d.ts +10 -0
  353. package/dist/core/react-native/configure.d.ts.map +1 -0
  354. package/dist/core/react-native/configure.js +24 -0
  355. package/dist/core/react-native/configure.js.map +1 -0
  356. package/dist/core/react-native/environment.d.ts +27 -0
  357. package/dist/core/react-native/environment.d.ts.map +1 -0
  358. package/dist/core/react-native/environment.js +13 -0
  359. package/dist/core/react-native/environment.js.map +1 -0
  360. package/dist/core/react-native/index.d.ts +5 -0
  361. package/dist/core/react-native/index.d.ts.map +1 -0
  362. package/dist/core/react-native/index.js +5 -0
  363. package/dist/core/react-native/index.js.map +1 -0
  364. package/dist/core/react-native/utils.d.ts +2 -0
  365. package/dist/core/react-native/utils.d.ts.map +1 -0
  366. package/dist/core/react-native/utils.js +12 -0
  367. package/dist/core/react-native/utils.js.map +1 -0
  368. package/dist/index.d.ts +17 -2
  369. package/dist/index.d.ts.map +1 -0
  370. package/dist/index.js +15 -2
  371. package/dist/index.js.map +1 -0
  372. package/dist/index.native.d.ts +8 -0
  373. package/dist/index.native.d.ts.map +1 -0
  374. package/dist/index.native.js +12 -0
  375. package/dist/index.native.js.map +1 -0
  376. package/dist/internal/index.d.ts +4 -0
  377. package/dist/internal/index.d.ts.map +1 -0
  378. package/dist/internal/index.js +4 -0
  379. package/dist/internal/index.js.map +1 -0
  380. package/dist/react-native/crypto.d.ts +2 -0
  381. package/dist/react-native/crypto.d.ts.map +1 -0
  382. package/dist/react-native/crypto.js +12 -0
  383. package/dist/react-native/crypto.js.map +1 -0
  384. package/dist/react-native/index.d.ts +8 -0
  385. package/dist/react-native/index.d.ts.map +1 -0
  386. package/dist/react-native/index.js +12 -0
  387. package/dist/react-native/index.js.map +1 -0
  388. package/dist/react-native/register.d.ts +3 -0
  389. package/dist/react-native/register.d.ts.map +1 -0
  390. package/dist/react-native/register.js +15 -0
  391. package/dist/react-native/register.js.map +1 -0
  392. package/dist/register/index.d.ts +15 -0
  393. package/dist/register/index.d.ts.map +1 -0
  394. package/dist/register/index.js +2 -0
  395. package/dist/register/index.js.map +1 -0
  396. package/dist/remote/Actions.d.ts +34 -0
  397. package/dist/remote/Actions.d.ts.map +1 -0
  398. package/dist/remote/Actions.js +76 -0
  399. package/dist/remote/Actions.js.map +1 -0
  400. package/dist/remote/Events.d.ts +47 -0
  401. package/dist/remote/Events.d.ts.map +1 -0
  402. package/dist/remote/Events.js +132 -0
  403. package/dist/remote/Events.js.map +1 -0
  404. package/dist/remote/Hooks.d.ts +3801 -0
  405. package/dist/remote/Hooks.d.ts.map +1 -0
  406. package/dist/remote/Hooks.js +106 -0
  407. package/dist/remote/Hooks.js.map +1 -0
  408. package/dist/remote/Porto.d.ts +858 -0
  409. package/dist/remote/Porto.d.ts.map +1 -0
  410. package/dist/remote/Porto.js +66 -0
  411. package/dist/remote/Porto.js.map +1 -0
  412. package/dist/remote/index.d.ts +5 -0
  413. package/dist/remote/index.d.ts.map +1 -0
  414. package/dist/remote/index.js +5 -0
  415. package/dist/remote/index.js.map +1 -0
  416. package/dist/remote/internal/methodPolicies.d.ts +97 -0
  417. package/dist/remote/internal/methodPolicies.d.ts.map +1 -0
  418. package/dist/remote/internal/methodPolicies.js +102 -0
  419. package/dist/remote/internal/methodPolicies.js.map +1 -0
  420. package/dist/server/Route.d.ts +88 -0
  421. package/dist/server/Route.d.ts.map +1 -0
  422. package/dist/server/Route.js +189 -0
  423. package/dist/server/Route.js.map +1 -0
  424. package/dist/server/Router.d.ts +24 -0
  425. package/dist/server/Router.d.ts.map +1 -0
  426. package/dist/server/Router.js +29 -0
  427. package/dist/server/Router.js.map +1 -0
  428. package/dist/server/index.d.ts +3 -0
  429. package/dist/server/index.d.ts.map +1 -0
  430. package/dist/server/index.js +3 -0
  431. package/dist/server/index.js.map +1 -0
  432. package/dist/server/internal/merchantSchema.d.ts +65 -0
  433. package/dist/server/internal/merchantSchema.d.ts.map +1 -0
  434. package/dist/server/internal/merchantSchema.js +7 -0
  435. package/dist/server/internal/merchantSchema.js.map +1 -0
  436. package/dist/server/internal/requestListener.d.ts +124 -0
  437. package/dist/server/internal/requestListener.d.ts.map +1 -0
  438. package/dist/server/internal/requestListener.js +172 -0
  439. package/dist/server/internal/requestListener.js.map +1 -0
  440. package/dist/theme/Theme.d.ts +122 -0
  441. package/dist/theme/Theme.d.ts.map +1 -0
  442. package/dist/theme/Theme.js +18 -0
  443. package/dist/theme/Theme.js.map +1 -0
  444. package/dist/theme/index.d.ts +3 -0
  445. package/dist/theme/index.d.ts.map +1 -0
  446. package/dist/theme/index.js +2 -0
  447. package/dist/theme/index.js.map +1 -0
  448. package/dist/trusted-hosts.d.ts +2 -0
  449. package/dist/trusted-hosts.d.ts.map +1 -0
  450. package/dist/trusted-hosts.js +44 -0
  451. package/dist/trusted-hosts.js.map +1 -0
  452. package/dist/tsconfig.tmp.tsbuildinfo +1 -0
  453. package/dist/viem/Account.d.ts +111 -0
  454. package/dist/viem/Account.d.ts.map +1 -0
  455. package/dist/viem/Account.js +132 -0
  456. package/dist/viem/Account.js.map +1 -0
  457. package/dist/viem/AccountActions.d.ts +11 -0
  458. package/dist/viem/AccountActions.d.ts.map +1 -0
  459. package/dist/viem/AccountActions.js +14 -0
  460. package/dist/viem/AccountActions.js.map +1 -0
  461. package/dist/viem/CapabilitiesSchema.d.ts +15 -0
  462. package/dist/viem/CapabilitiesSchema.d.ts.map +1 -0
  463. package/dist/viem/CapabilitiesSchema.js +2 -0
  464. package/dist/viem/CapabilitiesSchema.js.map +1 -0
  465. package/dist/viem/ContractActions.d.ts +209 -0
  466. package/dist/viem/ContractActions.d.ts.map +1 -0
  467. package/dist/viem/ContractActions.js +350 -0
  468. package/dist/viem/ContractActions.js.map +1 -0
  469. package/dist/viem/Key.d.ts +1156 -0
  470. package/dist/viem/Key.d.ts.map +1 -0
  471. package/dist/viem/Key.js +924 -0
  472. package/dist/viem/Key.js.map +1 -0
  473. package/dist/viem/RelayActions.d.ts +436 -0
  474. package/dist/viem/RelayActions.d.ts.map +1 -0
  475. package/dist/viem/RelayActions.js +385 -0
  476. package/dist/viem/RelayActions.js.map +1 -0
  477. package/dist/viem/RelayClient.d.ts +27 -0
  478. package/dist/viem/RelayClient.d.ts.map +1 -0
  479. package/dist/viem/RelayClient.js +44 -0
  480. package/dist/viem/RelayClient.js.map +1 -0
  481. package/dist/viem/RpcSchema.d.ts +23 -0
  482. package/dist/viem/RpcSchema.d.ts.map +1 -0
  483. package/dist/viem/RpcSchema.js +2 -0
  484. package/dist/viem/RpcSchema.js.map +1 -0
  485. package/dist/viem/WalletActions.d.ts +87 -0
  486. package/dist/viem/WalletActions.d.ts.map +1 -0
  487. package/dist/viem/WalletActions.js +220 -0
  488. package/dist/viem/WalletActions.js.map +1 -0
  489. package/dist/viem/WalletClient.d.ts +21 -0
  490. package/dist/viem/WalletClient.d.ts.map +1 -0
  491. package/dist/viem/WalletClient.js +23 -0
  492. package/dist/viem/WalletClient.js.map +1 -0
  493. package/dist/viem/index.d.ts +14 -0
  494. package/dist/viem/index.d.ts.map +1 -0
  495. package/dist/viem/index.js +12 -0
  496. package/dist/viem/index.js.map +1 -0
  497. package/dist/viem/internal/relayActions.d.ts +365 -0
  498. package/dist/viem/internal/relayActions.d.ts.map +1 -0
  499. package/dist/viem/internal/relayActions.js +783 -0
  500. package/dist/viem/internal/relayActions.js.map +1 -0
  501. package/dist/viem/internal/utils.d.ts +16 -0
  502. package/dist/viem/internal/utils.d.ts.map +1 -0
  503. package/dist/viem/internal/utils.js +2 -0
  504. package/dist/viem/internal/utils.js.map +1 -0
  505. package/dist/wagmi/Actions.d.ts +2 -0
  506. package/dist/wagmi/Actions.d.ts.map +1 -0
  507. package/dist/wagmi/Actions.js +2 -0
  508. package/dist/wagmi/Actions.js.map +1 -0
  509. package/dist/wagmi/Connector.d.ts +28 -0
  510. package/dist/wagmi/Connector.d.ts.map +1 -0
  511. package/dist/wagmi/Connector.js +238 -0
  512. package/dist/wagmi/Connector.js.map +1 -0
  513. package/dist/wagmi/Hooks.d.ts +2 -0
  514. package/dist/wagmi/Hooks.d.ts.map +1 -0
  515. package/dist/wagmi/Hooks.js +2 -0
  516. package/dist/wagmi/Hooks.js.map +1 -0
  517. package/dist/wagmi/Hooks.native.d.ts +3 -0
  518. package/dist/wagmi/Hooks.native.d.ts.map +1 -0
  519. package/dist/wagmi/Hooks.native.js +3 -0
  520. package/dist/wagmi/Hooks.native.js.map +1 -0
  521. package/dist/wagmi/Query.d.ts +2 -0
  522. package/dist/wagmi/Query.d.ts.map +1 -0
  523. package/dist/wagmi/Query.js +2 -0
  524. package/dist/wagmi/Query.js.map +1 -0
  525. package/dist/wagmi/index.d.ts +5 -0
  526. package/dist/wagmi/index.d.ts.map +1 -0
  527. package/dist/wagmi/index.js +5 -0
  528. package/dist/wagmi/index.js.map +1 -0
  529. package/dist/wagmi/index.native.d.ts +6 -0
  530. package/dist/wagmi/index.native.d.ts.map +1 -0
  531. package/dist/wagmi/index.native.js +6 -0
  532. package/dist/wagmi/index.native.js.map +1 -0
  533. package/dist/wagmi/internal/core.d.ts +84 -0
  534. package/dist/wagmi/internal/core.d.ts.map +1 -0
  535. package/dist/wagmi/internal/core.js +229 -0
  536. package/dist/wagmi/internal/core.js.map +1 -0
  537. package/dist/wagmi/internal/query.d.ts +33 -0
  538. package/dist/wagmi/internal/query.d.ts.map +1 -0
  539. package/dist/wagmi/internal/query.js +23 -0
  540. package/dist/wagmi/internal/query.js.map +1 -0
  541. package/dist/wagmi/internal/react.d.ts +91 -0
  542. package/dist/wagmi/internal/react.d.ts.map +1 -0
  543. package/dist/wagmi/internal/react.js +256 -0
  544. package/dist/wagmi/internal/react.js.map +1 -0
  545. package/dist/wagmi/internal/types.d.ts +11 -0
  546. package/dist/wagmi/internal/types.d.ts.map +1 -0
  547. package/dist/wagmi/internal/types.js +2 -0
  548. package/dist/wagmi/internal/types.js.map +1 -0
  549. package/dist/wagmi/internal/utils.d.ts +2 -0
  550. package/dist/wagmi/internal/utils.d.ts.map +1 -0
  551. package/dist/wagmi/internal/utils.js +18 -0
  552. package/dist/wagmi/internal/utils.js.map +1 -0
  553. package/package.json +287 -34
  554. package/src/cli/Dialog.ts +75 -0
  555. package/src/cli/Messenger.ts +148 -0
  556. package/src/cli/bin/index.ts +37 -0
  557. package/src/cli/bin/tsconfig.json +8 -0
  558. package/src/cli/index.ts +2 -0
  559. package/src/cli/internal/commands.ts +216 -0
  560. package/src/cli/internal/context.ts +56 -0
  561. package/src/cli/internal/http.ts +28 -0
  562. package/src/cli/internal/utils.ts +28 -0
  563. package/src/cli/tsdown.config.ts +37 -0
  564. package/src/core/Chains.ts +25 -0
  565. package/src/core/Dialog.ts +1059 -0
  566. package/src/core/Messenger.ts +394 -0
  567. package/src/core/Mode.ts +4 -0
  568. package/src/core/Porto.ts +287 -0
  569. package/src/core/RpcSchema.ts +124 -0
  570. package/src/core/Storage.ts +122 -0
  571. package/src/core/Transport.ts +45 -0
  572. package/src/core/internal/_generated/chains.ts +2 -0
  573. package/src/core/internal/_generated/contracts/EIP7702Proxy.ts +25 -0
  574. package/src/core/internal/_generated/contracts/Escrow.ts +330 -0
  575. package/src/core/internal/_generated/contracts/ExperimentERC20.ts +569 -0
  576. package/src/core/internal/_generated/contracts/ExperimentERC721.ts +588 -0
  577. package/src/core/internal/_generated/contracts/GuardedExecutor.ts +623 -0
  578. package/src/core/internal/_generated/contracts/ICallChecker.ts +34 -0
  579. package/src/core/internal/_generated/contracts/ICommon.ts +4 -0
  580. package/src/core/internal/_generated/contracts/IEscrow.ts +114 -0
  581. package/src/core/internal/_generated/contracts/IFunder.ts +80 -0
  582. package/src/core/internal/_generated/contracts/IFunderV4.ts +45 -0
  583. package/src/core/internal/_generated/contracts/IIthacaAccount.ts +107 -0
  584. package/src/core/internal/_generated/contracts/IOAppCore.ts +142 -0
  585. package/src/core/internal/_generated/contracts/IOAppMsgInspector.ts +45 -0
  586. package/src/core/internal/_generated/contracts/IOAppReceiver.ts +161 -0
  587. package/src/core/internal/_generated/contracts/IOrchestrator.ts +95 -0
  588. package/src/core/internal/_generated/contracts/ISettler.ts +52 -0
  589. package/src/core/internal/_generated/contracts/ISigner.ts +34 -0
  590. package/src/core/internal/_generated/contracts/IthacaAccount.ts +1454 -0
  591. package/src/core/internal/_generated/contracts/IthacaAccountNew.ts +1454 -0
  592. package/src/core/internal/_generated/contracts/IthacaAccountOld.ts +1454 -0
  593. package/src/core/internal/_generated/contracts/LayerZeroSettler.ts +811 -0
  594. package/src/core/internal/_generated/contracts/LibNonce.ts +15 -0
  595. package/src/core/internal/_generated/contracts/LibTStack.ts +4 -0
  596. package/src/core/internal/_generated/contracts/MultiSigSigner.ts +203 -0
  597. package/src/core/internal/_generated/contracts/OApp.ts +412 -0
  598. package/src/core/internal/_generated/contracts/OAppCore.ts +229 -0
  599. package/src/core/internal/_generated/contracts/OAppReceiver.ts +396 -0
  600. package/src/core/internal/_generated/contracts/OAppSender.ts +245 -0
  601. package/src/core/internal/_generated/contracts/Orchestrator.ts +390 -0
  602. package/src/core/internal/_generated/contracts/SimpleFunder.ts +534 -0
  603. package/src/core/internal/_generated/contracts/SimpleSettler.ts +360 -0
  604. package/src/core/internal/_generated/contracts/Simulator.ts +170 -0
  605. package/src/core/internal/_generated/contracts/TokenTransferLib.ts +4 -0
  606. package/src/core/internal/_snapshots/provider.browser.test.ts.snap +119 -0
  607. package/src/core/internal/_snapshots/provider.test.ts.snap +1103 -0
  608. package/src/core/internal/call.test.ts +116 -0
  609. package/src/core/internal/call.ts +245 -0
  610. package/src/core/internal/erc8010.test.ts +74 -0
  611. package/src/core/internal/erc8010.ts +44 -0
  612. package/src/core/internal/intersectionObserver.ts +5 -0
  613. package/src/core/internal/logger.ts +42 -0
  614. package/src/core/internal/mode.ts +498 -0
  615. package/src/core/internal/modes/dialog.ts +1051 -0
  616. package/src/core/internal/modes/reactNative.ts +29 -0
  617. package/src/core/internal/modes/relay.ts +893 -0
  618. package/src/core/internal/permissions.ts +43 -0
  619. package/src/core/internal/permissionsRequest.ts +88 -0
  620. package/src/core/internal/porto.ts +16 -0
  621. package/src/core/internal/promise.ts +19 -0
  622. package/src/core/internal/provider.browser.test.ts +311 -0
  623. package/src/core/internal/provider.test.ts +3552 -0
  624. package/src/core/internal/provider.ts +1278 -0
  625. package/src/core/internal/relay/rpcSchema.ts +101 -0
  626. package/src/core/internal/relay/schema/capabilities.test.ts +663 -0
  627. package/src/core/internal/relay/schema/capabilities.ts +156 -0
  628. package/src/core/internal/relay/schema/intent.test.ts +433 -0
  629. package/src/core/internal/relay/schema/intent.ts +174 -0
  630. package/src/core/internal/relay/schema/key.test.ts +424 -0
  631. package/src/core/internal/relay/schema/key.ts +34 -0
  632. package/src/core/internal/relay/schema/permission.test.ts +499 -0
  633. package/src/core/internal/relay/schema/permission.ts +34 -0
  634. package/src/core/internal/relay/schema/preCall.ts +39 -0
  635. package/src/core/internal/relay/schema/quotes.test.ts +901 -0
  636. package/src/core/internal/relay/schema/quotes.ts +98 -0
  637. package/src/core/internal/relay/schema/rpc.ts +822 -0
  638. package/src/core/internal/relay/schema/token.ts +16 -0
  639. package/src/core/internal/requiredFunds.test.ts +141 -0
  640. package/src/core/internal/requiredFunds.ts +45 -0
  641. package/src/core/internal/schema/capabilities.test.ts +1334 -0
  642. package/src/core/internal/schema/capabilities.ts +162 -0
  643. package/src/core/internal/schema/key.test.ts +570 -0
  644. package/src/core/internal/schema/key.ts +98 -0
  645. package/src/core/internal/schema/permissions.test.ts +948 -0
  646. package/src/core/internal/schema/permissions.ts +31 -0
  647. package/src/core/internal/schema/request.bench.ts +35 -0
  648. package/src/core/internal/schema/request.ts +90 -0
  649. package/src/core/internal/schema/rpc.ts +821 -0
  650. package/src/core/internal/schema/token.ts +1 -0
  651. package/src/core/internal/schema/utils.test.ts +572 -0
  652. package/src/core/internal/schema/utils.ts +236 -0
  653. package/src/core/internal/siwe.test.ts +473 -0
  654. package/src/core/internal/siwe.ts +144 -0
  655. package/src/core/internal/store.ts +9 -0
  656. package/src/core/internal/tokens.test.ts +317 -0
  657. package/src/core/internal/tokens.ts +125 -0
  658. package/src/core/internal/types.ts +448 -0
  659. package/src/core/internal/urlString.ts +5 -0
  660. package/src/core/internal/userAgent.ts +35 -0
  661. package/src/core/internal/utils.test.ts +35 -0
  662. package/src/core/internal/utils.ts +67 -0
  663. package/src/core/react-native/Porto.ts +22 -0
  664. package/src/core/react-native/configure.ts +31 -0
  665. package/src/core/react-native/environment.ts +43 -0
  666. package/src/core/react-native/index.ts +4 -0
  667. package/src/core/react-native/utils.ts +18 -0
  668. package/src/index.native.ts +15 -0
  669. package/src/index.ts +17 -0
  670. package/src/internal/index.ts +3 -0
  671. package/src/react-native/crypto.ts +19 -0
  672. package/src/react-native/index.ts +15 -0
  673. package/src/react-native/register.ts +24 -0
  674. package/src/register/index.ts +17 -0
  675. package/src/remote/Actions.ts +115 -0
  676. package/src/remote/Events.ts +193 -0
  677. package/src/remote/Hooks.ts +194 -0
  678. package/src/remote/Porto.ts +144 -0
  679. package/src/remote/index.ts +4 -0
  680. package/src/remote/internal/methodPolicies.ts +124 -0
  681. package/src/server/Route.test.ts +347 -0
  682. package/src/server/Route.ts +259 -0
  683. package/src/server/Router.test.ts +32 -0
  684. package/src/server/Router.ts +59 -0
  685. package/src/server/index.ts +2 -0
  686. package/src/server/internal/merchantSchema.ts +11 -0
  687. package/src/server/internal/requestListener.ts +284 -0
  688. package/src/theme/Theme.ts +163 -0
  689. package/src/theme/index.ts +2 -0
  690. package/src/trusted-hosts.ts +43 -0
  691. package/src/tsconfig.build.tsbuildinfo +1 -0
  692. package/src/tsconfig.json +15 -0
  693. package/src/viem/Account.test.ts +270 -0
  694. package/src/viem/Account.ts +278 -0
  695. package/src/viem/AccountActions.test.ts +3 -0
  696. package/src/viem/AccountActions.ts +30 -0
  697. package/src/viem/CapabilitiesSchema.ts +18 -0
  698. package/src/viem/ContractActions.test.ts +980 -0
  699. package/src/viem/ContractActions.ts +624 -0
  700. package/src/viem/Key.test.ts +1420 -0
  701. package/src/viem/Key.ts +1318 -0
  702. package/src/viem/RelayActions.test.ts +1730 -0
  703. package/src/viem/RelayActions.ts +1082 -0
  704. package/src/viem/RelayClient.test.ts +127 -0
  705. package/src/viem/RelayClient.ts +87 -0
  706. package/src/viem/RpcSchema.ts +27 -0
  707. package/src/viem/WalletActions.test.ts +646 -0
  708. package/src/viem/WalletActions.ts +476 -0
  709. package/src/viem/WalletClient.test.ts +36 -0
  710. package/src/viem/WalletClient.ts +74 -0
  711. package/src/viem/index.ts +13 -0
  712. package/src/viem/internal/relayActions.test.ts +1296 -0
  713. package/src/viem/internal/relayActions.ts +1222 -0
  714. package/src/viem/internal/utils.ts +27 -0
  715. package/src/wagmi/Actions.ts +13 -0
  716. package/src/wagmi/Connector.ts +306 -0
  717. package/src/wagmi/Hooks.native.ts +16 -0
  718. package/src/wagmi/Hooks.ts +14 -0
  719. package/src/wagmi/Query.ts +5 -0
  720. package/src/wagmi/index.native.ts +6 -0
  721. package/src/wagmi/index.ts +4 -0
  722. package/src/wagmi/internal/core.test.ts +12 -0
  723. package/src/wagmi/internal/core.ts +468 -0
  724. package/src/wagmi/internal/query.ts +52 -0
  725. package/src/wagmi/internal/react.test.ts +12 -0
  726. package/src/wagmi/internal/react.ts +705 -0
  727. package/src/wagmi/internal/types.ts +21 -0
  728. package/src/wagmi/internal/utils.ts +25 -0
  729. package/dist/chain.cjs +0 -17
  730. package/dist/chain.d.cts +0 -41
  731. package/dist/chain.d.ts +0 -41
  732. package/dist/chain.js +0 -13
  733. package/dist/config.cjs +0 -19
  734. package/dist/config.d.cts +0 -3
  735. package/dist/config.d.ts +0 -3
  736. package/dist/config.js +0 -16
  737. package/dist/index.cjs +0 -18
  738. package/dist/index.d.cts +0 -2
@@ -0,0 +1,3552 @@
1
+ import {
2
+ Address,
3
+ Hex,
4
+ P256,
5
+ PublicKey,
6
+ Secp256k1,
7
+ Signature,
8
+ TypedData,
9
+ Value,
10
+ WebCryptoP256,
11
+ } from 'ox'
12
+ import { Key, Mode } from 'porto'
13
+ import { Route } from 'porto/server'
14
+ import { encodeFunctionData, hashMessage, hashTypedData } from 'viem'
15
+ import {
16
+ readContract,
17
+ setCode,
18
+ signTypedData,
19
+ verifyHash,
20
+ setBalance as viem_setBalance,
21
+ waitForCallsStatus,
22
+ waitForTransactionReceipt,
23
+ } from 'viem/actions'
24
+ import { describe, expect, test } from 'vitest'
25
+
26
+ import { accountOldProxyAddress } from '../../../test/src/_generated/addresses.js'
27
+ import { createAccount, setBalance } from '../../../test/src/actions.js'
28
+ import * as Anvil from '../../../test/src/anvil.js'
29
+ import * as TestConfig from '../../../test/src/config.js'
30
+ import * as Http from '../../../test/src/http.js'
31
+ import * as RelayActions from '../../viem/RelayActions.js'
32
+ import * as RelayClient from '../../viem/RelayClient.js'
33
+ import * as WalletClient from '../../viem/WalletClient.js'
34
+
35
+ describe.each([['relay', Mode.relay]] as const)('%s', (type, mode) => {
36
+ if (!mode) return
37
+
38
+ const getPorto = (
39
+ config: {
40
+ merchantUrl?: string | undefined
41
+ relayRpcUrl?: string | undefined
42
+ } = {},
43
+ ) =>
44
+ TestConfig.getPorto({
45
+ ...config,
46
+ mode,
47
+ })
48
+
49
+ describe('eth_accounts', () => {
50
+ test('default', async () => {
51
+ const porto = getPorto()
52
+ await porto.provider.request({
53
+ method: 'wallet_connect',
54
+ params: [
55
+ {
56
+ capabilities: {
57
+ createAccount: true,
58
+ },
59
+ },
60
+ ],
61
+ })
62
+
63
+ const accounts = await porto.provider.request({
64
+ method: 'eth_accounts',
65
+ })
66
+ expect(accounts.length).toBe(1)
67
+ })
68
+
69
+ test('behavior: disconnected', async () => {
70
+ const porto = getPorto()
71
+ await expect(
72
+ porto.provider.request({
73
+ method: 'eth_accounts',
74
+ }),
75
+ ).rejects.matchSnapshot()
76
+ })
77
+ })
78
+
79
+ describe('eth_requestAccounts', () => {
80
+ test('default', async () => {
81
+ const porto = getPorto()
82
+ await porto.provider.request({
83
+ method: 'wallet_connect',
84
+ params: [{ capabilities: { createAccount: true } }],
85
+ })
86
+ await porto.provider.request({
87
+ method: 'wallet_disconnect',
88
+ })
89
+ const accounts = await porto.provider.request({
90
+ method: 'eth_requestAccounts',
91
+ })
92
+ expect(accounts.length).toBeGreaterThan(0)
93
+ })
94
+ })
95
+
96
+ describe('eth_sendTransaction', () => {
97
+ test('default', async () => {
98
+ const porto = getPorto()
99
+ const client = TestConfig.getRelayClient(porto)
100
+ const contracts = await TestConfig.getContracts(porto)
101
+
102
+ const {
103
+ accounts: [account],
104
+ } = await porto.provider.request({
105
+ method: 'wallet_connect',
106
+ params: [{ capabilities: { createAccount: true } }],
107
+ })
108
+ const address = account!.address
109
+
110
+ await setBalance(client, {
111
+ address,
112
+ value: Value.fromEther('10000'),
113
+ })
114
+
115
+ const alice = Hex.random(20)
116
+
117
+ const hash = await porto.provider.request({
118
+ method: 'eth_sendTransaction',
119
+ params: [
120
+ {
121
+ data: encodeFunctionData({
122
+ abi: contracts.exp1.abi,
123
+ args: [alice, 69420n],
124
+ functionName: 'transfer',
125
+ }),
126
+ from: address,
127
+ to: contracts.exp1.address,
128
+ },
129
+ ],
130
+ })
131
+
132
+ expect(hash).toBeDefined()
133
+
134
+ const receipt = await waitForTransactionReceipt(client, { hash })
135
+ expect(receipt).toBeDefined()
136
+
137
+ expect(
138
+ await readContract(client, {
139
+ abi: contracts.exp1.abi,
140
+ address: contracts.exp1.address,
141
+ args: [alice],
142
+ functionName: 'balanceOf',
143
+ }),
144
+ ).toBe(69420n)
145
+ })
146
+ })
147
+
148
+ describe('eth_signTypedData_v4', () => {
149
+ test('predelegated', async () => {
150
+ const porto = getPorto()
151
+ const relayClient = TestConfig.getRelayClient(porto)
152
+
153
+ const {
154
+ accounts: [account],
155
+ } = await porto.provider.request({
156
+ method: 'wallet_connect',
157
+ params: [{ capabilities: { createAccount: true } }],
158
+ })
159
+ const address = account!.address
160
+
161
+ const signature = await porto.provider.request({
162
+ method: 'eth_signTypedData_v4',
163
+ params: [address, TypedData.serialize(typedData)],
164
+ })
165
+ expect(signature).toBeDefined()
166
+
167
+ {
168
+ const { valid } = await porto.provider.request({
169
+ method: 'wallet_verifySignature',
170
+ params: [
171
+ {
172
+ address,
173
+ digest: hashTypedData(typedData),
174
+ signature,
175
+ },
176
+ ],
177
+ })
178
+ expect(valid).toBe(true)
179
+ }
180
+
181
+ {
182
+ const valid = await verifyHash(relayClient, {
183
+ address,
184
+ hash: hashTypedData(typedData),
185
+ signature,
186
+ })
187
+ expect(valid).toBe(true)
188
+ }
189
+ })
190
+
191
+ test('delegated', async () => {
192
+ const porto = getPorto()
193
+ const walletClient = TestConfig.getWalletClient(porto)
194
+ const relayClient = TestConfig.getRelayClient(porto)
195
+
196
+ const {
197
+ accounts: [account],
198
+ } = await porto.provider.request({
199
+ method: 'wallet_connect',
200
+ params: [{ capabilities: { createAccount: true } }],
201
+ })
202
+ const address = account!.address
203
+
204
+ await setBalance(relayClient, {
205
+ address,
206
+ value: Value.fromEther('10000'),
207
+ })
208
+ const { id } = await porto.provider.request({
209
+ method: 'wallet_sendCalls',
210
+ params: [{ calls: [] }],
211
+ })
212
+ await waitForCallsStatus(walletClient, {
213
+ id,
214
+ })
215
+
216
+ const signature = await porto.provider.request({
217
+ method: 'eth_signTypedData_v4',
218
+ params: [address, TypedData.serialize(typedData)],
219
+ })
220
+ expect(signature).toBeDefined()
221
+
222
+ {
223
+ const { valid } = await porto.provider.request({
224
+ method: 'wallet_verifySignature',
225
+ params: [
226
+ {
227
+ address,
228
+ digest: hashTypedData(typedData),
229
+ signature,
230
+ },
231
+ ],
232
+ })
233
+ expect(valid).toBe(true)
234
+ }
235
+
236
+ {
237
+ const valid = await verifyHash(relayClient, {
238
+ address,
239
+ hash: hashTypedData(typedData),
240
+ signature,
241
+ })
242
+ expect(valid).toBe(true)
243
+ }
244
+ })
245
+ })
246
+
247
+ describe('wallet_grantAdmin', () => {
248
+ test('default', async () => {
249
+ const messages: any[] = []
250
+
251
+ const porto = getPorto()
252
+ const client = RelayClient.fromPorto(porto).extend(() => ({
253
+ mode: 'anvil',
254
+ }))
255
+
256
+ porto.provider.on('message', (message) => messages.push(message))
257
+
258
+ const {
259
+ accounts: [account],
260
+ } = await porto.provider.request({
261
+ method: 'wallet_connect',
262
+ params: [{ capabilities: { createAccount: true } }],
263
+ })
264
+ const address = account!.address
265
+
266
+ await setBalance(client, {
267
+ address,
268
+ value: Value.fromEther('10000'),
269
+ })
270
+
271
+ const response = await porto.provider.request({
272
+ method: 'wallet_grantAdmin',
273
+ params: [
274
+ {
275
+ key: {
276
+ publicKey: '0x0000000000000000000000000000000000069420',
277
+ type: 'address',
278
+ },
279
+ },
280
+ ],
281
+ })
282
+
283
+ expect(response.key).matchSnapshot()
284
+
285
+ const accounts = porto._internal.store.getState().accounts
286
+ expect(accounts.length).toBe(1)
287
+ expect(accounts[0]!.keys?.length).toBe(2)
288
+
289
+ expect(messages[0].type).toBe('adminsChanged')
290
+ })
291
+ })
292
+
293
+ describe.runIf(type === 'relay')('wallet_getAssets', () => {
294
+ test('default', async () => {
295
+ const porto = getPorto()
296
+ const {
297
+ accounts: [account],
298
+ } = await porto.provider.request({
299
+ method: 'wallet_connect',
300
+ params: [
301
+ {
302
+ capabilities: {
303
+ createAccount: true,
304
+ },
305
+ },
306
+ ],
307
+ })
308
+
309
+ const result = await porto.provider.request({
310
+ method: 'wallet_getAssets',
311
+ params: [{ account: account!.address }],
312
+ })
313
+ expect(result).toBeDefined()
314
+ expect(Object.keys(result).length).toBeGreaterThanOrEqual(1)
315
+ })
316
+
317
+ test('behavior: with balances', async () => {
318
+ const porto = getPorto()
319
+ const client = TestConfig.getRelayClient(porto)
320
+ const contracts = await TestConfig.getContracts(porto)
321
+
322
+ const {
323
+ accounts: [account],
324
+ } = await porto.provider.request({
325
+ method: 'wallet_connect',
326
+ params: [
327
+ {
328
+ capabilities: {
329
+ createAccount: true,
330
+ },
331
+ },
332
+ ],
333
+ })
334
+ const address = account!.address
335
+
336
+ // Set native balance
337
+ await setBalance(client, {
338
+ address,
339
+ value: Value.fromEther('100'),
340
+ })
341
+
342
+ // Mint some ERC20 tokens
343
+ await porto.provider.request({
344
+ method: 'wallet_sendCalls',
345
+ params: [
346
+ {
347
+ calls: [
348
+ {
349
+ data: encodeFunctionData({
350
+ abi: contracts.exp1.abi,
351
+ args: [address, Value.fromEther('1000')],
352
+ functionName: 'mint',
353
+ }),
354
+ to: contracts.exp1.address,
355
+ },
356
+ ],
357
+ from: address,
358
+ version: '1',
359
+ },
360
+ ],
361
+ })
362
+
363
+ const result = await porto.provider.request({
364
+ method: 'wallet_getAssets',
365
+ params: [{ account: address }],
366
+ })
367
+
368
+ expect(result).toBeDefined()
369
+ const assetKeys = Object.keys(result)
370
+ expect(assetKeys.length).toBeGreaterThanOrEqual(1)
371
+
372
+ // Check if we have chain-specific assets
373
+ const chainId = Hex.fromNumber(client.chain.id)
374
+ expect(result[chainId]).toBeDefined()
375
+ expect(Array.isArray(result[chainId])).toBe(true)
376
+ })
377
+
378
+ test('behavior: after transaction', async () => {
379
+ const porto = getPorto()
380
+ const client = TestConfig.getRelayClient(porto)
381
+ const contracts = await TestConfig.getContracts(porto)
382
+
383
+ const {
384
+ accounts: [account],
385
+ } = await porto.provider.request({
386
+ method: 'wallet_connect',
387
+ params: [
388
+ {
389
+ capabilities: {
390
+ createAccount: true,
391
+ },
392
+ },
393
+ ],
394
+ })
395
+ const address = account!.address
396
+
397
+ await setBalance(client, {
398
+ address,
399
+ value: Value.fromEther('1000'),
400
+ })
401
+
402
+ // Get assets before transaction
403
+ const assetsBefore = await porto.provider.request({
404
+ method: 'wallet_getAssets',
405
+ params: [{ account: address }],
406
+ })
407
+
408
+ const alice = Hex.random(20)
409
+
410
+ const { id } = await porto.provider.request({
411
+ method: 'wallet_sendCalls',
412
+ params: [
413
+ {
414
+ calls: [
415
+ {
416
+ data: encodeFunctionData({
417
+ abi: contracts.exp1.abi,
418
+ args: [alice, Value.fromEther('50')],
419
+ functionName: 'transfer',
420
+ }),
421
+ to: contracts.exp1.address,
422
+ },
423
+ ],
424
+ from: address,
425
+ version: '1',
426
+ },
427
+ ],
428
+ })
429
+
430
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
431
+ id,
432
+ })
433
+
434
+ // Get assets after transaction
435
+ const assetsAfter = await porto.provider.request({
436
+ method: 'wallet_getAssets',
437
+ params: [{ account: address }],
438
+ })
439
+
440
+ expect(assetsAfter).toBeDefined()
441
+ expect(Object.keys(assetsAfter).length).toBeGreaterThanOrEqual(1)
442
+ // The balance should have changed after the transaction
443
+ expect(assetsAfter).not.toEqual(assetsBefore)
444
+ })
445
+
446
+ test('behavior: multiple chains; one unsupported', async () => {
447
+ const porto = getPorto()
448
+ const client = TestConfig.getRelayClient(porto)
449
+
450
+ const {
451
+ accounts: [account],
452
+ } = await porto.provider.request({
453
+ method: 'wallet_connect',
454
+ params: [
455
+ {
456
+ capabilities: {
457
+ createAccount: true,
458
+ },
459
+ },
460
+ ],
461
+ })
462
+ const address = account!.address
463
+
464
+ await setBalance(client, {
465
+ address,
466
+ value: Value.fromEther('100'),
467
+ })
468
+
469
+ await expect(
470
+ porto.provider.request({
471
+ method: 'wallet_getAssets',
472
+ params: [{ account: address, chainFilter: [Hex.fromNumber(999999)] }],
473
+ }),
474
+ ).rejects.toThrow('unsupported chain 999999')
475
+ })
476
+ })
477
+
478
+ describe('wallet_getAdmins', () => {
479
+ test('default', async () => {
480
+ const porto = getPorto()
481
+ await porto.provider.request({
482
+ method: 'wallet_connect',
483
+ params: [
484
+ {
485
+ capabilities: {
486
+ createAccount: true,
487
+ },
488
+ },
489
+ ],
490
+ })
491
+
492
+ const { address, keys } = await porto.provider.request({
493
+ method: 'wallet_getAdmins',
494
+ })
495
+ expect(address).toBeDefined()
496
+ expect(keys.length).toBe(1)
497
+ })
498
+
499
+ test('behavior: disconnected', async () => {
500
+ const porto = getPorto()
501
+ await expect(
502
+ porto.provider.request({
503
+ method: 'wallet_getAdmins',
504
+ }),
505
+ ).rejects.matchSnapshot()
506
+ })
507
+
508
+ test('behavior: disconnect > connect > getAdmins', async () => {
509
+ const porto = getPorto()
510
+ await porto.provider.request({
511
+ method: 'wallet_connect',
512
+ params: [
513
+ {
514
+ capabilities: {
515
+ createAccount: true,
516
+ },
517
+ },
518
+ ],
519
+ })
520
+
521
+ await porto.provider.request({
522
+ method: 'wallet_disconnect',
523
+ })
524
+
525
+ await porto.provider.request({
526
+ method: 'wallet_connect',
527
+ })
528
+
529
+ const { address, keys } = await porto.provider.request({
530
+ method: 'wallet_getAdmins',
531
+ })
532
+ expect(address).toBeDefined()
533
+ expect(keys.length).toBe(1)
534
+ })
535
+ })
536
+
537
+ describe('wallet_grantPermissions', () => {
538
+ test('default', async () => {
539
+ const messages: any[] = []
540
+
541
+ const porto = getPorto()
542
+ porto.provider.on('message', (message) => messages.push(message))
543
+
544
+ await porto.provider.request({
545
+ method: 'wallet_connect',
546
+ params: [{ capabilities: { createAccount: true } }],
547
+ })
548
+ await porto.provider.request({
549
+ method: 'wallet_grantPermissions',
550
+ params: [
551
+ {
552
+ expiry: 9999999999,
553
+ feeToken: {
554
+ limit: '1',
555
+ symbol: 'EXP',
556
+ },
557
+ permissions: {
558
+ calls: [{ signature: 'mint()' }],
559
+ },
560
+ },
561
+ ],
562
+ })
563
+
564
+ const accounts = porto._internal.store.getState().accounts
565
+ expect(accounts.length).toBe(1)
566
+ expect(accounts![0]!.keys?.length).toBe(2)
567
+ expect(
568
+ accounts![0]!.keys?.map((x) => ({
569
+ ...x,
570
+ chainId: null,
571
+ expiry: null,
572
+ hash: null,
573
+ id: null,
574
+ permissions: {
575
+ ...x.permissions,
576
+ spend: x.permissions?.spend?.map((x) => ({
577
+ ...x,
578
+ token: null,
579
+ })),
580
+ },
581
+ publicKey: null,
582
+ })),
583
+ ).matchSnapshot()
584
+
585
+ expect(messages[0].type).toBe('permissionsChanged')
586
+ })
587
+
588
+ test('behavior: provided key', async () => {
589
+ const messages: any[] = []
590
+
591
+ const porto = getPorto()
592
+ porto.provider.on('message', (message) => messages.push(message))
593
+
594
+ await porto.provider.request({
595
+ method: 'wallet_connect',
596
+ params: [{ capabilities: { createAccount: true } }],
597
+ })
598
+
599
+ const permissions = await porto.provider.request({
600
+ method: 'wallet_grantPermissions',
601
+ params: [
602
+ {
603
+ expiry: 9999999999,
604
+ feeToken: {
605
+ limit: '1',
606
+ symbol: 'EXP',
607
+ },
608
+ key: {
609
+ publicKey:
610
+ '0x86a0d77beccf47a0a78cccfc19fdfe7317816740c9f9e6d7f696a02b0c66e0e21744d93c5699e9ce658a64ce60df2f32a17954cd577c713922bf62a1153cf68e',
611
+ type: 'p256',
612
+ },
613
+ permissions: {
614
+ calls: [{ signature: 'mint()' }],
615
+ },
616
+ },
617
+ ],
618
+ })
619
+
620
+ expect(permissions.address).toBeDefined()
621
+ expect({
622
+ ...permissions,
623
+ address: null,
624
+ capabilities: null,
625
+ chainId: null,
626
+ permissions: {
627
+ ...permissions.permissions,
628
+ spend: permissions.permissions?.spend?.map((x) => ({
629
+ ...x,
630
+ token: null,
631
+ })),
632
+ },
633
+ }).matchSnapshot()
634
+
635
+ {
636
+ const permissions = await porto.provider.request({
637
+ method: 'wallet_grantPermissions',
638
+ params: [
639
+ {
640
+ expiry: 9999999999,
641
+ feeToken: {
642
+ limit: '1',
643
+ symbol: 'EXP',
644
+ },
645
+ key: {
646
+ publicKey: '0x0000000000000000000000000000000000000000',
647
+ type: 'address',
648
+ },
649
+ permissions: {
650
+ calls: [{ signature: 'mint()' }],
651
+ spend: [
652
+ {
653
+ limit: Hex.fromNumber(Value.fromEther('1.5')),
654
+ period: 'day',
655
+ },
656
+ ],
657
+ },
658
+ },
659
+ ],
660
+ })
661
+
662
+ expect(permissions.address).toBeDefined()
663
+ expect({
664
+ ...permissions,
665
+ address: null,
666
+ capabilities: null,
667
+ chainId: null,
668
+ permissions: {
669
+ ...permissions.permissions,
670
+ spend: permissions.permissions?.spend?.map((x) => ({
671
+ ...x,
672
+ token: null,
673
+ })),
674
+ },
675
+ }).matchSnapshot()
676
+ }
677
+
678
+ const accounts = porto._internal.store.getState().accounts
679
+ expect(accounts.length).toBe(1)
680
+ expect(accounts![0]!.keys?.length).toBe(3)
681
+ expect(
682
+ accounts![0]!.keys?.map((x) => ({
683
+ ...x,
684
+ chainId: null,
685
+ expiry: null,
686
+ hash: null,
687
+ id: null,
688
+ permissions: {
689
+ ...permissions.permissions,
690
+ spend: permissions.permissions?.spend?.map((x) => ({
691
+ ...x,
692
+ token: null,
693
+ })),
694
+ },
695
+ publicKey: null,
696
+ })),
697
+ ).matchSnapshot()
698
+
699
+ expect(messages[0].type).toBe('permissionsChanged')
700
+ })
701
+
702
+ test('behavior: no permissions', async () => {
703
+ const porto = getPorto()
704
+ await porto.provider.request({
705
+ method: 'wallet_connect',
706
+ params: [{ capabilities: { createAccount: true } }],
707
+ })
708
+ await expect(
709
+ porto.provider.request({
710
+ method: 'wallet_grantPermissions',
711
+ params: [
712
+ {
713
+ expiry: 9999999999,
714
+ feeToken: {
715
+ limit: '1',
716
+ symbol: 'EXP',
717
+ },
718
+ key: {
719
+ publicKey:
720
+ '0x86a0d77beccf47a0a78cccfc19fdfe7317816740c9f9e6d7f696a02b0c66e0e21744d93c5699e9ce658a64ce60df2f32a17954cd577c713922bf62a1153cf68e',
721
+ type: 'p256',
722
+ },
723
+ permissions: {
724
+ calls: [],
725
+ },
726
+ },
727
+ ],
728
+ }),
729
+ ).rejects.matchSnapshot()
730
+ })
731
+
732
+ test('behavior: unlimited expiry', async () => {
733
+ const porto = getPorto()
734
+ await porto.provider.request({
735
+ method: 'wallet_connect',
736
+ params: [{ capabilities: { createAccount: true } }],
737
+ })
738
+ await expect(
739
+ porto.provider.request({
740
+ method: 'wallet_grantPermissions',
741
+ params: [
742
+ {
743
+ expiry: 0,
744
+ feeToken: {
745
+ limit: '1',
746
+ symbol: 'EXP',
747
+ },
748
+ key: {
749
+ publicKey:
750
+ '0x86a0d77beccf47a0a78cccfc19fdfe7317816740c9f9e6d7f696a02b0c66e0e21744d93c5699e9ce658a64ce60df2f32a17954cd577c713922bf62a1153cf68e',
751
+ type: 'p256',
752
+ },
753
+ permissions: {
754
+ calls: [{ signature: 'mint()' }],
755
+ },
756
+ },
757
+ ],
758
+ }),
759
+ ).rejects.matchSnapshot()
760
+ })
761
+ })
762
+
763
+ describe('wallet_getPermissions', () => {
764
+ test('default', async () => {
765
+ const porto = getPorto()
766
+ await porto.provider.request({
767
+ method: 'wallet_connect',
768
+ params: [{ capabilities: { createAccount: true } }],
769
+ })
770
+ await porto.provider.request({
771
+ method: 'wallet_grantPermissions',
772
+ params: [
773
+ {
774
+ expiry: 9999999999,
775
+ feeToken: {
776
+ limit: '1',
777
+ symbol: 'EXP',
778
+ },
779
+ permissions: {
780
+ calls: [{ signature: 'mint()' }],
781
+ },
782
+ },
783
+ ],
784
+ })
785
+ await porto.provider.request({
786
+ method: 'wallet_grantPermissions',
787
+ params: [
788
+ {
789
+ expiry: 9999999999,
790
+ feeToken: {
791
+ limit: '1',
792
+ symbol: 'EXP',
793
+ },
794
+ permissions: {
795
+ calls: [{ signature: 'mint()' }],
796
+ spend: [
797
+ {
798
+ limit: Hex.fromNumber(Value.fromEther('1.5')),
799
+ period: 'day',
800
+ },
801
+ ],
802
+ },
803
+ },
804
+ ],
805
+ })
806
+ const permissions = await porto.provider.request({
807
+ method: 'wallet_getPermissions',
808
+ })
809
+ expect(permissions.length).toBe(2)
810
+ })
811
+
812
+ test('behavior: grant on connect > grant another > get after connect', async () => {
813
+ const porto = getPorto()
814
+ const client = TestConfig.getRelayClient(porto)
815
+ const walletClient = TestConfig.getWalletClient(porto)
816
+
817
+ const { accounts } = await porto.provider.request({
818
+ method: 'wallet_connect',
819
+ params: [
820
+ {
821
+ capabilities: {
822
+ createAccount: true,
823
+ grantPermissions: {
824
+ expiry: 9999999999,
825
+ feeToken: {
826
+ limit: '1',
827
+ symbol: 'EXP',
828
+ },
829
+ key: {
830
+ publicKey: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
831
+ type: 'address',
832
+ },
833
+ permissions: {
834
+ calls: [{ signature: 'mint()' }],
835
+ },
836
+ },
837
+ },
838
+ },
839
+ ],
840
+ })
841
+ await porto.provider.request({
842
+ method: 'wallet_grantPermissions',
843
+ params: [
844
+ {
845
+ expiry: 9999999999,
846
+ feeToken: {
847
+ limit: '1',
848
+ symbol: 'EXP',
849
+ },
850
+ key: {
851
+ publicKey:
852
+ '0xcafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe',
853
+ type: 'p256',
854
+ },
855
+ permissions: {
856
+ calls: [{ signature: 'mint()' }],
857
+ spend: [
858
+ {
859
+ limit: Hex.fromNumber(Value.fromEther('1.5')),
860
+ period: 'day',
861
+ },
862
+ ],
863
+ },
864
+ },
865
+ ],
866
+ })
867
+
868
+ {
869
+ const permissions = await porto.provider.request({
870
+ method: 'wallet_getPermissions',
871
+ })
872
+ expect(
873
+ permissions.map((x) => ({
874
+ ...x,
875
+ address: null,
876
+ chainId: null,
877
+ permissions: {
878
+ calls: x.permissions?.calls?.map((x) => ({
879
+ ...x,
880
+ to: null,
881
+ })),
882
+ spend: x.permissions?.spend?.map((x) => ({
883
+ ...x,
884
+ token: null,
885
+ })),
886
+ },
887
+ })),
888
+ ).matchSnapshot()
889
+ }
890
+
891
+ await setBalance(client, {
892
+ address: accounts[0]!.address,
893
+ value: Value.fromEther('10000'),
894
+ })
895
+ const { id } = await porto.provider.request({
896
+ method: 'wallet_sendCalls',
897
+ params: [{ calls: [] }],
898
+ })
899
+ await waitForCallsStatus(walletClient, {
900
+ id,
901
+ })
902
+
903
+ {
904
+ const permissions = await porto.provider.request({
905
+ method: 'wallet_getPermissions',
906
+ })
907
+ expect(
908
+ permissions.map((x) => ({
909
+ ...x,
910
+ address: null,
911
+ chainId: null,
912
+ permissions: {
913
+ calls: x.permissions?.calls?.map((x) => ({
914
+ ...x,
915
+ to: null,
916
+ })),
917
+ spend: x.permissions?.spend?.map((x) => ({
918
+ ...x,
919
+ token: null,
920
+ })),
921
+ },
922
+ })),
923
+ ).matchSnapshot()
924
+ }
925
+
926
+ await porto.provider.request({
927
+ method: 'wallet_disconnect',
928
+ })
929
+ await porto.provider.request({
930
+ method: 'wallet_connect',
931
+ })
932
+
933
+ {
934
+ const permissions = await porto.provider.request({
935
+ method: 'wallet_getPermissions',
936
+ })
937
+ expect(
938
+ permissions.map((x) => ({
939
+ ...x,
940
+ address: null,
941
+ chainId: null,
942
+ permissions: {
943
+ calls: x.permissions?.calls?.map((x) => ({
944
+ ...x,
945
+ to: null,
946
+ })),
947
+ spend: x.permissions?.spend?.map((x) => ({
948
+ ...x,
949
+ token: null,
950
+ })),
951
+ },
952
+ })),
953
+ ).matchSnapshot()
954
+ }
955
+ })
956
+ })
957
+
958
+ describe('wallet_revokeAdmin', () => {
959
+ test('default', async () => {
960
+ const porto = getPorto()
961
+ const client = RelayClient.fromPorto(porto).extend(() => ({
962
+ mode: 'anvil',
963
+ }))
964
+
965
+ const messages: any[] = []
966
+ porto.provider.on('message', (message) => messages.push(message))
967
+
968
+ const {
969
+ accounts: [account],
970
+ } = await porto.provider.request({
971
+ method: 'wallet_connect',
972
+ params: [{ capabilities: { createAccount: true } }],
973
+ })
974
+ const address = account!.address
975
+
976
+ await setBalance(client, {
977
+ address,
978
+ value: Value.fromEther('10000'),
979
+ })
980
+
981
+ const { key } = await porto.provider.request({
982
+ method: 'wallet_grantAdmin',
983
+ params: [
984
+ {
985
+ key: {
986
+ publicKey: '0x0000000000000000000000000000000000069420',
987
+ type: 'address',
988
+ },
989
+ },
990
+ ],
991
+ })
992
+ let accounts = porto._internal.store.getState().accounts
993
+ expect(accounts.length).toBe(1)
994
+ expect(accounts![0]!.keys?.length).toBe(2)
995
+ expect(
996
+ accounts![0]!.keys?.map((x) => ({
997
+ ...x,
998
+ chainId: null,
999
+ expiry: null,
1000
+ hash: null,
1001
+ id: null,
1002
+ publicKey: null,
1003
+ })),
1004
+ ).matchSnapshot()
1005
+
1006
+ expect(messages[0].type).toBe('adminsChanged')
1007
+
1008
+ await porto.provider.request({
1009
+ method: 'wallet_revokeAdmin',
1010
+ params: [{ id: key.publicKey }],
1011
+ })
1012
+
1013
+ accounts = porto._internal.store.getState().accounts
1014
+ expect(accounts![0]!.keys?.length).toBe(1)
1015
+ expect(
1016
+ accounts![0]!.keys?.map((x) => ({
1017
+ ...x,
1018
+ chainId: null,
1019
+ expiry: null,
1020
+ hash: null,
1021
+ id: null,
1022
+ publicKey: null,
1023
+ })),
1024
+ ).matchSnapshot()
1025
+
1026
+ expect(messages[1].type).toBe('adminsChanged')
1027
+ })
1028
+ })
1029
+
1030
+ describe('wallet_revokePermissions', () => {
1031
+ test('default', async () => {
1032
+ const porto = getPorto()
1033
+ const client = RelayClient.fromPorto(porto).extend(() => ({
1034
+ mode: 'anvil',
1035
+ }))
1036
+
1037
+ const messages: any[] = []
1038
+ porto.provider.on('message', (message) => messages.push(message))
1039
+
1040
+ const {
1041
+ accounts: [account],
1042
+ } = await porto.provider.request({
1043
+ method: 'wallet_connect',
1044
+ params: [{ capabilities: { createAccount: true } }],
1045
+ })
1046
+ const address = account!.address
1047
+
1048
+ await setBalance(client, {
1049
+ address,
1050
+ value: Value.fromEther('10000'),
1051
+ })
1052
+
1053
+ const { id } = await porto.provider.request({
1054
+ method: 'wallet_grantPermissions',
1055
+ params: [
1056
+ {
1057
+ expiry: 9999999999,
1058
+ feeToken: {
1059
+ limit: '1',
1060
+ symbol: 'EXP',
1061
+ },
1062
+ permissions: {
1063
+ calls: [{ signature: 'mint()' }],
1064
+ },
1065
+ },
1066
+ ],
1067
+ })
1068
+ let accounts = porto._internal.store.getState().accounts
1069
+ expect(accounts.length).toBe(1)
1070
+ expect(accounts![0]!.keys?.length).toBe(2)
1071
+ expect(
1072
+ accounts![0]!.keys?.map((x) => ({
1073
+ ...x,
1074
+ chainId: null,
1075
+ expiry: null,
1076
+ hash: null,
1077
+ id: null,
1078
+ permissions: {
1079
+ ...x.permissions,
1080
+ spend: x.permissions?.spend?.map((x) => ({
1081
+ ...x,
1082
+ token: null,
1083
+ })),
1084
+ },
1085
+ publicKey: null,
1086
+ })),
1087
+ ).matchSnapshot()
1088
+
1089
+ expect(messages[0].type).toBe('permissionsChanged')
1090
+
1091
+ await porto.provider.request({
1092
+ method: 'wallet_revokePermissions',
1093
+ params: [{ id }],
1094
+ })
1095
+
1096
+ accounts = porto._internal.store.getState().accounts
1097
+ expect(accounts![0]!.keys?.length).toBe(1)
1098
+ expect(
1099
+ accounts![0]!.keys?.map((x) => ({
1100
+ ...x,
1101
+ chainId: null,
1102
+ expiry: null,
1103
+ hash: null,
1104
+ id: null,
1105
+ publicKey: null,
1106
+ })),
1107
+ ).matchSnapshot()
1108
+
1109
+ expect(messages[1].type).toBe('permissionsChanged')
1110
+ })
1111
+
1112
+ test('behavior: revoke last admin key', async () => {
1113
+ const porto = getPorto()
1114
+
1115
+ const messages: any[] = []
1116
+ porto.provider.on('message', (message) => messages.push(message))
1117
+
1118
+ await porto.provider.request({
1119
+ method: 'wallet_connect',
1120
+ params: [{ capabilities: { createAccount: true } }],
1121
+ })
1122
+
1123
+ const accounts = porto._internal.store.getState().accounts
1124
+ const id = accounts![0]!.keys![0]!.publicKey
1125
+
1126
+ await expect(() =>
1127
+ porto.provider.request({
1128
+ method: 'wallet_revokePermissions',
1129
+ params: [{ id }],
1130
+ }),
1131
+ ).rejects.matchSnapshot()
1132
+ })
1133
+ })
1134
+
1135
+ describe('wallet_getAccountVersion', () => {
1136
+ test('default', async () => {
1137
+ const porto = getPorto()
1138
+ const client = TestConfig.getRelayClient(porto)
1139
+
1140
+ const capabilities = await RelayActions.getCapabilities(client)
1141
+
1142
+ await porto.provider.request({
1143
+ method: 'wallet_connect',
1144
+ params: [{ capabilities: { createAccount: true } }],
1145
+ })
1146
+
1147
+ const version = await porto.provider.request({
1148
+ method: 'wallet_getAccountVersion',
1149
+ })
1150
+ expect(version.current).toMatch(
1151
+ capabilities.contracts.accountImplementation.version!,
1152
+ )
1153
+ expect(version.latest).toMatch(
1154
+ capabilities.contracts.accountImplementation.version!,
1155
+ )
1156
+ })
1157
+
1158
+ test('behavior: provided address', async () => {
1159
+ const porto = getPorto()
1160
+ const client = TestConfig.getRelayClient(porto)
1161
+
1162
+ const capabilities = await RelayActions.getCapabilities(client)
1163
+
1164
+ const {
1165
+ accounts: [account],
1166
+ } = await porto.provider.request({
1167
+ method: 'wallet_connect',
1168
+ params: [{ capabilities: { createAccount: true } }],
1169
+ })
1170
+ const address = account!.address
1171
+
1172
+ const version = await porto.provider.request({
1173
+ method: 'wallet_getAccountVersion',
1174
+ params: [{ address }],
1175
+ })
1176
+ expect(version.current).toMatch(
1177
+ capabilities.contracts.accountImplementation.version!,
1178
+ )
1179
+ expect(version.latest).toMatch(
1180
+ capabilities.contracts.accountImplementation.version!,
1181
+ )
1182
+ })
1183
+
1184
+ test('behavior: not connected', async () => {
1185
+ const porto = getPorto()
1186
+
1187
+ await expect(
1188
+ porto.provider.request({
1189
+ method: 'wallet_getAccountVersion',
1190
+ }),
1191
+ ).rejects.toMatchInlineSnapshot(
1192
+ '[Provider.DisconnectedError: The provider is disconnected from all chains.]',
1193
+ )
1194
+ })
1195
+
1196
+ test('behavior: account not found', async () => {
1197
+ const porto = getPorto()
1198
+
1199
+ await porto.provider.request({
1200
+ method: 'wallet_connect',
1201
+ params: [{ capabilities: { createAccount: true } }],
1202
+ })
1203
+
1204
+ await expect(
1205
+ porto.provider.request({
1206
+ method: 'wallet_getAccountVersion',
1207
+ params: [{ address: '0x0000000000000000000000000000000000000000' }],
1208
+ }),
1209
+ ).rejects.toMatchInlineSnapshot(
1210
+ '[Provider.UnauthorizedError: The requested method and/or account has not been authorized by the user.]',
1211
+ )
1212
+ })
1213
+
1214
+ test.runIf(Anvil.enabled)('behavior: outdated account', async () => {
1215
+ const porto = getPorto()
1216
+ const client = RelayClient.fromPorto(porto).extend(() => ({
1217
+ mode: 'anvil',
1218
+ }))
1219
+
1220
+ const capabilities = await RelayActions.getCapabilities(client)
1221
+
1222
+ const {
1223
+ accounts: [account],
1224
+ } = await porto.provider.request({
1225
+ method: 'wallet_connect',
1226
+ params: [{ capabilities: { createAccount: true } }],
1227
+ })
1228
+ const address = account!.address
1229
+
1230
+ await setBalance(client, {
1231
+ address,
1232
+ value: Value.fromEther('10000'),
1233
+ })
1234
+
1235
+ const { id } = await porto.provider.request({
1236
+ method: 'wallet_sendCalls',
1237
+ params: [
1238
+ {
1239
+ calls: [],
1240
+ from: address,
1241
+ version: '1',
1242
+ },
1243
+ ],
1244
+ })
1245
+
1246
+ expect(id).toBeDefined()
1247
+
1248
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
1249
+ id,
1250
+ })
1251
+
1252
+ await setCode(client, {
1253
+ address,
1254
+ bytecode: Hex.concat('0xef0100', accountOldProxyAddress),
1255
+ })
1256
+
1257
+ const version = await porto.provider.request({
1258
+ method: 'wallet_getAccountVersion',
1259
+ })
1260
+ expect(version.current).toMatch('0.0.1')
1261
+ expect(version.latest).toMatch(
1262
+ capabilities.contracts.accountImplementation.version!,
1263
+ )
1264
+ })
1265
+ })
1266
+
1267
+ describe('personal_sign', () => {
1268
+ test('predelegated', async () => {
1269
+ const porto = getPorto()
1270
+ const relayClient = TestConfig.getRelayClient(porto)
1271
+
1272
+ const {
1273
+ accounts: [account],
1274
+ } = await porto.provider.request({
1275
+ method: 'wallet_connect',
1276
+ params: [{ capabilities: { createAccount: true } }],
1277
+ })
1278
+ const address = account!.address
1279
+
1280
+ const signature = await porto.provider.request({
1281
+ method: 'personal_sign',
1282
+ params: [Hex.fromString('hello'), address],
1283
+ })
1284
+ expect(signature).toBeDefined()
1285
+
1286
+ {
1287
+ const { valid } = await porto.provider.request({
1288
+ method: 'wallet_verifySignature',
1289
+ params: [
1290
+ {
1291
+ address,
1292
+ digest: hashMessage('hello'),
1293
+ signature,
1294
+ },
1295
+ ],
1296
+ })
1297
+ expect(valid).toBe(true)
1298
+ }
1299
+
1300
+ {
1301
+ const valid = await verifyHash(relayClient, {
1302
+ address,
1303
+ hash: hashMessage('hello'),
1304
+ signature,
1305
+ })
1306
+ expect(valid).toBe(true)
1307
+ }
1308
+ })
1309
+
1310
+ test('delegated', async () => {
1311
+ const porto = getPorto()
1312
+ const walletClient = TestConfig.getWalletClient(porto)
1313
+ const relayClient = TestConfig.getRelayClient(porto)
1314
+
1315
+ const {
1316
+ accounts: [account],
1317
+ } = await porto.provider.request({
1318
+ method: 'wallet_connect',
1319
+ params: [{ capabilities: { createAccount: true } }],
1320
+ })
1321
+ const address = account!.address
1322
+
1323
+ await setBalance(relayClient, {
1324
+ address,
1325
+ value: Value.fromEther('10000'),
1326
+ })
1327
+ const { id } = await porto.provider.request({
1328
+ method: 'wallet_sendCalls',
1329
+ params: [{ calls: [] }],
1330
+ })
1331
+ await waitForCallsStatus(walletClient, {
1332
+ id,
1333
+ })
1334
+
1335
+ const signature = await porto.provider.request({
1336
+ method: 'personal_sign',
1337
+ params: [Hex.fromString('hello'), address],
1338
+ })
1339
+ expect(signature).toBeDefined()
1340
+
1341
+ {
1342
+ const { valid } = await porto.provider.request({
1343
+ method: 'wallet_verifySignature',
1344
+ params: [
1345
+ {
1346
+ address,
1347
+ digest: hashMessage('hello'),
1348
+ signature,
1349
+ },
1350
+ ],
1351
+ })
1352
+ expect(valid).toBe(true)
1353
+ }
1354
+
1355
+ {
1356
+ const valid = await verifyHash(relayClient, {
1357
+ address,
1358
+ hash: hashMessage('hello'),
1359
+ signature,
1360
+ })
1361
+ expect(valid).toBe(true)
1362
+ }
1363
+ })
1364
+ })
1365
+
1366
+ describe('wallet_connect', () => {
1367
+ test('default', async () => {
1368
+ const messages: any[] = []
1369
+
1370
+ const porto = getPorto()
1371
+ const client = TestConfig.getRelayClient(porto)
1372
+
1373
+ porto.provider.on('connect', (message) => messages.push(message))
1374
+
1375
+ await porto.provider.request({
1376
+ method: 'wallet_connect',
1377
+ params: [{ capabilities: { createAccount: true } }],
1378
+ })
1379
+ await porto.provider.request({
1380
+ method: 'wallet_disconnect',
1381
+ })
1382
+ await porto.provider.request({
1383
+ method: 'wallet_connect',
1384
+ })
1385
+ const accounts = porto._internal.store.getState().accounts
1386
+ expect(accounts.length).toBe(1)
1387
+ expect(accounts![0]!.keys?.length).toBe(1)
1388
+ expect(
1389
+ accounts![0]!.keys?.map((x) => ({
1390
+ ...x,
1391
+ chainId: null,
1392
+ expiry: null,
1393
+ hash: null,
1394
+ id: null,
1395
+ privateKey: null,
1396
+ publicKey: null,
1397
+ })),
1398
+ ).matchSnapshot()
1399
+
1400
+ expect(messages[0].chainId).toBe(Hex.fromNumber(client.chain.id))
1401
+ })
1402
+
1403
+ test('behavior: `createAccount` capability', async () => {
1404
+ const messages: any[] = []
1405
+
1406
+ const porto = getPorto()
1407
+ const client = TestConfig.getRelayClient(porto)
1408
+
1409
+ porto.provider.on('connect', (message) => messages.push(message))
1410
+
1411
+ await porto.provider.request({
1412
+ method: 'wallet_connect',
1413
+ params: [
1414
+ {
1415
+ capabilities: {
1416
+ createAccount: true,
1417
+ },
1418
+ },
1419
+ ],
1420
+ })
1421
+ const accounts = porto._internal.store.getState().accounts
1422
+ expect(accounts.length).toBe(1)
1423
+ expect(accounts![0]!.keys?.length).toBe(1)
1424
+ expect(
1425
+ accounts![0]!.keys?.map((x) => ({
1426
+ ...x,
1427
+ chainId: null,
1428
+ expiry: null,
1429
+ hash: null,
1430
+ id: null,
1431
+ publicKey: null,
1432
+ })),
1433
+ ).matchSnapshot(`
1434
+ [
1435
+ {
1436
+ "expiry": null,
1437
+ "hash": null,
1438
+ "permissions": undefined,
1439
+ "privateKey": [Function],
1440
+ "publicKey": null,
1441
+ "role": "admin",
1442
+ "type": "p256",
1443
+ },
1444
+ ]
1445
+ `)
1446
+
1447
+ expect(messages[0].chainId).toBe(Hex.fromNumber(client.chain.id))
1448
+ })
1449
+
1450
+ test('behavior: `createAccount` + `grantPermissions` capability', async () => {
1451
+ const messages: any[] = []
1452
+
1453
+ const porto = getPorto()
1454
+ const client = TestConfig.getRelayClient(porto)
1455
+
1456
+ porto.provider.on('connect', (message) => messages.push(message))
1457
+
1458
+ await porto.provider.request({
1459
+ method: 'wallet_connect',
1460
+ params: [
1461
+ {
1462
+ capabilities: {
1463
+ createAccount: true,
1464
+ grantPermissions: {
1465
+ expiry: 9999999999,
1466
+ feeToken: {
1467
+ limit: '1',
1468
+ symbol: 'EXP',
1469
+ },
1470
+ permissions: {
1471
+ calls: [{ signature: 'mint()' }],
1472
+ },
1473
+ },
1474
+ },
1475
+ },
1476
+ ],
1477
+ })
1478
+ const accounts = porto._internal.store.getState().accounts
1479
+ expect(accounts.length).toBe(1)
1480
+ expect(accounts![0]!.keys?.length).toBe(2)
1481
+ expect(
1482
+ accounts![0]!.keys?.map((x) => ({
1483
+ ...x,
1484
+ chainId: null,
1485
+ expiry: null,
1486
+ hash: null,
1487
+ id: null,
1488
+ permissions: {
1489
+ ...x.permissions,
1490
+ spend: x.permissions?.spend?.map((x) => ({
1491
+ ...x,
1492
+ token: null,
1493
+ })),
1494
+ },
1495
+ publicKey: null,
1496
+ })),
1497
+ ).matchSnapshot()
1498
+
1499
+ expect(messages[0].chainId).toBe(Hex.fromNumber(client.chain.id))
1500
+ })
1501
+
1502
+ test('behavior: `createAccount` + `grantPermissions` capability (provided key)', async () => {
1503
+ const messages: any[] = []
1504
+
1505
+ const porto = getPorto()
1506
+ const client = TestConfig.getRelayClient(porto)
1507
+
1508
+ porto.provider.on('connect', (message) => messages.push(message))
1509
+
1510
+ const privateKey =
1511
+ '0x1e8dd87f21bc6bbfc86e726ca9c21a285c13984461cf2e3adb265019fb78203d'
1512
+ const publicKey = PublicKey.toHex(P256.getPublicKey({ privateKey }), {
1513
+ includePrefix: false,
1514
+ })
1515
+
1516
+ await porto.provider.request({
1517
+ method: 'wallet_connect',
1518
+ params: [
1519
+ {
1520
+ capabilities: {
1521
+ createAccount: true,
1522
+ grantPermissions: {
1523
+ expiry: 9999999999,
1524
+ feeToken: {
1525
+ limit: '1',
1526
+ symbol: 'EXP',
1527
+ },
1528
+ key: {
1529
+ publicKey,
1530
+ type: 'p256',
1531
+ },
1532
+ permissions: {
1533
+ calls: [{ signature: 'mint()' }],
1534
+ },
1535
+ },
1536
+ },
1537
+ },
1538
+ ],
1539
+ })
1540
+ const accounts = porto._internal.store.getState().accounts
1541
+ expect(accounts.length).toBe(1)
1542
+ expect(accounts![0]!.keys?.length).toBe(2)
1543
+ expect(
1544
+ accounts![0]!.keys?.map((x, i) => ({
1545
+ ...x,
1546
+ chainId: null,
1547
+ expiry: i === 0 ? null : x.expiry,
1548
+ hash: i === 0 ? null : x.hash,
1549
+ id: i === 0 ? null : x.id,
1550
+ permissions: {
1551
+ ...x.permissions,
1552
+ spend: x.permissions?.spend?.map((x) => ({
1553
+ ...x,
1554
+ token: null,
1555
+ })),
1556
+ },
1557
+ publicKey: i === 0 ? null : x.publicKey,
1558
+ })),
1559
+ ).matchSnapshot()
1560
+
1561
+ expect(messages[0].chainId).toBe(Hex.fromNumber(client.chain.id))
1562
+ })
1563
+
1564
+ test('behavior: `grantPermissions` capability (unlimited expiry)', async () => {
1565
+ const porto = getPorto()
1566
+ await expect(() =>
1567
+ porto.provider.request({
1568
+ method: 'wallet_connect',
1569
+ params: [
1570
+ {
1571
+ capabilities: {
1572
+ createAccount: true,
1573
+ grantPermissions: {
1574
+ expiry: 0,
1575
+ feeToken: {
1576
+ limit: '1',
1577
+ symbol: 'EXP',
1578
+ },
1579
+ permissions: {
1580
+ calls: [{ signature: 'mint()' }],
1581
+ },
1582
+ },
1583
+ },
1584
+ },
1585
+ ],
1586
+ }),
1587
+ ).rejects.matchSnapshot()
1588
+ })
1589
+
1590
+ test('behavior: `grantPermissions` capability (no permissions)', async () => {
1591
+ const porto = getPorto()
1592
+ await expect(() =>
1593
+ porto.provider.request({
1594
+ method: 'wallet_connect',
1595
+ params: [
1596
+ {
1597
+ capabilities: {
1598
+ createAccount: true,
1599
+ grantPermissions: {
1600
+ expiry: 9999999,
1601
+ feeToken: {
1602
+ limit: '1',
1603
+ symbol: 'EXP',
1604
+ },
1605
+ permissions: {
1606
+ calls: [],
1607
+ },
1608
+ },
1609
+ },
1610
+ },
1611
+ ],
1612
+ }),
1613
+ ).rejects.matchSnapshot()
1614
+ })
1615
+
1616
+ test('behavior: `signInWithEthereum` capability (predelegated)', async () => {
1617
+ const porto = getPorto()
1618
+ const relayClient = TestConfig.getRelayClient(porto)
1619
+
1620
+ const res = await porto.provider.request({
1621
+ method: 'wallet_connect',
1622
+ params: [
1623
+ {
1624
+ capabilities: {
1625
+ createAccount: true,
1626
+ signInWithEthereum: {
1627
+ domain: 'example.com',
1628
+ nonce: 'deadbeef',
1629
+ uri: 'http://example.com/',
1630
+ },
1631
+ },
1632
+ },
1633
+ ],
1634
+ })
1635
+ const { message, signature } =
1636
+ res.accounts.at(0)?.capabilities?.signInWithEthereum ?? {}
1637
+ if (message && signature) {
1638
+ switch (type) {
1639
+ case 'relay': {
1640
+ {
1641
+ const { valid } = await porto.provider.request({
1642
+ method: 'wallet_verifySignature',
1643
+ params: [
1644
+ {
1645
+ address: res.accounts.at(0)?.address!,
1646
+ digest: hashMessage(message),
1647
+ signature,
1648
+ },
1649
+ ],
1650
+ })
1651
+ expect(valid).toBeTruthy()
1652
+ }
1653
+
1654
+ {
1655
+ const valid = await verifyHash(relayClient, {
1656
+ address: res.accounts.at(0)?.address!,
1657
+ hash: hashMessage(message),
1658
+ signature,
1659
+ })
1660
+ expect(valid).toBeTruthy()
1661
+ }
1662
+ break
1663
+ }
1664
+ }
1665
+ }
1666
+ })
1667
+ })
1668
+
1669
+ describe('wallet_disconnect', () => {
1670
+ test('default', async () => {
1671
+ const messages: any[] = []
1672
+
1673
+ const porto = getPorto()
1674
+ porto.provider.on('disconnect', (message) => messages.push(message))
1675
+
1676
+ await porto.provider.request({
1677
+ method: 'wallet_connect',
1678
+ params: [{ capabilities: { createAccount: true } }],
1679
+ })
1680
+ await porto.provider.request({
1681
+ method: 'wallet_disconnect',
1682
+ })
1683
+
1684
+ const accounts = porto._internal.store.getState().accounts
1685
+ expect(accounts.length).toBe(0)
1686
+ expect(messages).matchSnapshot()
1687
+ })
1688
+ })
1689
+
1690
+ describe('wallet_switchEthereumChain', () => {
1691
+ test('default', async () => {
1692
+ const porto = getPorto()
1693
+ const client = TestConfig.getRelayClient(porto)
1694
+
1695
+ await porto.provider.request({
1696
+ method: 'wallet_connect',
1697
+ params: [{ capabilities: { createAccount: true } }],
1698
+ })
1699
+
1700
+ const initialChainId = await porto.provider.request({
1701
+ method: 'eth_chainId',
1702
+ })
1703
+ expect(initialChainId).toBe(Hex.fromNumber(client.chain.id))
1704
+
1705
+ const targetChain = porto._internal.config.chains.find(
1706
+ (chain) => chain.id !== client.chain.id,
1707
+ )
1708
+ if (!targetChain) throw new Error('No target chain found')
1709
+
1710
+ await porto.provider.request({
1711
+ method: 'wallet_switchEthereumChain',
1712
+ params: [{ chainId: Hex.fromNumber(targetChain.id) }],
1713
+ })
1714
+
1715
+ const state = porto._internal.store.getState()
1716
+ expect(state.chainIds[0]).toBe(targetChain.id)
1717
+
1718
+ const nextChainId = await porto.provider.request({
1719
+ method: 'eth_chainId',
1720
+ })
1721
+ expect(nextChainId).toBe(Hex.fromNumber(targetChain.id))
1722
+ expect(nextChainId).not.toBe(initialChainId)
1723
+
1724
+ await porto.provider.request({
1725
+ method: 'wallet_switchEthereumChain',
1726
+ params: [{ chainId: initialChainId }],
1727
+ })
1728
+ })
1729
+
1730
+ test('behavior: unsupported chain', async () => {
1731
+ const porto = getPorto()
1732
+
1733
+ await porto.provider.request({
1734
+ method: 'wallet_connect',
1735
+ params: [{ capabilities: { createAccount: true } }],
1736
+ })
1737
+
1738
+ await expect(
1739
+ porto.provider.request({
1740
+ method: 'wallet_switchEthereumChain',
1741
+ params: [{ chainId: '0x999' }],
1742
+ }),
1743
+ ).rejects.toMatchInlineSnapshot(
1744
+ '[Provider.UnsupportedChainIdError: This Wallet does not support the requested chain ID.]',
1745
+ )
1746
+ })
1747
+ })
1748
+
1749
+ describe.runIf(Anvil.enabled)('wallet_getCapabilities', () => {
1750
+ test('default', async () => {
1751
+ const porto = getPorto()
1752
+ const capabilities = await porto.provider.request({
1753
+ method: 'wallet_getCapabilities',
1754
+ })
1755
+
1756
+ const keys = Object.keys(capabilities)
1757
+ expect(keys).matchSnapshot()
1758
+
1759
+ const values = Object.values(capabilities)
1760
+ const { atomic, feeToken, permissions, merchant } = values[0]!
1761
+ expect(atomic).matchSnapshot()
1762
+ expect(feeToken.supported).matchSnapshot()
1763
+ expect(feeToken.tokens.length).matchSnapshot()
1764
+ expect(permissions).matchSnapshot()
1765
+ expect(merchant).matchSnapshot()
1766
+ })
1767
+
1768
+ test('behavior: chainId', async () => {
1769
+ const porto = getPorto()
1770
+ const client = TestConfig.getRelayClient(porto)
1771
+
1772
+ const capabilities = await porto.provider.request({
1773
+ method: 'wallet_getCapabilities',
1774
+ params: [undefined, [Hex.fromNumber(client.chain.id)]],
1775
+ })
1776
+
1777
+ const keys = Object.keys(capabilities)
1778
+ expect(keys).matchSnapshot()
1779
+
1780
+ const values = Object.values(capabilities)
1781
+ const { atomic, feeToken, permissions, merchant } = values[0]!
1782
+ expect(atomic).matchSnapshot()
1783
+ expect(feeToken.supported).matchSnapshot()
1784
+ expect(
1785
+ feeToken.tokens
1786
+ .map((x) => ({ ...x, nativeRate: null }))
1787
+ .toSorted((a, b) => a.address.localeCompare(b.address)),
1788
+ ).matchSnapshot()
1789
+ expect(permissions).matchSnapshot()
1790
+ expect(merchant).matchSnapshot()
1791
+ })
1792
+ })
1793
+
1794
+ describe('wallet_sendCalls', () => {
1795
+ test('default', async () => {
1796
+ const porto = getPorto()
1797
+ const client = TestConfig.getRelayClient(porto)
1798
+ const contracts = await TestConfig.getContracts(porto)
1799
+
1800
+ const {
1801
+ accounts: [account],
1802
+ } = await porto.provider.request({
1803
+ method: 'wallet_connect',
1804
+ params: [{ capabilities: { createAccount: true } }],
1805
+ })
1806
+ const address = account!.address
1807
+
1808
+ await setBalance(client, {
1809
+ address,
1810
+ value: Value.fromEther('10000'),
1811
+ })
1812
+
1813
+ const alice = Hex.random(20)
1814
+
1815
+ const { id } = await porto.provider.request({
1816
+ method: 'wallet_sendCalls',
1817
+ params: [
1818
+ {
1819
+ calls: [
1820
+ {
1821
+ data: encodeFunctionData({
1822
+ abi: contracts.exp1.abi,
1823
+ args: [alice, 69420n],
1824
+ functionName: 'transfer',
1825
+ }),
1826
+ to: contracts.exp1.address,
1827
+ },
1828
+ ],
1829
+ from: address,
1830
+ version: '1',
1831
+ },
1832
+ ],
1833
+ })
1834
+
1835
+ expect(id).toBeDefined()
1836
+
1837
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
1838
+ id,
1839
+ })
1840
+
1841
+ expect(
1842
+ await readContract(client, {
1843
+ abi: contracts.exp1.abi,
1844
+ address: contracts.exp1.address,
1845
+ args: [alice],
1846
+ functionName: 'balanceOf',
1847
+ }),
1848
+ ).toBe(69420n)
1849
+ })
1850
+
1851
+ test.runIf(type === 'relay' && Anvil.enabled)(
1852
+ 'behavior: `feeToken` capability',
1853
+ async () => {
1854
+ const porto = getPorto()
1855
+ const client = TestConfig.getRelayClient(porto)
1856
+ const contracts = await TestConfig.getContracts(porto)
1857
+
1858
+ const {
1859
+ accounts: [account],
1860
+ } = await porto.provider.request({
1861
+ method: 'wallet_connect',
1862
+ params: [
1863
+ {
1864
+ capabilities: { createAccount: true },
1865
+ },
1866
+ ],
1867
+ })
1868
+ const address = account!.address
1869
+
1870
+ await viem_setBalance(client, {
1871
+ address,
1872
+ value: Value.fromEther('10000'),
1873
+ })
1874
+ await setBalance(client, {
1875
+ address,
1876
+ value: Value.fromEther('10000'),
1877
+ })
1878
+
1879
+ const alice = Hex.random(20)
1880
+
1881
+ const { id } = await porto.provider.request({
1882
+ method: 'wallet_sendCalls',
1883
+ params: [
1884
+ {
1885
+ calls: [
1886
+ {
1887
+ data: encodeFunctionData({
1888
+ abi: contracts.exp1.abi,
1889
+ args: [alice, 100n],
1890
+ functionName: 'mint',
1891
+ }),
1892
+ to: contracts.exp1.address,
1893
+ },
1894
+ ],
1895
+ capabilities: {
1896
+ feeToken: '0x0000000000000000000000000000000000000000',
1897
+ },
1898
+ from: address,
1899
+ version: '1',
1900
+ },
1901
+ ],
1902
+ })
1903
+
1904
+ expect(id).toBeDefined()
1905
+
1906
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
1907
+ id,
1908
+ })
1909
+
1910
+ expect(
1911
+ await readContract(client, {
1912
+ abi: contracts.exp1.abi,
1913
+ address: contracts.exp1.address,
1914
+ args: [address],
1915
+ functionName: 'balanceOf',
1916
+ }),
1917
+ ).toBe(Value.fromEther('10000'))
1918
+ expect(
1919
+ await readContract(client, {
1920
+ abi: contracts.exp1.abi,
1921
+ address: contracts.exp1.address,
1922
+ args: [alice],
1923
+ functionName: 'balanceOf',
1924
+ }),
1925
+ ).toBe(100n)
1926
+ },
1927
+ )
1928
+
1929
+ test.runIf(type === 'relay')('behavior: merchant fee sponsor', async () => {
1930
+ const porto = getPorto()
1931
+ const client = TestConfig.getRelayClient(porto)
1932
+ const contracts = await TestConfig.getContracts(porto)
1933
+
1934
+ const merchantKey = Key.createSecp256k1()
1935
+ const merchantAccount = await createAccount(client, {
1936
+ deploy: true,
1937
+ keys: [merchantKey],
1938
+ })
1939
+
1940
+ const listener = Route.merchant({
1941
+ ...porto.config,
1942
+ address: merchantAccount.address,
1943
+ key: {
1944
+ privateKey: merchantKey.privateKey!(),
1945
+ type: merchantKey.type,
1946
+ },
1947
+ }).listener
1948
+ const server = await Http.createServer(listener)
1949
+
1950
+ const {
1951
+ accounts: [account],
1952
+ } = await porto.provider.request({
1953
+ method: 'wallet_connect',
1954
+ params: [
1955
+ {
1956
+ capabilities: { createAccount: true },
1957
+ },
1958
+ ],
1959
+ })
1960
+ const address = account!.address
1961
+
1962
+ await setBalance(client, {
1963
+ address,
1964
+ value: Value.fromEther('10000'),
1965
+ })
1966
+
1967
+ const userBalance_pre = await readContract(client, {
1968
+ abi: contracts.exp1.abi,
1969
+ address: contracts.exp1.address,
1970
+ args: [address],
1971
+ functionName: 'balanceOf',
1972
+ })
1973
+ const merchantBalance_pre = await readContract(client, {
1974
+ abi: contracts.exp1.abi,
1975
+ address: contracts.exp1.address,
1976
+ args: [merchantAccount.address],
1977
+ functionName: 'balanceOf',
1978
+ })
1979
+
1980
+ const { id } = await porto.provider.request({
1981
+ method: 'wallet_sendCalls',
1982
+ params: [
1983
+ {
1984
+ calls: [
1985
+ {
1986
+ data: encodeFunctionData({
1987
+ abi: contracts.exp1.abi,
1988
+ args: [Hex.random(20), Value.fromEther('1')],
1989
+ functionName: 'transfer',
1990
+ }),
1991
+ to: contracts.exp1.address,
1992
+ },
1993
+ ],
1994
+ capabilities: {
1995
+ merchantUrl: server.url,
1996
+ },
1997
+ from: address,
1998
+ version: '1',
1999
+ },
2000
+ ],
2001
+ })
2002
+
2003
+ expect(id).toBeDefined()
2004
+
2005
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2006
+ id,
2007
+ })
2008
+
2009
+ const userBalance_post = await readContract(client, {
2010
+ abi: contracts.exp1.abi,
2011
+ address: contracts.exp1.address,
2012
+ args: [address],
2013
+ functionName: 'balanceOf',
2014
+ })
2015
+ const merchantBalance_post = await readContract(client, {
2016
+ abi: contracts.exp1.abi,
2017
+ address: contracts.exp1.address,
2018
+ args: [merchantAccount.address],
2019
+ functionName: 'balanceOf',
2020
+ })
2021
+
2022
+ // Check if user was debited 1 EXP.
2023
+ expect(userBalance_post).toBe(userBalance_pre - Value.fromEther('1'))
2024
+
2025
+ // Check if merchant was debited the fee payment.
2026
+ expect(merchantBalance_post).toBeLessThan(merchantBalance_pre)
2027
+ })
2028
+
2029
+ test('behavior: merchant fee sponsor (porto config)', async () => {
2030
+ const p = getPorto()
2031
+ const client = TestConfig.getRelayClient(p)
2032
+ const contracts = await TestConfig.getContracts(p)
2033
+
2034
+ const merchantKey = Key.createSecp256k1()
2035
+ const merchantAccount = await createAccount(client, {
2036
+ deploy: true,
2037
+ keys: [merchantKey],
2038
+ })
2039
+
2040
+ const listener = Route.merchant({
2041
+ ...p.config,
2042
+ address: merchantAccount.address,
2043
+ key: {
2044
+ privateKey: merchantKey.privateKey!(),
2045
+ type: merchantKey.type,
2046
+ },
2047
+ }).listener
2048
+ const server = await Http.createServer(listener)
2049
+
2050
+ const porto = getPorto({ merchantUrl: server.url })
2051
+
2052
+ const {
2053
+ accounts: [account],
2054
+ } = await porto.provider.request({
2055
+ method: 'wallet_connect',
2056
+ params: [
2057
+ {
2058
+ capabilities: { createAccount: true },
2059
+ },
2060
+ ],
2061
+ })
2062
+ const address = account!.address
2063
+
2064
+ await setBalance(client, {
2065
+ address,
2066
+ value: Value.fromEther('10000'),
2067
+ })
2068
+
2069
+ const userBalance_pre = await readContract(client, {
2070
+ abi: contracts.exp1.abi,
2071
+ address: contracts.exp1.address,
2072
+ args: [address],
2073
+ functionName: 'balanceOf',
2074
+ })
2075
+ const merchantBalance_pre = await readContract(client, {
2076
+ abi: contracts.exp1.abi,
2077
+ address: contracts.exp1.address,
2078
+ args: [merchantAccount.address],
2079
+ functionName: 'balanceOf',
2080
+ })
2081
+
2082
+ const { id } = await porto.provider.request({
2083
+ method: 'wallet_sendCalls',
2084
+ params: [
2085
+ {
2086
+ calls: [
2087
+ {
2088
+ data: encodeFunctionData({
2089
+ abi: contracts.exp1.abi,
2090
+ args: [Hex.random(20), Value.fromEther('1')],
2091
+ functionName: 'transfer',
2092
+ }),
2093
+ to: contracts.exp1.address,
2094
+ },
2095
+ ],
2096
+ from: address,
2097
+ version: '1',
2098
+ },
2099
+ ],
2100
+ })
2101
+
2102
+ expect(id).toBeDefined()
2103
+
2104
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2105
+ id,
2106
+ })
2107
+
2108
+ const userBalance_post = await readContract(client, {
2109
+ abi: contracts.exp1.abi,
2110
+ address: contracts.exp1.address,
2111
+ args: [address],
2112
+ functionName: 'balanceOf',
2113
+ })
2114
+ const merchantBalance_post = await readContract(client, {
2115
+ abi: contracts.exp1.abi,
2116
+ address: contracts.exp1.address,
2117
+ args: [merchantAccount.address],
2118
+ functionName: 'balanceOf',
2119
+ })
2120
+
2121
+ // Check if user was debited 1 EXP.
2122
+ expect(userBalance_post).toBe(userBalance_pre - Value.fromEther('1'))
2123
+
2124
+ // Check if merchant was debited the fee payment.
2125
+ expect(merchantBalance_post).toBeLessThan(merchantBalance_pre)
2126
+ })
2127
+
2128
+ test('behavior: use inferred permissions', async () => {
2129
+ const porto = getPorto()
2130
+ const client = TestConfig.getRelayClient(porto)
2131
+ const contracts = await TestConfig.getContracts(porto)
2132
+
2133
+ const {
2134
+ accounts: [account],
2135
+ } = await porto.provider.request({
2136
+ method: 'wallet_connect',
2137
+ params: [{ capabilities: { createAccount: true } }],
2138
+ })
2139
+ const address = account!.address
2140
+
2141
+ await setBalance(client, {
2142
+ address,
2143
+ value: Value.fromEther('10000'),
2144
+ })
2145
+
2146
+ const alice = Hex.random(20)
2147
+
2148
+ await porto.provider.request({
2149
+ method: 'wallet_grantPermissions',
2150
+ params: [
2151
+ {
2152
+ expiry: 9999999999,
2153
+ feeToken: {
2154
+ limit: '1',
2155
+ symbol: 'EXP',
2156
+ },
2157
+ permissions: {
2158
+ calls: [{ to: contracts.exp1.address }],
2159
+ spend: [
2160
+ {
2161
+ limit: Hex.fromNumber(Value.fromEther('50')),
2162
+ period: 'day',
2163
+ token: contracts.exp1.address,
2164
+ },
2165
+ ],
2166
+ },
2167
+ },
2168
+ ],
2169
+ })
2170
+
2171
+ const { id } = await porto.provider.request({
2172
+ method: 'wallet_sendCalls',
2173
+ params: [
2174
+ {
2175
+ calls: [
2176
+ {
2177
+ data: encodeFunctionData({
2178
+ abi: contracts.exp1.abi,
2179
+ args: [alice, Value.fromEther('50')],
2180
+ functionName: 'transfer',
2181
+ }),
2182
+ to: contracts.exp1.address,
2183
+ },
2184
+ ],
2185
+ from: address,
2186
+ version: '1',
2187
+ },
2188
+ ],
2189
+ })
2190
+
2191
+ expect(id).toBeDefined()
2192
+
2193
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2194
+ id,
2195
+ })
2196
+
2197
+ expect(
2198
+ await readContract(client, {
2199
+ abi: contracts.exp1.abi,
2200
+ address: contracts.exp1.address,
2201
+ args: [alice],
2202
+ functionName: 'balanceOf',
2203
+ }),
2204
+ ).toBe(Value.fromEther('50'))
2205
+ })
2206
+
2207
+ test('behavior: `permissions` capability', async () => {
2208
+ const porto = getPorto()
2209
+ const client = TestConfig.getRelayClient(porto)
2210
+ const contracts = await TestConfig.getContracts(porto)
2211
+
2212
+ const {
2213
+ accounts: [account],
2214
+ } = await porto.provider.request({
2215
+ method: 'wallet_connect',
2216
+ params: [{ capabilities: { createAccount: true } }],
2217
+ })
2218
+ const address = account!.address
2219
+
2220
+ await setBalance(client, {
2221
+ address,
2222
+ value: Value.fromEther('10000'),
2223
+ })
2224
+
2225
+ const alice = Hex.random(20)
2226
+
2227
+ const permissions = await porto.provider.request({
2228
+ method: 'wallet_grantPermissions',
2229
+ params: [
2230
+ {
2231
+ expiry: 9999999999,
2232
+ feeToken: {
2233
+ limit: '1',
2234
+ symbol: 'EXP',
2235
+ },
2236
+ permissions: {
2237
+ calls: [{ to: contracts.exp1.address }],
2238
+ spend: [
2239
+ {
2240
+ limit: Hex.fromNumber(69420),
2241
+ period: 'day',
2242
+ token: contracts.exp1.address,
2243
+ },
2244
+ ],
2245
+ },
2246
+ },
2247
+ ],
2248
+ })
2249
+ const { id } = await porto.provider.request({
2250
+ method: 'wallet_sendCalls',
2251
+ params: [
2252
+ {
2253
+ calls: [
2254
+ {
2255
+ data: encodeFunctionData({
2256
+ abi: contracts.exp1.abi,
2257
+ args: [alice, 40_000n],
2258
+ functionName: 'transfer',
2259
+ }),
2260
+ to: contracts.exp1.address,
2261
+ },
2262
+ ],
2263
+ capabilities: {
2264
+ permissions,
2265
+ },
2266
+ from: address,
2267
+ version: '1',
2268
+ },
2269
+ ],
2270
+ })
2271
+
2272
+ expect(id).toBeDefined()
2273
+
2274
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2275
+ id,
2276
+ })
2277
+
2278
+ expect(
2279
+ await readContract(client, {
2280
+ abi: contracts.exp1.abi,
2281
+ address: contracts.exp1.address,
2282
+ args: [alice],
2283
+ functionName: 'balanceOf',
2284
+ }),
2285
+ ).toBe(40_000n)
2286
+ })
2287
+
2288
+ // TODO: remove condition once Anvil supports reverts on delegated accounts.
2289
+ test.runIf(type === 'relay')(
2290
+ 'behavior: `permissions.calls` unauthorized',
2291
+ async () => {
2292
+ const porto = getPorto()
2293
+ const client = TestConfig.getRelayClient(porto)
2294
+ const contracts = await TestConfig.getContracts(porto)
2295
+
2296
+ const {
2297
+ accounts: [account],
2298
+ } = await porto.provider.request({
2299
+ method: 'wallet_connect',
2300
+ params: [
2301
+ {
2302
+ capabilities: { createAccount: true },
2303
+ },
2304
+ ],
2305
+ })
2306
+ const address = account!.address
2307
+
2308
+ await setBalance(client, {
2309
+ address,
2310
+ value: Value.fromEther('10000'),
2311
+ })
2312
+
2313
+ const alice = '0x0000000000000000000000000000000000069422'
2314
+
2315
+ const permissions = await porto.provider.request({
2316
+ method: 'wallet_grantPermissions',
2317
+ params: [
2318
+ {
2319
+ expiry: 9999999999,
2320
+ feeToken: {
2321
+ limit: '1',
2322
+ symbol: 'EXP',
2323
+ },
2324
+ permissions: {
2325
+ calls: [{ to: '0x0000000000000000000000000000000000000000' }],
2326
+ spend: [
2327
+ {
2328
+ limit: Hex.fromNumber(69420),
2329
+ period: 'day',
2330
+ token: contracts.exp1.address,
2331
+ },
2332
+ ],
2333
+ },
2334
+ },
2335
+ ],
2336
+ })
2337
+ await expect(() =>
2338
+ porto.provider.request({
2339
+ method: 'wallet_sendCalls',
2340
+ params: [
2341
+ {
2342
+ calls: [
2343
+ {
2344
+ data: encodeFunctionData({
2345
+ abi: contracts.exp1.abi,
2346
+ args: [alice, 69420n],
2347
+ functionName: 'mint',
2348
+ }),
2349
+ to: contracts.exp1.address,
2350
+ },
2351
+ ],
2352
+ capabilities: {
2353
+ permissions,
2354
+ },
2355
+ from: address,
2356
+ version: '1',
2357
+ },
2358
+ ],
2359
+ }),
2360
+ ).rejects.toThrowError('Unauthorized')
2361
+ },
2362
+ )
2363
+
2364
+ // TODO: remove condition once Anvil supports reverts on delegated accounts.
2365
+ test.runIf(type === 'relay')(
2366
+ 'behavior: `permissions.spend` exceeded',
2367
+ async () => {
2368
+ const porto = getPorto()
2369
+ const client = TestConfig.getRelayClient(porto)
2370
+ const contracts = await TestConfig.getContracts(porto)
2371
+
2372
+ const {
2373
+ accounts: [account],
2374
+ } = await porto.provider.request({
2375
+ method: 'wallet_connect',
2376
+ params: [
2377
+ {
2378
+ capabilities: { createAccount: true },
2379
+ },
2380
+ ],
2381
+ })
2382
+ const address = account!.address
2383
+
2384
+ await setBalance(client, {
2385
+ address,
2386
+ value: Value.fromEther('10000'),
2387
+ })
2388
+
2389
+ const alice = Hex.random(20)
2390
+
2391
+ const permissions = await porto.provider.request({
2392
+ method: 'wallet_grantPermissions',
2393
+ params: [
2394
+ {
2395
+ expiry: 9999999999,
2396
+ feeToken: {
2397
+ limit: '1',
2398
+ symbol: 'EXP',
2399
+ },
2400
+ permissions: {
2401
+ calls: [{ to: contracts.exp1.address }],
2402
+ spend: [
2403
+ {
2404
+ limit: Hex.fromNumber(Value.fromEther('50')),
2405
+ period: 'day',
2406
+ token: contracts.exp1.address,
2407
+ },
2408
+ ],
2409
+ },
2410
+ },
2411
+ ],
2412
+ })
2413
+
2414
+ const { id } = await porto.provider.request({
2415
+ method: 'wallet_sendCalls',
2416
+ params: [
2417
+ {
2418
+ calls: [
2419
+ {
2420
+ data: encodeFunctionData({
2421
+ abi: contracts.exp1.abi,
2422
+ args: [alice, Value.fromEther('50')],
2423
+ functionName: 'transfer',
2424
+ }),
2425
+ to: contracts.exp1.address,
2426
+ },
2427
+ ],
2428
+ capabilities: {
2429
+ permissions,
2430
+ },
2431
+ from: address,
2432
+ version: '1',
2433
+ },
2434
+ ],
2435
+ })
2436
+
2437
+ expect(id).toBeDefined()
2438
+
2439
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2440
+ id,
2441
+ })
2442
+
2443
+ await expect(() =>
2444
+ porto.provider.request({
2445
+ method: 'wallet_sendCalls',
2446
+ params: [
2447
+ {
2448
+ calls: [
2449
+ {
2450
+ data: encodeFunctionData({
2451
+ abi: contracts.exp1.abi,
2452
+ args: [alice, Value.fromEther('200')],
2453
+ functionName: 'transfer',
2454
+ }),
2455
+ to: contracts.exp1.address,
2456
+ },
2457
+ ],
2458
+ capabilities: {
2459
+ permissions,
2460
+ },
2461
+ from: address,
2462
+ version: '1',
2463
+ },
2464
+ ],
2465
+ }),
2466
+ ).rejects.toThrowError('ExceededSpendLimit')
2467
+ },
2468
+ )
2469
+
2470
+ test('behavior: revoked permission', async () => {
2471
+ const porto = getPorto()
2472
+ const client = TestConfig.getRelayClient(porto)
2473
+ const contracts = await TestConfig.getContracts(porto)
2474
+
2475
+ const {
2476
+ accounts: [account],
2477
+ } = await porto.provider.request({
2478
+ method: 'wallet_connect',
2479
+ params: [{ capabilities: { createAccount: true } }],
2480
+ })
2481
+ const address = account!.address
2482
+
2483
+ await setBalance(client, {
2484
+ address,
2485
+ value: Value.fromEther('10000'),
2486
+ })
2487
+
2488
+ const alice = Hex.random(20)
2489
+
2490
+ const permissions = await porto.provider.request({
2491
+ method: 'wallet_grantPermissions',
2492
+ params: [
2493
+ {
2494
+ expiry: 9999999999,
2495
+ feeToken: {
2496
+ limit: '1',
2497
+ symbol: 'EXP',
2498
+ },
2499
+ permissions: {
2500
+ calls: [{ to: contracts.exp1.address }],
2501
+ spend: [
2502
+ {
2503
+ limit: Hex.fromNumber(69420 * 3),
2504
+ period: 'day',
2505
+ token: contracts.exp1.address,
2506
+ },
2507
+ ],
2508
+ },
2509
+ },
2510
+ ],
2511
+ })
2512
+ const { id } = await porto.provider.request({
2513
+ method: 'wallet_sendCalls',
2514
+ params: [
2515
+ {
2516
+ calls: [
2517
+ {
2518
+ data: encodeFunctionData({
2519
+ abi: contracts.exp1.abi,
2520
+ args: [alice, 69420n],
2521
+ functionName: 'transfer',
2522
+ }),
2523
+ to: contracts.exp1.address,
2524
+ },
2525
+ ],
2526
+ capabilities: {
2527
+ permissions,
2528
+ },
2529
+ from: address,
2530
+ version: '1',
2531
+ },
2532
+ ],
2533
+ })
2534
+
2535
+ expect(id).toBeDefined()
2536
+
2537
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2538
+ id,
2539
+ })
2540
+
2541
+ expect(
2542
+ await readContract(client, {
2543
+ abi: contracts.exp1.abi,
2544
+ address: contracts.exp1.address,
2545
+ args: [alice],
2546
+ functionName: 'balanceOf',
2547
+ }),
2548
+ ).toBe(69420n)
2549
+
2550
+ await porto.provider.request({
2551
+ method: 'wallet_revokePermissions',
2552
+ params: [{ id: permissions.id }],
2553
+ })
2554
+ await expect(() =>
2555
+ porto.provider.request({
2556
+ method: 'wallet_sendCalls',
2557
+ params: [
2558
+ {
2559
+ calls: [
2560
+ {
2561
+ data: encodeFunctionData({
2562
+ abi: contracts.exp1.abi,
2563
+ args: [alice, 69420n],
2564
+ functionName: 'transfer',
2565
+ }),
2566
+ to: contracts.exp1.address,
2567
+ },
2568
+ ],
2569
+ capabilities: {
2570
+ permissions,
2571
+ },
2572
+ from: address,
2573
+ version: '1',
2574
+ },
2575
+ ],
2576
+ }),
2577
+ ).rejects.toThrowError()
2578
+ })
2579
+
2580
+ test('behavior: not provider-managed permission', async () => {
2581
+ const porto = getPorto()
2582
+ const client = TestConfig.getRelayClient(porto)
2583
+ const contracts = await TestConfig.getContracts(porto)
2584
+
2585
+ const {
2586
+ accounts: [account],
2587
+ } = await porto.provider.request({
2588
+ method: 'wallet_connect',
2589
+ params: [{ capabilities: { createAccount: true } }],
2590
+ })
2591
+ const address = account!.address
2592
+
2593
+ await setBalance(client, {
2594
+ address,
2595
+ value: Value.fromEther('10000'),
2596
+ })
2597
+
2598
+ const alice = Hex.random(20)
2599
+
2600
+ const { id } = await porto.provider.request({
2601
+ method: 'wallet_grantPermissions',
2602
+ params: [
2603
+ {
2604
+ expiry: 9999999999,
2605
+ feeToken: {
2606
+ limit: '1',
2607
+ symbol: 'EXP',
2608
+ },
2609
+ key: {
2610
+ publicKey:
2611
+ '0x86a0d77beccf47a0a78cccfc19fdfe7317816740c9f9e6d7f696a02b0c66e0e21744d93c5699e9ce658a64ce60df2f32a17954cd577c713922bf62a1153cf68e',
2612
+ type: 'p256',
2613
+ },
2614
+ permissions: {
2615
+ calls: [{ to: contracts.exp1.address }],
2616
+ },
2617
+ },
2618
+ ],
2619
+ })
2620
+ await expect(() =>
2621
+ porto.provider.request({
2622
+ method: 'wallet_sendCalls',
2623
+ params: [
2624
+ {
2625
+ calls: [
2626
+ {
2627
+ data: encodeFunctionData({
2628
+ abi: contracts.exp1.abi,
2629
+ args: [alice, 69420n],
2630
+ functionName: 'transfer',
2631
+ }),
2632
+ to: contracts.exp1.address,
2633
+ },
2634
+ ],
2635
+ capabilities: {
2636
+ permissions: {
2637
+ id,
2638
+ },
2639
+ },
2640
+ from: address,
2641
+ version: '1',
2642
+ },
2643
+ ],
2644
+ }),
2645
+ ).rejects.matchSnapshot()
2646
+ })
2647
+
2648
+ test('behavior: permission does not exist', async () => {
2649
+ const porto = getPorto()
2650
+ const client = TestConfig.getRelayClient(porto)
2651
+ const contracts = await TestConfig.getContracts(porto)
2652
+
2653
+ const {
2654
+ accounts: [account],
2655
+ } = await porto.provider.request({
2656
+ method: 'wallet_connect',
2657
+ params: [{ capabilities: { createAccount: true } }],
2658
+ })
2659
+ const address = account!.address
2660
+
2661
+ await setBalance(client, {
2662
+ address,
2663
+ value: Value.fromEther('10000'),
2664
+ })
2665
+
2666
+ const alice = Hex.random(20)
2667
+
2668
+ await expect(() =>
2669
+ porto.provider.request({
2670
+ method: 'wallet_sendCalls',
2671
+ params: [
2672
+ {
2673
+ calls: [
2674
+ {
2675
+ data: encodeFunctionData({
2676
+ abi: contracts.exp1.abi,
2677
+ args: [alice, 69420n],
2678
+ functionName: 'transfer',
2679
+ }),
2680
+ to: contracts.exp1.address,
2681
+ },
2682
+ ],
2683
+ capabilities: {
2684
+ permissions: {
2685
+ id: '0x86a0d77beccf47a0a78cccfc19fdfe7317816740c9f9e6d7f696a02b0c66e0e21744d93c5699e9ce658a64ce60df2f32a17954cd577c713922bf62a1153cf68e',
2686
+ },
2687
+ },
2688
+ from: address,
2689
+ version: '1',
2690
+ },
2691
+ ],
2692
+ }),
2693
+ ).rejects.matchSnapshot()
2694
+ })
2695
+
2696
+ test.runIf(!Anvil.enabled && type === 'relay')(
2697
+ 'behavior: required funds (address)',
2698
+ async () => {
2699
+ const porto = getPorto()
2700
+ const client = TestConfig.getRelayClient(porto)
2701
+ const contracts = await TestConfig.getContracts(porto)
2702
+
2703
+ const {
2704
+ accounts: [account],
2705
+ } = await porto.provider.request({
2706
+ method: 'wallet_connect',
2707
+ params: [{ capabilities: { createAccount: true } }],
2708
+ })
2709
+ const address = account!.address
2710
+
2711
+ const initialBalance = Value.fromEther('10000')
2712
+ await setBalance(client, {
2713
+ address,
2714
+ value: initialBalance,
2715
+ })
2716
+
2717
+ const alice = Hex.random(20)
2718
+ const chainId_dest = TestConfig.chains[1]!.id
2719
+
2720
+ const { id } = await porto.provider.request({
2721
+ method: 'wallet_sendCalls',
2722
+ params: [
2723
+ {
2724
+ calls: [
2725
+ {
2726
+ data: encodeFunctionData({
2727
+ abi: contracts.exp1.abi,
2728
+ args: [alice, Value.fromEther('50')],
2729
+ functionName: 'transfer',
2730
+ }),
2731
+ to: contracts.exp1.address,
2732
+ },
2733
+ ],
2734
+ capabilities: {
2735
+ // TODO: allow `requiredFunds` to be set without `feeToken`
2736
+ feeToken: contracts.exp1.address,
2737
+ requiredFunds: [
2738
+ {
2739
+ address: contracts.exp1.address,
2740
+ value: Hex.fromNumber(Value.fromEther('50')),
2741
+ },
2742
+ ],
2743
+ },
2744
+ chainId: Hex.fromNumber(chainId_dest),
2745
+ from: address,
2746
+ version: '1',
2747
+ },
2748
+ ],
2749
+ })
2750
+
2751
+ expect(id).toBeDefined()
2752
+
2753
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2754
+ id,
2755
+ })
2756
+
2757
+ const balance = await readContract(client, {
2758
+ abi: contracts.exp1.abi,
2759
+ address: contracts.exp1.address,
2760
+ args: [address],
2761
+ functionName: 'balanceOf',
2762
+ })
2763
+ expect(balance).toBeLessThan(initialBalance)
2764
+
2765
+ const client_dest = TestConfig.getRelayClient(porto, {
2766
+ chainId: chainId_dest,
2767
+ })
2768
+
2769
+ const balance_dest = await readContract(client_dest, {
2770
+ abi: contracts.exp1.abi,
2771
+ address: contracts.exp1.address,
2772
+ args: [alice],
2773
+ functionName: 'balanceOf',
2774
+ })
2775
+ expect(balance_dest).toBeGreaterThanOrEqual(Value.fromEther('50'))
2776
+ expect(balance_dest).toBeLessThan(Value.fromEther('50.0005'))
2777
+ },
2778
+ )
2779
+
2780
+ test.runIf(!Anvil.enabled && type === 'relay')(
2781
+ 'behavior: required funds (symbol)',
2782
+ async () => {
2783
+ const porto = getPorto()
2784
+ const client = TestConfig.getRelayClient(porto)
2785
+ const contracts = await TestConfig.getContracts(porto)
2786
+
2787
+ const {
2788
+ accounts: [account],
2789
+ } = await porto.provider.request({
2790
+ method: 'wallet_connect',
2791
+ params: [{ capabilities: { createAccount: true } }],
2792
+ })
2793
+ const address = account!.address
2794
+
2795
+ const initialBalance = Value.fromEther('10000')
2796
+ await setBalance(client, {
2797
+ address,
2798
+ value: initialBalance,
2799
+ })
2800
+
2801
+ const alice = Hex.random(20)
2802
+ const chainId_dest = TestConfig.chains[1]!.id
2803
+
2804
+ const { id } = await porto.provider.request({
2805
+ method: 'wallet_sendCalls',
2806
+ params: [
2807
+ {
2808
+ calls: [
2809
+ {
2810
+ data: encodeFunctionData({
2811
+ abi: contracts.exp1.abi,
2812
+ args: [alice, Value.fromEther('50')],
2813
+ functionName: 'transfer',
2814
+ }),
2815
+ to: contracts.exp1.address,
2816
+ },
2817
+ ],
2818
+ capabilities: {
2819
+ // TODO: allow `requiredFunds` to be set without `feeToken`
2820
+ feeToken: contracts.exp1.address,
2821
+ requiredFunds: [
2822
+ {
2823
+ symbol: 'EXP',
2824
+ value: '50',
2825
+ },
2826
+ ],
2827
+ },
2828
+ chainId: Hex.fromNumber(chainId_dest),
2829
+ from: address,
2830
+ version: '1',
2831
+ },
2832
+ ],
2833
+ })
2834
+
2835
+ expect(id).toBeDefined()
2836
+
2837
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
2838
+ id,
2839
+ })
2840
+
2841
+ const balance = await readContract(client, {
2842
+ abi: contracts.exp1.abi,
2843
+ address: contracts.exp1.address,
2844
+ args: [address],
2845
+ functionName: 'balanceOf',
2846
+ })
2847
+ expect(balance).toBeLessThan(initialBalance)
2848
+
2849
+ const client_dest = TestConfig.getRelayClient(porto, {
2850
+ chainId: chainId_dest,
2851
+ })
2852
+
2853
+ const balance_dest = await readContract(client_dest, {
2854
+ abi: contracts.exp1.abi,
2855
+ address: contracts.exp1.address,
2856
+ args: [alice],
2857
+ functionName: 'balanceOf',
2858
+ })
2859
+ expect(balance_dest).toBeGreaterThanOrEqual(Value.fromEther('50'))
2860
+ expect(balance_dest).toBeLessThan(Value.fromEther('50.0005'))
2861
+ },
2862
+ )
2863
+
2864
+ test('behavior: no calls.to', async () => {
2865
+ const porto = getPorto()
2866
+
2867
+ const {
2868
+ accounts: [account],
2869
+ } = await porto.provider.request({
2870
+ method: 'wallet_connect',
2871
+ params: [{ capabilities: { createAccount: true } }],
2872
+ })
2873
+ const address = account!.address
2874
+
2875
+ await expect(() =>
2876
+ porto.provider.request({
2877
+ method: 'wallet_sendCalls',
2878
+ params: [
2879
+ {
2880
+ calls: [
2881
+ // @ts-expect-error
2882
+ {
2883
+ data: '0xdeadbeef',
2884
+ },
2885
+ ],
2886
+ from: address,
2887
+ version: '1',
2888
+ },
2889
+ ],
2890
+ }),
2891
+ ).rejects.matchSnapshot()
2892
+ })
2893
+ })
2894
+
2895
+ describe('wallet_getCallsStatus', () => {
2896
+ test('default', async () => {
2897
+ const porto = getPorto()
2898
+ const client = TestConfig.getRelayClient(porto)
2899
+ const contracts = await TestConfig.getContracts(porto)
2900
+
2901
+ const {
2902
+ accounts: [account],
2903
+ } = await porto.provider.request({
2904
+ method: 'wallet_connect',
2905
+ params: [{ capabilities: { createAccount: true } }],
2906
+ })
2907
+ const address = account!.address
2908
+
2909
+ await setBalance(client, {
2910
+ address,
2911
+ value: Value.fromEther('10000'),
2912
+ })
2913
+
2914
+ const alice = Hex.random(20)
2915
+
2916
+ const { id } = await porto.provider.request({
2917
+ method: 'wallet_sendCalls',
2918
+ params: [
2919
+ {
2920
+ calls: [
2921
+ {
2922
+ data: encodeFunctionData({
2923
+ abi: contracts.exp1.abi,
2924
+ args: [alice, 69420n],
2925
+ functionName: 'transfer',
2926
+ }),
2927
+ to: contracts.exp1.address,
2928
+ },
2929
+ ],
2930
+ from: address,
2931
+ version: '1',
2932
+ },
2933
+ ],
2934
+ })
2935
+
2936
+ expect(id).toBeDefined()
2937
+
2938
+ const response = await porto.provider.request({
2939
+ method: 'wallet_getCallsStatus',
2940
+ params: [id],
2941
+ })
2942
+
2943
+ expect(response.id).toBe(id)
2944
+ })
2945
+ })
2946
+
2947
+ describe('wallet_getCallsStatus', () => {
2948
+ test('default', async () => {
2949
+ const porto = getPorto()
2950
+ const client = TestConfig.getRelayClient(porto)
2951
+ const contracts = await TestConfig.getContracts(porto)
2952
+
2953
+ const {
2954
+ accounts: [account],
2955
+ } = await porto.provider.request({
2956
+ method: 'wallet_connect',
2957
+ params: [{ capabilities: { createAccount: true } }],
2958
+ })
2959
+ const address = account!.address
2960
+
2961
+ await setBalance(client, {
2962
+ address,
2963
+ value: Value.fromEther('10000'),
2964
+ })
2965
+
2966
+ const alice = Hex.random(20)
2967
+
2968
+ const { id } = await porto.provider.request({
2969
+ method: 'wallet_sendCalls',
2970
+ params: [
2971
+ {
2972
+ calls: [
2973
+ {
2974
+ data: encodeFunctionData({
2975
+ abi: contracts.exp1.abi,
2976
+ args: [alice, 69420n],
2977
+ functionName: 'transfer',
2978
+ }),
2979
+ to: contracts.exp1.address,
2980
+ },
2981
+ ],
2982
+ from: address,
2983
+ version: '1',
2984
+ },
2985
+ ],
2986
+ })
2987
+
2988
+ expect(id).toBeDefined()
2989
+
2990
+ const response = await porto.provider.request({
2991
+ method: 'wallet_getCallsStatus',
2992
+ params: [id],
2993
+ })
2994
+
2995
+ expect(response.id).toBe(id)
2996
+ })
2997
+ })
2998
+
2999
+ describe('wallet_prepareCalls → wallet_sendPreparedCalls', () => {
3000
+ describe('behavior: permissions', () => {
3001
+ test('default', async () => {
3002
+ const porto = getPorto()
3003
+ const client = TestConfig.getRelayClient(porto)
3004
+ const contracts = await TestConfig.getContracts(porto)
3005
+
3006
+ const alice = Hex.random(20)
3007
+
3008
+ const privateKey = P256.randomPrivateKey()
3009
+ const publicKey = PublicKey.toHex(P256.getPublicKey({ privateKey }), {
3010
+ includePrefix: false,
3011
+ })
3012
+
3013
+ const { accounts } = await porto.provider.request({
3014
+ method: 'wallet_connect',
3015
+ params: [
3016
+ {
3017
+ capabilities: {
3018
+ createAccount: true,
3019
+ grantPermissions: {
3020
+ expiry: 9999999999,
3021
+ feeToken: {
3022
+ limit: '1',
3023
+ symbol: 'EXP',
3024
+ },
3025
+ key: {
3026
+ publicKey: publicKey,
3027
+ type: 'p256',
3028
+ },
3029
+ permissions: {
3030
+ calls: [{ to: contracts.exp1.address }],
3031
+ spend: [
3032
+ {
3033
+ limit: Hex.fromNumber(42069n),
3034
+ period: 'day',
3035
+ token: contracts.exp1.address,
3036
+ },
3037
+ ],
3038
+ },
3039
+ },
3040
+ },
3041
+ },
3042
+ ],
3043
+ })
3044
+
3045
+ await setBalance(client, {
3046
+ address: accounts[0]?.address!,
3047
+ value: Value.fromEther('10000'),
3048
+ })
3049
+
3050
+ const key = {
3051
+ publicKey,
3052
+ type: 'p256',
3053
+ } as const
3054
+
3055
+ const { digest, ...request } = await porto.provider.request({
3056
+ method: 'wallet_prepareCalls',
3057
+ params: [
3058
+ {
3059
+ calls: [
3060
+ {
3061
+ data: encodeFunctionData({
3062
+ abi: contracts.exp1.abi,
3063
+ args: [alice, 40_000n],
3064
+ functionName: 'transfer',
3065
+ }),
3066
+ to: contracts.exp1.address,
3067
+ },
3068
+ ],
3069
+ key,
3070
+ },
3071
+ ],
3072
+ })
3073
+
3074
+ const signature = P256.sign({ payload: digest, privateKey })
3075
+
3076
+ const result = await porto.provider.request({
3077
+ method: 'wallet_sendPreparedCalls',
3078
+ params: [
3079
+ {
3080
+ ...request,
3081
+ signature: Signature.toHex(signature),
3082
+ },
3083
+ ],
3084
+ })
3085
+
3086
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
3087
+ id: result[0]!.id,
3088
+ })
3089
+
3090
+ expect(
3091
+ await readContract(client, {
3092
+ abi: contracts.exp1.abi,
3093
+ address: contracts.exp1.address,
3094
+ args: [alice],
3095
+ functionName: 'balanceOf',
3096
+ }),
3097
+ ).toBe(40_000n)
3098
+ })
3099
+
3100
+ test('WebCryptoP256', async () => {
3101
+ const porto = getPorto()
3102
+ const client = TestConfig.getRelayClient(porto)
3103
+ const contracts = await TestConfig.getContracts(porto)
3104
+
3105
+ const alice = Hex.random(20)
3106
+
3107
+ const keyPair = await WebCryptoP256.createKeyPair()
3108
+ const publicKey = PublicKey.toHex(keyPair.publicKey, {
3109
+ includePrefix: false,
3110
+ })
3111
+
3112
+ const { accounts } = await porto.provider.request({
3113
+ method: 'wallet_connect',
3114
+ params: [
3115
+ {
3116
+ capabilities: {
3117
+ createAccount: true,
3118
+ grantPermissions: {
3119
+ expiry: 9999999999,
3120
+ feeToken: {
3121
+ limit: '1',
3122
+ symbol: 'EXP',
3123
+ },
3124
+ key: {
3125
+ publicKey: publicKey,
3126
+ type: 'p256',
3127
+ },
3128
+ permissions: {
3129
+ calls: [{ to: contracts.exp1.address }],
3130
+ spend: [
3131
+ {
3132
+ limit: Hex.fromNumber(42069n),
3133
+ period: 'day',
3134
+ token: contracts.exp1.address,
3135
+ },
3136
+ ],
3137
+ },
3138
+ },
3139
+ },
3140
+ },
3141
+ ],
3142
+ })
3143
+
3144
+ await setBalance(client, {
3145
+ address: accounts[0]?.address!,
3146
+ value: Value.fromEther('10000'),
3147
+ })
3148
+
3149
+ const key = {
3150
+ prehash: true,
3151
+ publicKey,
3152
+ type: 'p256',
3153
+ } as const
3154
+
3155
+ const { digest, ...request } = await porto.provider.request({
3156
+ method: 'wallet_prepareCalls',
3157
+ params: [
3158
+ {
3159
+ calls: [
3160
+ {
3161
+ data: encodeFunctionData({
3162
+ abi: contracts.exp1.abi,
3163
+ args: [alice, 40_000n],
3164
+ functionName: 'transfer',
3165
+ }),
3166
+ to: contracts.exp1.address,
3167
+ },
3168
+ ],
3169
+ key,
3170
+ },
3171
+ ],
3172
+ })
3173
+
3174
+ const signature = await WebCryptoP256.sign({
3175
+ payload: digest,
3176
+ privateKey: keyPair.privateKey,
3177
+ })
3178
+
3179
+ const result = await porto.provider.request({
3180
+ method: 'wallet_sendPreparedCalls',
3181
+ params: [
3182
+ {
3183
+ ...request,
3184
+ key,
3185
+ signature: Signature.toHex(signature),
3186
+ },
3187
+ ],
3188
+ })
3189
+
3190
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
3191
+ id: result[0]!.id,
3192
+ })
3193
+
3194
+ expect(
3195
+ await readContract(client, {
3196
+ abi: contracts.exp1.abi,
3197
+ address: contracts.exp1.address,
3198
+ args: [alice],
3199
+ functionName: 'balanceOf',
3200
+ }),
3201
+ ).toBe(40_000n)
3202
+ })
3203
+
3204
+ test('Secp256k1', async () => {
3205
+ const porto = getPorto()
3206
+ const client = TestConfig.getRelayClient(porto)
3207
+ const contracts = await TestConfig.getContracts(porto)
3208
+
3209
+ const alice = Hex.random(20)
3210
+
3211
+ const privateKey = Secp256k1.randomPrivateKey()
3212
+ const publicKey = Secp256k1.getPublicKey({ privateKey })
3213
+ const address = Address.fromPublicKey(publicKey)
3214
+
3215
+ const { accounts } = await porto.provider.request({
3216
+ method: 'wallet_connect',
3217
+ params: [
3218
+ {
3219
+ capabilities: {
3220
+ createAccount: true,
3221
+ grantPermissions: {
3222
+ expiry: 9999999999,
3223
+ feeToken: {
3224
+ limit: '1',
3225
+ symbol: 'EXP',
3226
+ },
3227
+ key: {
3228
+ publicKey: address,
3229
+ type: 'address',
3230
+ },
3231
+ permissions: {
3232
+ calls: [{ to: contracts.exp1.address }],
3233
+ spend: [
3234
+ {
3235
+ limit: Hex.fromNumber(42069n),
3236
+ period: 'day',
3237
+ token: contracts.exp1.address,
3238
+ },
3239
+ ],
3240
+ },
3241
+ },
3242
+ },
3243
+ },
3244
+ ],
3245
+ })
3246
+
3247
+ await setBalance(client, {
3248
+ address: accounts[0]?.address!,
3249
+ value: Value.fromEther('10000'),
3250
+ })
3251
+
3252
+ const key = {
3253
+ publicKey: address,
3254
+ type: 'secp256k1',
3255
+ } as const
3256
+
3257
+ const { digest, ...request } = await porto.provider.request({
3258
+ method: 'wallet_prepareCalls',
3259
+ params: [
3260
+ {
3261
+ calls: [
3262
+ {
3263
+ data: encodeFunctionData({
3264
+ abi: contracts.exp1.abi,
3265
+ args: [alice, 40_000n],
3266
+ functionName: 'transfer',
3267
+ }),
3268
+ to: contracts.exp1.address,
3269
+ },
3270
+ ],
3271
+ key,
3272
+ },
3273
+ ],
3274
+ })
3275
+
3276
+ const signature = Secp256k1.sign({ payload: digest, privateKey })
3277
+
3278
+ const result = await porto.provider.request({
3279
+ method: 'wallet_sendPreparedCalls',
3280
+ params: [
3281
+ {
3282
+ ...request,
3283
+ signature: Signature.toHex(signature),
3284
+ },
3285
+ ],
3286
+ })
3287
+
3288
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
3289
+ id: result[0]!.id,
3290
+ })
3291
+
3292
+ expect(
3293
+ await readContract(client, {
3294
+ abi: contracts.exp1.abi,
3295
+ address: contracts.exp1.address,
3296
+ args: [alice],
3297
+ functionName: 'balanceOf',
3298
+ }),
3299
+ ).toBe(40_000n)
3300
+ })
3301
+ })
3302
+
3303
+ describe('behavior: admin', () => {
3304
+ test('Secp256k1', async () => {
3305
+ const porto = getPorto()
3306
+ const client = TestConfig.getRelayClient(porto)
3307
+ const contracts = await TestConfig.getContracts(porto)
3308
+
3309
+ const alice = Hex.random(20)
3310
+
3311
+ const privateKey = Secp256k1.randomPrivateKey()
3312
+ const publicKey = Secp256k1.getPublicKey({ privateKey })
3313
+ const address = Address.fromPublicKey(publicKey)
3314
+
3315
+ const { accounts } = await porto.provider.request({
3316
+ method: 'wallet_connect',
3317
+ params: [
3318
+ {
3319
+ capabilities: {
3320
+ createAccount: true,
3321
+ },
3322
+ },
3323
+ ],
3324
+ })
3325
+
3326
+ await setBalance(client, {
3327
+ address: accounts[0]?.address!,
3328
+ value: Value.fromEther('10000'),
3329
+ })
3330
+
3331
+ const key = {
3332
+ publicKey: address,
3333
+ type: 'secp256k1',
3334
+ } as const
3335
+
3336
+ await porto.provider.request({
3337
+ method: 'wallet_grantAdmin',
3338
+ params: [
3339
+ {
3340
+ key,
3341
+ },
3342
+ ],
3343
+ })
3344
+
3345
+ const { digest, ...request } = await porto.provider.request({
3346
+ method: 'wallet_prepareCalls',
3347
+ params: [
3348
+ {
3349
+ calls: [
3350
+ {
3351
+ data: encodeFunctionData({
3352
+ abi: contracts.exp1.abi,
3353
+ args: [alice, 40_000n],
3354
+ functionName: 'transfer',
3355
+ }),
3356
+ to: contracts.exp1.address,
3357
+ },
3358
+ ],
3359
+ key,
3360
+ },
3361
+ ],
3362
+ })
3363
+
3364
+ const signature = Secp256k1.sign({ payload: digest, privateKey })
3365
+
3366
+ const result = await porto.provider.request({
3367
+ method: 'wallet_sendPreparedCalls',
3368
+ params: [
3369
+ {
3370
+ ...request,
3371
+ signature: Signature.toHex(signature),
3372
+ },
3373
+ ],
3374
+ })
3375
+
3376
+ await waitForCallsStatus(WalletClient.fromPorto(porto), {
3377
+ id: result[0]!.id,
3378
+ })
3379
+
3380
+ expect(
3381
+ await readContract(client, {
3382
+ abi: contracts.exp1.abi,
3383
+ address: contracts.exp1.address,
3384
+ args: [alice],
3385
+ functionName: 'balanceOf',
3386
+ }),
3387
+ ).toBe(40_000n)
3388
+ })
3389
+ })
3390
+
3391
+ test('behavior: sign typed data', async () => {
3392
+ const porto = getPorto()
3393
+ const client = TestConfig.getRelayClient(porto)
3394
+ const contracts = await TestConfig.getContracts(porto)
3395
+
3396
+ const { accounts } = await porto.provider.request({
3397
+ method: 'wallet_connect',
3398
+ params: [
3399
+ {
3400
+ capabilities: {
3401
+ createAccount: true,
3402
+ },
3403
+ },
3404
+ ],
3405
+ })
3406
+
3407
+ const walletClient = WalletClient.fromPorto(porto, {
3408
+ account: accounts[0]!.address,
3409
+ })
3410
+
3411
+ await setBalance(client, {
3412
+ address: accounts[0]?.address!,
3413
+ value: Value.fromEther('10000'),
3414
+ })
3415
+
3416
+ const alice = Hex.random(20)
3417
+
3418
+ const { typedData, ...request } = await porto.provider.request({
3419
+ method: 'wallet_prepareCalls',
3420
+ params: [
3421
+ {
3422
+ calls: [
3423
+ {
3424
+ data: encodeFunctionData({
3425
+ abi: contracts.exp1.abi,
3426
+ args: [alice, 40_000n],
3427
+ functionName: 'transfer',
3428
+ }),
3429
+ to: contracts.exp1.address,
3430
+ },
3431
+ ],
3432
+ },
3433
+ ],
3434
+ })
3435
+
3436
+ const signature = await signTypedData(walletClient, typedData as never)
3437
+
3438
+ const result = await porto.provider.request({
3439
+ method: 'wallet_sendPreparedCalls',
3440
+ params: [
3441
+ {
3442
+ ...request,
3443
+ signature,
3444
+ },
3445
+ ],
3446
+ })
3447
+
3448
+ await waitForCallsStatus(walletClient, {
3449
+ id: result[0]!.id,
3450
+ })
3451
+
3452
+ expect(
3453
+ await readContract(client, {
3454
+ abi: contracts.exp1.abi,
3455
+ address: contracts.exp1.address,
3456
+ args: [alice],
3457
+ functionName: 'balanceOf',
3458
+ }),
3459
+ ).toBe(40_000n)
3460
+ })
3461
+ })
3462
+
3463
+ test('behavior: fall through', async () => {
3464
+ const porto = getPorto()
3465
+ expect(
3466
+ await porto.provider.request({
3467
+ method: 'eth_blockNumber',
3468
+ }),
3469
+ ).toBeDefined()
3470
+ })
3471
+
3472
+ test('behavior: unsupported wallet_ method', async () => {
3473
+ const porto = getPorto()
3474
+ await expect(() =>
3475
+ porto.provider.request({
3476
+ method: 'wallet_lol',
3477
+ }),
3478
+ ).rejects.toThrowError(
3479
+ 'The provider does not support the requested method.',
3480
+ )
3481
+ })
3482
+
3483
+ test('behavior: invalid params', async () => {
3484
+ const porto = getPorto()
3485
+ await porto.provider.request({
3486
+ method: 'wallet_connect',
3487
+ params: [{ capabilities: { createAccount: true } }],
3488
+ })
3489
+ await expect(() =>
3490
+ porto.provider.request({
3491
+ method: 'eth_sendTransaction',
3492
+ // @ts-expect-error
3493
+ params: [{ to: 1 }],
3494
+ }),
3495
+ ).rejects.matchSnapshot()
3496
+ })
3497
+ })
3498
+
3499
+ const typedData = {
3500
+ domain: {
3501
+ chainId: 1,
3502
+ name: 'Ether Mail 🥵',
3503
+ verifyingContract: '0x0000000000000000000000000000000000000000',
3504
+ version: '1.1.1',
3505
+ },
3506
+ message: {
3507
+ contents: 'Hello, Bob! 🖤',
3508
+ from: {
3509
+ age: 69,
3510
+ favoriteColors: ['red', 'green', 'blue'],
3511
+ foo: 123123123123123123n,
3512
+ isCool: false,
3513
+ name: {
3514
+ first: 'Cow',
3515
+ last: 'Burns',
3516
+ },
3517
+ wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
3518
+ },
3519
+ hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
3520
+ timestamp: 1234567890n,
3521
+ to: {
3522
+ age: 70,
3523
+ favoriteColors: ['orange', 'yellow', 'green'],
3524
+ foo: 123123123123123123n,
3525
+ isCool: true,
3526
+ name: { first: 'Bob', last: 'Builder' },
3527
+ wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
3528
+ },
3529
+ },
3530
+ primaryType: 'Mail',
3531
+ types: {
3532
+ Mail: [
3533
+ { name: 'timestamp', type: 'uint256' },
3534
+ { name: 'from', type: 'Person' },
3535
+ { name: 'to', type: 'Person' },
3536
+ { name: 'contents', type: 'string' },
3537
+ { name: 'hash', type: 'bytes' },
3538
+ ],
3539
+ Name: [
3540
+ { name: 'first', type: 'string' },
3541
+ { name: 'last', type: 'string' },
3542
+ ],
3543
+ Person: [
3544
+ { name: 'name', type: 'Name' },
3545
+ { name: 'wallet', type: 'address' },
3546
+ { name: 'favoriteColors', type: 'string[3]' },
3547
+ { name: 'foo', type: 'uint256' },
3548
+ { name: 'age', type: 'uint8' },
3549
+ { name: 'isCool', type: 'bool' },
3550
+ ],
3551
+ },
3552
+ } as const