@multiplatform.one/web3 7.23.1 → 7.24.0

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 (431) hide show
  1. package/README.md +150 -11
  2. package/dist/cjs/clients/evm.cjs +299 -11
  3. package/dist/cjs/clients/evm.native.js +500 -12
  4. package/dist/cjs/clients/evm.native.js.map +1 -1
  5. package/dist/cjs/clients/index.cjs +5 -0
  6. package/dist/cjs/clients/index.native.js +5 -0
  7. package/dist/cjs/clients/index.native.js.map +1 -1
  8. package/dist/cjs/clients/solana.cjs +39 -21
  9. package/dist/cjs/clients/solana.native.js +48 -23
  10. package/dist/cjs/clients/solana.native.js.map +1 -1
  11. package/dist/cjs/connectkit/GpgProvider.cjs +44 -0
  12. package/dist/cjs/connectkit/GpgProvider.native.js +51 -0
  13. package/dist/cjs/connectkit/GpgProvider.native.js.map +1 -0
  14. package/dist/cjs/connectkit/adapters/BitcoinAdapter.cjs +5 -14
  15. package/dist/cjs/connectkit/adapters/BitcoinAdapter.native.js +5 -15
  16. package/dist/cjs/connectkit/adapters/BitcoinAdapter.native.js.map +1 -1
  17. package/dist/cjs/connectkit/adapters/EthereumAdapter.cjs +6 -15
  18. package/dist/cjs/connectkit/adapters/EthereumAdapter.native.js +7 -16
  19. package/dist/cjs/connectkit/adapters/EthereumAdapter.native.js.map +1 -1
  20. package/dist/cjs/connectkit/adapters/SolanaAdapter.cjs +5 -14
  21. package/dist/cjs/connectkit/adapters/SolanaAdapter.native.js +5 -15
  22. package/dist/cjs/connectkit/adapters/SolanaAdapter.native.js.map +1 -1
  23. package/dist/cjs/connectkit/adapters/SuiAdapter.cjs +5 -14
  24. package/dist/cjs/connectkit/adapters/SuiAdapter.native.js +5 -15
  25. package/dist/cjs/connectkit/adapters/SuiAdapter.native.js.map +1 -1
  26. package/dist/cjs/connectkit/connectors/createWalletMessage.cjs +2 -2
  27. package/dist/cjs/connectkit/connectors/createWalletMessage.native.js +2 -2
  28. package/dist/cjs/connectkit/connectors/createWalletMessage.native.js.map +1 -1
  29. package/dist/cjs/connectkit/index.cjs +4 -3
  30. package/dist/cjs/connectkit/index.native.js +4 -3
  31. package/dist/cjs/connectkit/index.native.js.map +1 -1
  32. package/dist/cjs/connectkit/siwe/SIWEContext.native.js.map +1 -1
  33. package/dist/cjs/connectkit/siwe/SIWEProvider.cjs +18 -3
  34. package/dist/cjs/connectkit/siwe/SIWEProvider.native.js +18 -3
  35. package/dist/cjs/connectkit/siwe/SIWEProvider.native.js.map +1 -1
  36. package/dist/cjs/index.cjs +1 -0
  37. package/dist/cjs/index.native.js +1 -0
  38. package/dist/cjs/index.native.js.map +1 -1
  39. package/dist/cjs/keycloak/KeycloakWalletLogin.cjs +255 -0
  40. package/dist/cjs/keycloak/KeycloakWalletLogin.native.js +33 -0
  41. package/dist/cjs/keycloak/KeycloakWalletLogin.native.js.map +1 -0
  42. package/dist/cjs/keycloak/browserFlow.cjs +83 -0
  43. package/dist/cjs/keycloak/browserFlow.native.js +90 -0
  44. package/dist/cjs/keycloak/browserFlow.native.js.map +1 -0
  45. package/dist/cjs/keycloak/device.cjs +36 -0
  46. package/dist/cjs/keycloak/device.native.js +45 -0
  47. package/dist/cjs/keycloak/device.native.js.map +1 -0
  48. package/dist/cjs/keycloak/directGrant.cjs +189 -0
  49. package/dist/cjs/keycloak/directGrant.native.js +233 -0
  50. package/dist/cjs/keycloak/directGrant.native.js.map +1 -0
  51. package/dist/cjs/keycloak/iife.cjs +4 -0
  52. package/dist/cjs/keycloak/iife.native.js +7 -0
  53. package/dist/cjs/keycloak/iife.native.js.map +1 -0
  54. package/dist/cjs/keycloak/index.cjs +53 -0
  55. package/dist/cjs/keycloak/index.native.js +56 -0
  56. package/dist/cjs/keycloak/index.native.js.map +1 -0
  57. package/dist/cjs/keycloak/keycloakWallet.cjs +214 -0
  58. package/dist/cjs/keycloak/keycloakWallet.native.js +285 -0
  59. package/dist/cjs/keycloak/keycloakWallet.native.js.map +1 -0
  60. package/dist/cjs/keycloak/mount.cjs +53 -0
  61. package/dist/cjs/keycloak/mount.native.js +33 -0
  62. package/dist/cjs/keycloak/mount.native.js.map +1 -0
  63. package/dist/cjs/keycloak/registerWallet.cjs +74 -0
  64. package/dist/cjs/keycloak/registerWallet.native.js +81 -0
  65. package/dist/cjs/keycloak/registerWallet.native.js.map +1 -0
  66. package/dist/cjs/keycloak/types.cjs +46 -0
  67. package/dist/cjs/keycloak/types.native.js +179 -0
  68. package/dist/cjs/keycloak/types.native.js.map +1 -0
  69. package/dist/cjs/keycloak/useDirectLogin.cjs +57 -0
  70. package/dist/cjs/keycloak/useDirectLogin.native.js +77 -0
  71. package/dist/cjs/keycloak/useDirectLogin.native.js.map +1 -0
  72. package/dist/cjs/keycloak/useWalletLogin.cjs +97 -0
  73. package/dist/cjs/keycloak/useWalletLogin.native.js +33 -0
  74. package/dist/cjs/keycloak/useWalletLogin.native.js.map +1 -0
  75. package/dist/cjs/message/buildWalletMessage.cjs +113 -0
  76. package/dist/cjs/message/buildWalletMessage.native.js +121 -0
  77. package/dist/cjs/message/buildWalletMessage.native.js.map +1 -0
  78. package/dist/cjs/message/index.cjs +29 -0
  79. package/dist/cjs/message/index.native.js +32 -0
  80. package/dist/cjs/message/index.native.js.map +1 -0
  81. package/dist/cjs/providers/WalletProvider.cjs +8 -2
  82. package/dist/cjs/siws/message.cjs +5 -16
  83. package/dist/cjs/siws/message.native.js +6 -16
  84. package/dist/cjs/siws/message.native.js.map +1 -1
  85. package/dist/cjs/solana.native.js.map +1 -1
  86. package/dist/esm/clients/evm.mjs +295 -12
  87. package/dist/esm/clients/evm.mjs.map +1 -1
  88. package/dist/esm/clients/evm.native.js +496 -13
  89. package/dist/esm/clients/evm.native.js.map +1 -1
  90. package/dist/esm/clients/index.mjs +2 -2
  91. package/dist/esm/clients/index.mjs.map +1 -1
  92. package/dist/esm/clients/index.native.js +2 -2
  93. package/dist/esm/clients/index.native.js.map +1 -1
  94. package/dist/esm/clients/solana.mjs +39 -21
  95. package/dist/esm/clients/solana.mjs.map +1 -1
  96. package/dist/esm/clients/solana.native.js +48 -23
  97. package/dist/esm/clients/solana.native.js.map +1 -1
  98. package/dist/esm/connectkit/GpgProvider.mjs +19 -0
  99. package/dist/esm/connectkit/GpgProvider.mjs.map +1 -0
  100. package/dist/esm/connectkit/GpgProvider.native.js +23 -0
  101. package/dist/esm/connectkit/GpgProvider.native.js.map +1 -0
  102. package/dist/esm/connectkit/adapters/BitcoinAdapter.mjs +5 -14
  103. package/dist/esm/connectkit/adapters/BitcoinAdapter.mjs.map +1 -1
  104. package/dist/esm/connectkit/adapters/BitcoinAdapter.native.js +5 -15
  105. package/dist/esm/connectkit/adapters/BitcoinAdapter.native.js.map +1 -1
  106. package/dist/esm/connectkit/adapters/EthereumAdapter.mjs +6 -15
  107. package/dist/esm/connectkit/adapters/EthereumAdapter.mjs.map +1 -1
  108. package/dist/esm/connectkit/adapters/EthereumAdapter.native.js +7 -16
  109. package/dist/esm/connectkit/adapters/EthereumAdapter.native.js.map +1 -1
  110. package/dist/esm/connectkit/adapters/SolanaAdapter.mjs +5 -14
  111. package/dist/esm/connectkit/adapters/SolanaAdapter.mjs.map +1 -1
  112. package/dist/esm/connectkit/adapters/SolanaAdapter.native.js +5 -15
  113. package/dist/esm/connectkit/adapters/SolanaAdapter.native.js.map +1 -1
  114. package/dist/esm/connectkit/adapters/SuiAdapter.mjs +5 -14
  115. package/dist/esm/connectkit/adapters/SuiAdapter.mjs.map +1 -1
  116. package/dist/esm/connectkit/adapters/SuiAdapter.native.js +5 -15
  117. package/dist/esm/connectkit/adapters/SuiAdapter.native.js.map +1 -1
  118. package/dist/esm/connectkit/connectors/createWalletMessage.mjs +1 -1
  119. package/dist/esm/connectkit/connectors/createWalletMessage.native.js +1 -1
  120. package/dist/esm/connectkit/index.mjs +3 -2
  121. package/dist/esm/connectkit/index.mjs.map +1 -1
  122. package/dist/esm/connectkit/index.native.js +3 -2
  123. package/dist/esm/connectkit/index.native.js.map +1 -1
  124. package/dist/esm/connectkit/siwe/SIWEContext.mjs.map +1 -1
  125. package/dist/esm/connectkit/siwe/SIWEContext.native.js.map +1 -1
  126. package/dist/esm/connectkit/siwe/SIWEProvider.mjs +19 -4
  127. package/dist/esm/connectkit/siwe/SIWEProvider.mjs.map +1 -1
  128. package/dist/esm/connectkit/siwe/SIWEProvider.native.js +19 -4
  129. package/dist/esm/connectkit/siwe/SIWEProvider.native.js.map +1 -1
  130. package/dist/esm/index.mjs +1 -0
  131. package/dist/esm/index.mjs.map +1 -1
  132. package/dist/esm/index.native.js +1 -0
  133. package/dist/esm/index.native.js.map +1 -1
  134. package/dist/esm/keycloak/KeycloakWalletLogin.mjs +218 -0
  135. package/dist/esm/keycloak/KeycloakWalletLogin.mjs.map +1 -0
  136. package/dist/esm/keycloak/KeycloakWalletLogin.native.js +5 -0
  137. package/dist/esm/keycloak/KeycloakWalletLogin.native.js.map +1 -0
  138. package/dist/esm/keycloak/browserFlow.mjs +58 -0
  139. package/dist/esm/keycloak/browserFlow.mjs.map +1 -0
  140. package/dist/esm/keycloak/browserFlow.native.js +62 -0
  141. package/dist/esm/keycloak/browserFlow.native.js.map +1 -0
  142. package/dist/esm/keycloak/device.mjs +10 -0
  143. package/dist/esm/keycloak/device.mjs.map +1 -0
  144. package/dist/esm/keycloak/device.native.js +16 -0
  145. package/dist/esm/keycloak/device.native.js.map +1 -0
  146. package/dist/esm/keycloak/directGrant.mjs +164 -0
  147. package/dist/esm/keycloak/directGrant.mjs.map +1 -0
  148. package/dist/esm/keycloak/directGrant.native.js +205 -0
  149. package/dist/esm/keycloak/directGrant.native.js.map +1 -0
  150. package/dist/esm/keycloak/iife.mjs +5 -0
  151. package/dist/esm/keycloak/iife.mjs.map +1 -0
  152. package/dist/esm/keycloak/iife.native.js +5 -0
  153. package/dist/esm/keycloak/iife.native.js.map +1 -0
  154. package/dist/esm/keycloak/index.mjs +13 -0
  155. package/dist/esm/keycloak/index.mjs.map +1 -0
  156. package/dist/esm/keycloak/index.native.js +13 -0
  157. package/dist/esm/keycloak/index.native.js.map +1 -0
  158. package/dist/esm/keycloak/keycloakWallet.mjs +186 -0
  159. package/dist/esm/keycloak/keycloakWallet.mjs.map +1 -0
  160. package/dist/esm/keycloak/keycloakWallet.native.js +254 -0
  161. package/dist/esm/keycloak/keycloakWallet.native.js.map +1 -0
  162. package/dist/esm/keycloak/mount.mjs +28 -0
  163. package/dist/esm/keycloak/mount.mjs.map +1 -0
  164. package/dist/esm/keycloak/mount.native.js +5 -0
  165. package/dist/esm/keycloak/mount.native.js.map +1 -0
  166. package/dist/esm/keycloak/registerWallet.mjs +49 -0
  167. package/dist/esm/keycloak/registerWallet.mjs.map +1 -0
  168. package/dist/esm/keycloak/registerWallet.native.js +53 -0
  169. package/dist/esm/keycloak/registerWallet.native.js.map +1 -0
  170. package/dist/esm/keycloak/types.mjs +20 -0
  171. package/dist/esm/keycloak/types.mjs.map +1 -0
  172. package/dist/esm/keycloak/types.native.js +150 -0
  173. package/dist/esm/keycloak/types.native.js.map +1 -0
  174. package/dist/esm/keycloak/useDirectLogin.mjs +32 -0
  175. package/dist/esm/keycloak/useDirectLogin.mjs.map +1 -0
  176. package/dist/esm/keycloak/useDirectLogin.native.js +49 -0
  177. package/dist/esm/keycloak/useDirectLogin.native.js.map +1 -0
  178. package/dist/esm/keycloak/useWalletLogin.mjs +72 -0
  179. package/dist/esm/keycloak/useWalletLogin.mjs.map +1 -0
  180. package/dist/esm/keycloak/useWalletLogin.native.js +5 -0
  181. package/dist/esm/keycloak/useWalletLogin.native.js.map +1 -0
  182. package/dist/esm/message/buildWalletMessage.mjs +87 -0
  183. package/dist/esm/message/buildWalletMessage.mjs.map +1 -0
  184. package/dist/esm/message/buildWalletMessage.native.js +92 -0
  185. package/dist/esm/message/buildWalletMessage.native.js.map +1 -0
  186. package/dist/esm/message/index.mjs +3 -0
  187. package/dist/esm/message/index.mjs.map +1 -0
  188. package/dist/esm/message/index.native.js +3 -0
  189. package/dist/esm/message/index.native.js.map +1 -0
  190. package/dist/esm/providers/WalletProvider.mjs +9 -3
  191. package/dist/esm/providers/WalletProvider.mjs.map +1 -1
  192. package/dist/esm/siws/message.mjs +5 -16
  193. package/dist/esm/siws/message.mjs.map +1 -1
  194. package/dist/esm/siws/message.native.js +6 -16
  195. package/dist/esm/siws/message.native.js.map +1 -1
  196. package/dist/esm/solana.mjs.map +1 -1
  197. package/dist/esm/solana.native.js.map +1 -1
  198. package/dist/jsx/clients/evm.mjs +295 -12
  199. package/dist/jsx/clients/evm.mjs.map +1 -1
  200. package/dist/jsx/clients/evm.native.js +500 -12
  201. package/dist/jsx/clients/evm.native.js.map +1 -1
  202. package/dist/jsx/clients/index.mjs +2 -2
  203. package/dist/jsx/clients/index.mjs.map +1 -1
  204. package/dist/jsx/clients/index.native.js +5 -0
  205. package/dist/jsx/clients/index.native.js.map +1 -1
  206. package/dist/jsx/clients/solana.mjs +39 -21
  207. package/dist/jsx/clients/solana.mjs.map +1 -1
  208. package/dist/jsx/clients/solana.native.js +48 -23
  209. package/dist/jsx/clients/solana.native.js.map +1 -1
  210. package/dist/jsx/connectkit/GpgProvider.mjs +19 -0
  211. package/dist/jsx/connectkit/GpgProvider.mjs.map +1 -0
  212. package/dist/jsx/connectkit/GpgProvider.native.js +51 -0
  213. package/dist/jsx/connectkit/GpgProvider.native.js.map +1 -0
  214. package/dist/jsx/connectkit/adapters/BitcoinAdapter.mjs +5 -14
  215. package/dist/jsx/connectkit/adapters/BitcoinAdapter.mjs.map +1 -1
  216. package/dist/jsx/connectkit/adapters/BitcoinAdapter.native.js +5 -15
  217. package/dist/jsx/connectkit/adapters/BitcoinAdapter.native.js.map +1 -1
  218. package/dist/jsx/connectkit/adapters/EthereumAdapter.mjs +6 -15
  219. package/dist/jsx/connectkit/adapters/EthereumAdapter.mjs.map +1 -1
  220. package/dist/jsx/connectkit/adapters/EthereumAdapter.native.js +7 -16
  221. package/dist/jsx/connectkit/adapters/EthereumAdapter.native.js.map +1 -1
  222. package/dist/jsx/connectkit/adapters/SolanaAdapter.mjs +5 -14
  223. package/dist/jsx/connectkit/adapters/SolanaAdapter.mjs.map +1 -1
  224. package/dist/jsx/connectkit/adapters/SolanaAdapter.native.js +5 -15
  225. package/dist/jsx/connectkit/adapters/SolanaAdapter.native.js.map +1 -1
  226. package/dist/jsx/connectkit/adapters/SuiAdapter.mjs +5 -14
  227. package/dist/jsx/connectkit/adapters/SuiAdapter.mjs.map +1 -1
  228. package/dist/jsx/connectkit/adapters/SuiAdapter.native.js +5 -15
  229. package/dist/jsx/connectkit/adapters/SuiAdapter.native.js.map +1 -1
  230. package/dist/jsx/connectkit/connectors/createWalletMessage.mjs +1 -1
  231. package/dist/jsx/connectkit/connectors/createWalletMessage.native.js +2 -2
  232. package/dist/jsx/connectkit/index.mjs +3 -2
  233. package/dist/jsx/connectkit/index.mjs.map +1 -1
  234. package/dist/jsx/connectkit/index.native.js +4 -3
  235. package/dist/jsx/connectkit/index.native.js.map +1 -1
  236. package/dist/jsx/connectkit/siwe/SIWEContext.mjs.map +1 -1
  237. package/dist/jsx/connectkit/siwe/SIWEContext.native.js.map +1 -1
  238. package/dist/jsx/connectkit/siwe/SIWEProvider.mjs +19 -4
  239. package/dist/jsx/connectkit/siwe/SIWEProvider.mjs.map +1 -1
  240. package/dist/jsx/connectkit/siwe/SIWEProvider.native.js +18 -3
  241. package/dist/jsx/connectkit/siwe/SIWEProvider.native.js.map +1 -1
  242. package/dist/jsx/index.js +1 -0
  243. package/dist/jsx/index.js.map +1 -1
  244. package/dist/jsx/index.mjs +1 -0
  245. package/dist/jsx/index.mjs.map +1 -1
  246. package/dist/jsx/index.native.js +1 -0
  247. package/dist/jsx/index.native.js.map +1 -1
  248. package/dist/jsx/keycloak/KeycloakWalletLogin.mjs +218 -0
  249. package/dist/jsx/keycloak/KeycloakWalletLogin.mjs.map +1 -0
  250. package/dist/jsx/keycloak/KeycloakWalletLogin.native.js +33 -0
  251. package/dist/jsx/keycloak/KeycloakWalletLogin.native.js.map +1 -0
  252. package/dist/jsx/keycloak/browserFlow.mjs +58 -0
  253. package/dist/jsx/keycloak/browserFlow.mjs.map +1 -0
  254. package/dist/jsx/keycloak/browserFlow.native.js +90 -0
  255. package/dist/jsx/keycloak/browserFlow.native.js.map +1 -0
  256. package/dist/jsx/keycloak/device.mjs +10 -0
  257. package/dist/jsx/keycloak/device.mjs.map +1 -0
  258. package/dist/jsx/keycloak/device.native.js +45 -0
  259. package/dist/jsx/keycloak/device.native.js.map +1 -0
  260. package/dist/jsx/keycloak/directGrant.mjs +164 -0
  261. package/dist/jsx/keycloak/directGrant.mjs.map +1 -0
  262. package/dist/jsx/keycloak/directGrant.native.js +233 -0
  263. package/dist/jsx/keycloak/directGrant.native.js.map +1 -0
  264. package/dist/jsx/keycloak/iife.mjs +5 -0
  265. package/dist/jsx/keycloak/iife.mjs.map +1 -0
  266. package/dist/jsx/keycloak/iife.native.js +7 -0
  267. package/dist/jsx/keycloak/iife.native.js.map +1 -0
  268. package/dist/jsx/keycloak/index.mjs +13 -0
  269. package/dist/jsx/keycloak/index.mjs.map +1 -0
  270. package/dist/jsx/keycloak/index.native.js +56 -0
  271. package/dist/jsx/keycloak/index.native.js.map +1 -0
  272. package/dist/jsx/keycloak/keycloakWallet.mjs +186 -0
  273. package/dist/jsx/keycloak/keycloakWallet.mjs.map +1 -0
  274. package/dist/jsx/keycloak/keycloakWallet.native.js +285 -0
  275. package/dist/jsx/keycloak/keycloakWallet.native.js.map +1 -0
  276. package/dist/jsx/keycloak/mount.mjs +28 -0
  277. package/dist/jsx/keycloak/mount.mjs.map +1 -0
  278. package/dist/jsx/keycloak/mount.native.js +33 -0
  279. package/dist/jsx/keycloak/mount.native.js.map +1 -0
  280. package/dist/jsx/keycloak/registerWallet.mjs +49 -0
  281. package/dist/jsx/keycloak/registerWallet.mjs.map +1 -0
  282. package/dist/jsx/keycloak/registerWallet.native.js +81 -0
  283. package/dist/jsx/keycloak/registerWallet.native.js.map +1 -0
  284. package/dist/jsx/keycloak/types.mjs +20 -0
  285. package/dist/jsx/keycloak/types.mjs.map +1 -0
  286. package/dist/jsx/keycloak/types.native.js +179 -0
  287. package/dist/jsx/keycloak/types.native.js.map +1 -0
  288. package/dist/jsx/keycloak/useDirectLogin.mjs +32 -0
  289. package/dist/jsx/keycloak/useDirectLogin.mjs.map +1 -0
  290. package/dist/jsx/keycloak/useDirectLogin.native.js +77 -0
  291. package/dist/jsx/keycloak/useDirectLogin.native.js.map +1 -0
  292. package/dist/jsx/keycloak/useWalletLogin.mjs +72 -0
  293. package/dist/jsx/keycloak/useWalletLogin.mjs.map +1 -0
  294. package/dist/jsx/keycloak/useWalletLogin.native.js +33 -0
  295. package/dist/jsx/keycloak/useWalletLogin.native.js.map +1 -0
  296. package/dist/jsx/message/buildWalletMessage.mjs +87 -0
  297. package/dist/jsx/message/buildWalletMessage.mjs.map +1 -0
  298. package/dist/jsx/message/buildWalletMessage.native.js +121 -0
  299. package/dist/jsx/message/buildWalletMessage.native.js.map +1 -0
  300. package/dist/jsx/message/index.mjs +3 -0
  301. package/dist/jsx/message/index.mjs.map +1 -0
  302. package/dist/jsx/message/index.native.js +32 -0
  303. package/dist/jsx/message/index.native.js.map +1 -0
  304. package/dist/jsx/providers/WalletProvider.mjs +9 -3
  305. package/dist/jsx/providers/WalletProvider.mjs.map +1 -1
  306. package/dist/jsx/siws/message.mjs +5 -16
  307. package/dist/jsx/siws/message.mjs.map +1 -1
  308. package/dist/jsx/siws/message.native.js +6 -16
  309. package/dist/jsx/siws/message.native.js.map +1 -1
  310. package/dist/jsx/solana.mjs.map +1 -1
  311. package/dist/jsx/solana.native.js.map +1 -1
  312. package/dist/keycloak/login.iife.js +3604 -0
  313. package/package.json +27 -8
  314. package/src/clients/evm.spec.ts +644 -10
  315. package/src/clients/evm.ts +498 -10
  316. package/src/clients/index.ts +8 -0
  317. package/src/clients/solana.spec.ts +116 -0
  318. package/src/clients/solana.ts +51 -31
  319. package/src/connectkit/GpgProvider.tsx +16 -0
  320. package/src/connectkit/adapters/BitcoinAdapter.ts +5 -16
  321. package/src/connectkit/adapters/EthereumAdapter.ts +6 -17
  322. package/src/connectkit/adapters/SolanaAdapter.ts +5 -16
  323. package/src/connectkit/adapters/SuiAdapter.ts +5 -16
  324. package/src/connectkit/connectors/createWalletMessage.ts +1 -1
  325. package/src/connectkit/index.ts +2 -6
  326. package/src/connectkit/openConnector/modal.spec.tsx +1 -1
  327. package/src/connectkit/siwe/SIWEContext.tsx +6 -2
  328. package/src/connectkit/siwe/SIWEProvider.tsx +22 -5
  329. package/src/index.ts +3 -0
  330. package/src/keycloak/KeycloakWalletLogin.native.tsx +7 -0
  331. package/src/keycloak/KeycloakWalletLogin.spec.tsx +168 -0
  332. package/src/keycloak/KeycloakWalletLogin.tsx +251 -0
  333. package/src/keycloak/browserFlow.spec.ts +108 -0
  334. package/src/keycloak/browserFlow.ts +84 -0
  335. package/src/keycloak/device.ts +17 -0
  336. package/src/keycloak/directGrant.spec.ts +331 -0
  337. package/src/keycloak/directGrant.ts +214 -0
  338. package/src/keycloak/iife.ts +3 -0
  339. package/src/keycloak/index.ts +44 -0
  340. package/src/keycloak/keycloakWallet.spec.ts +216 -0
  341. package/src/keycloak/keycloakWallet.ts +275 -0
  342. package/src/keycloak/mount.native.ts +11 -0
  343. package/src/keycloak/mount.tsx +45 -0
  344. package/src/keycloak/nonceReset.spec.tsx +205 -0
  345. package/src/keycloak/registerWallet.spec.ts +88 -0
  346. package/src/keycloak/registerWallet.ts +59 -0
  347. package/src/keycloak/types.ts +66 -0
  348. package/src/keycloak/useDirectLogin.spec.tsx +112 -0
  349. package/src/keycloak/useDirectLogin.ts +74 -0
  350. package/src/keycloak/useWalletLogin.native.ts +7 -0
  351. package/src/keycloak/useWalletLogin.ts +99 -0
  352. package/src/message/buildWalletMessage.spec.ts +291 -0
  353. package/src/message/buildWalletMessage.ts +150 -0
  354. package/src/message/index.ts +8 -0
  355. package/src/providers/WalletProvider.tsx +15 -2
  356. package/src/siws/message.ts +3 -22
  357. package/src/solana.ts +1 -0
  358. package/types/clients/evm.d.ts +144 -2
  359. package/types/clients/evm.d.ts.map +1 -1
  360. package/types/clients/index.d.ts +1 -1
  361. package/types/clients/index.d.ts.map +1 -1
  362. package/types/clients/solana.d.ts +14 -5
  363. package/types/clients/solana.d.ts.map +1 -1
  364. package/types/connectkit/GpgProvider.d.ts +10 -0
  365. package/types/connectkit/GpgProvider.d.ts.map +1 -0
  366. package/types/connectkit/adapters/BitcoinAdapter.d.ts.map +1 -1
  367. package/types/connectkit/adapters/EthereumAdapter.d.ts.map +1 -1
  368. package/types/connectkit/adapters/SolanaAdapter.d.ts.map +1 -1
  369. package/types/connectkit/adapters/SuiAdapter.d.ts.map +1 -1
  370. package/types/connectkit/connectors/createWalletMessage.d.ts +1 -1
  371. package/types/connectkit/connectors/createWalletMessage.d.ts.map +1 -1
  372. package/types/connectkit/index.d.ts +3 -2
  373. package/types/connectkit/index.d.ts.map +1 -1
  374. package/types/connectkit/siwe/SIWEContext.d.ts +2 -1
  375. package/types/connectkit/siwe/SIWEContext.d.ts.map +1 -1
  376. package/types/connectkit/siwe/SIWEProvider.d.ts.map +1 -1
  377. package/types/index.d.ts +1 -0
  378. package/types/index.d.ts.map +1 -1
  379. package/types/keycloak/KeycloakWalletLogin.d.ts +45 -0
  380. package/types/keycloak/KeycloakWalletLogin.d.ts.map +1 -0
  381. package/types/keycloak/KeycloakWalletLogin.native.d.ts +4 -0
  382. package/types/keycloak/KeycloakWalletLogin.native.d.ts.map +1 -0
  383. package/types/keycloak/browserFlow.d.ts +27 -0
  384. package/types/keycloak/browserFlow.d.ts.map +1 -0
  385. package/types/keycloak/device.d.ts +14 -0
  386. package/types/keycloak/device.d.ts.map +1 -0
  387. package/types/keycloak/directGrant.d.ts +43 -0
  388. package/types/keycloak/directGrant.d.ts.map +1 -0
  389. package/types/keycloak/iife.d.ts +2 -0
  390. package/types/keycloak/iife.d.ts.map +1 -0
  391. package/types/keycloak/index.d.ts +12 -0
  392. package/types/keycloak/index.d.ts.map +1 -0
  393. package/types/keycloak/keycloakWallet.d.ts +120 -0
  394. package/types/keycloak/keycloakWallet.d.ts.map +1 -0
  395. package/types/keycloak/mount.d.ts +16 -0
  396. package/types/keycloak/mount.d.ts.map +1 -0
  397. package/types/keycloak/mount.native.d.ts +5 -0
  398. package/types/keycloak/mount.native.d.ts.map +1 -0
  399. package/types/keycloak/registerWallet.d.ts +22 -0
  400. package/types/keycloak/registerWallet.d.ts.map +1 -0
  401. package/types/keycloak/types.d.ts +50 -0
  402. package/types/keycloak/types.d.ts.map +1 -0
  403. package/types/keycloak/useDirectLogin.d.ts +29 -0
  404. package/types/keycloak/useDirectLogin.d.ts.map +1 -0
  405. package/types/keycloak/useWalletLogin.d.ts +26 -0
  406. package/types/keycloak/useWalletLogin.d.ts.map +1 -0
  407. package/types/keycloak/useWalletLogin.native.d.ts +4 -0
  408. package/types/keycloak/useWalletLogin.native.d.ts.map +1 -0
  409. package/types/message/buildWalletMessage.d.ts +46 -0
  410. package/types/message/buildWalletMessage.d.ts.map +1 -0
  411. package/types/message/index.d.ts +2 -0
  412. package/types/message/index.d.ts.map +1 -0
  413. package/types/providers/WalletProvider.d.ts +8 -1
  414. package/types/providers/WalletProvider.d.ts.map +1 -1
  415. package/types/siws/message.d.ts.map +1 -1
  416. package/types/solana.d.ts +1 -1
  417. package/types/solana.d.ts.map +1 -1
  418. package/dist/cjs/connectkit/adapters/messages.cjs +0 -73
  419. package/dist/cjs/connectkit/adapters/messages.native.js +0 -79
  420. package/dist/cjs/connectkit/adapters/messages.native.js.map +0 -1
  421. package/dist/esm/connectkit/adapters/messages.mjs +0 -48
  422. package/dist/esm/connectkit/adapters/messages.mjs.map +0 -1
  423. package/dist/esm/connectkit/adapters/messages.native.js +0 -51
  424. package/dist/esm/connectkit/adapters/messages.native.js.map +0 -1
  425. package/dist/jsx/connectkit/adapters/messages.mjs +0 -48
  426. package/dist/jsx/connectkit/adapters/messages.mjs.map +0 -1
  427. package/dist/jsx/connectkit/adapters/messages.native.js +0 -79
  428. package/dist/jsx/connectkit/adapters/messages.native.js.map +0 -1
  429. package/src/connectkit/adapters/messages.ts +0 -84
  430. package/types/connectkit/adapters/messages.d.ts +0 -16
  431. package/types/connectkit/adapters/messages.d.ts.map +0 -1
@@ -0,0 +1,99 @@
1
+ import { useModal } from "@multiplatform.one/connectkit";
2
+ import { useCallback, useContext, useEffect, useRef } from "react";
3
+ import { useAccount } from "wagmi";
4
+ import { useConnectorLauncher } from "../connectkit/openConnector";
5
+ import { SIWEContext, StatusState } from "../connectkit/siwe/SIWEContext";
6
+ import { hasUserActivation, isMobileBrowser } from "./device";
7
+
8
+ export interface UseWalletLoginOptions {
9
+ /** sessionStorage key of the pending-login mark. One per button on a page. */
10
+ intentKey?: string;
11
+ /** How long a connect started by `login()` may still drive the signature. Default 90 s. */
12
+ intentTtlMs?: number;
13
+ }
14
+
15
+ export interface UseWalletLoginResult {
16
+ /** Connect if needed, then sign through SIWEProvider. One press, no Continue step. */
17
+ login(): Promise<void>;
18
+ status: StatusState;
19
+ isConnected: boolean;
20
+ address?: string;
21
+ }
22
+
23
+ function readIntent(key: string, ttl: number): boolean {
24
+ try {
25
+ const raw = globalThis.sessionStorage?.getItem(key);
26
+ if (raw === null || raw === undefined) return false;
27
+ globalThis.sessionStorage.removeItem(key);
28
+ const at = Number(raw);
29
+ return Number.isFinite(at) && Date.now() - at < ttl;
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
34
+
35
+ function writeIntent(key: string, value: string | null) {
36
+ try {
37
+ if (value === null) globalThis.sessionStorage?.removeItem(key);
38
+ else globalThis.sessionStorage?.setItem(key, value);
39
+ } catch {
40
+ // Storage off (private mode): the login falls back to a second press.
41
+ }
42
+ }
43
+
44
+ /**
45
+ * A wallet login button's behaviour. Pressing it while disconnected opens the
46
+ * connect modal, or on a phone with ConnectKit's `mobile.preferredConnector`
47
+ * that wallet straight away, so call `login()` synchronously in the click
48
+ * handler. The press is marked in sessionStorage (the wallet bounce can reload
49
+ * the page); once the wallet connects the signature starts by itself.
50
+ * Only a fresh mark drives it, so a wallet that reconnects on a later visit
51
+ * never signs unasked. A phone browser opens the wallet for a signature only
52
+ * from a tap, so without one the user presses again.
53
+ */
54
+ export function useWalletLogin(opts: UseWalletLoginOptions = {}): UseWalletLoginResult {
55
+ const { intentKey = "mpo:wallet-login-intent", intentTtlMs = 90_000 } = opts;
56
+ const siwe = useContext(SIWEContext);
57
+ const { setOpen } = useModal();
58
+ const launcher = useConnectorLauncher();
59
+ const { address, isConnected } = useAccount();
60
+ const signingRef = useRef(false);
61
+
62
+ const sign = useCallback(async () => {
63
+ if (!siwe) throw new Error("useWalletLogin must be used inside a SIWEProvider");
64
+ if (signingRef.current) return;
65
+ signingRef.current = true;
66
+ try {
67
+ await siwe.signIn();
68
+ } finally {
69
+ signingRef.current = false;
70
+ }
71
+ }, [siwe]);
72
+
73
+ const login = useCallback(async () => {
74
+ if (isConnected) {
75
+ await sign();
76
+ return;
77
+ }
78
+ writeIntent(intentKey, String(Date.now()));
79
+ // No await above: a phone's preferred wallet opens from inside the tap.
80
+ if (launcher?.openPreferredConnector()) return;
81
+ setOpen(true);
82
+ }, [isConnected, sign, intentKey, setOpen, launcher]);
83
+
84
+ useEffect(() => {
85
+ if (!isConnected || !readIntent(intentKey, intentTtlMs)) return;
86
+ if (isMobileBrowser() && !hasUserActivation()) return;
87
+ setOpen(false);
88
+ void sign();
89
+ }, [isConnected, intentKey, intentTtlMs, setOpen, sign]);
90
+
91
+ useEffect(() => () => writeIntent(intentKey, null), [intentKey]);
92
+
93
+ return {
94
+ login,
95
+ status: siwe?.status ?? StatusState.ERROR,
96
+ isConnected,
97
+ address,
98
+ };
99
+ }
@@ -0,0 +1,291 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { createWalletMessage } from "../connectkit/connectors/createWalletMessage";
3
+ import { SOLANA_CHAIN_ID } from "../connectkit/connectors/syntheticChains";
4
+ import { createSiwsMessage } from "../siws/message";
5
+ import { buildWalletMessage } from "./buildWalletMessage";
6
+
7
+ const common = {
8
+ domain: "app.multiplatform.one",
9
+ uri: "https://app.multiplatform.one",
10
+ nonce: "ohY7vD2Kq9",
11
+ issuedAt: "2026-09-26T20:48:18.648Z",
12
+ };
13
+
14
+ describe("buildWalletMessage", () => {
15
+ it("eth: EIP-4361 with the EIP-55 address and no optional fields", () => {
16
+ expect(
17
+ buildWalletMessage("eth", {
18
+ ...common,
19
+ address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
20
+ chainId: 137,
21
+ }),
22
+ ).toBe(
23
+ "app.multiplatform.one wants you to sign in with your Ethereum account:\n" +
24
+ "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\n" +
25
+ "\n" +
26
+ "Sign in With Ethereum.\n" +
27
+ "\n" +
28
+ "URI: https://app.multiplatform.one\n" +
29
+ "Version: 1\n" +
30
+ "Chain ID: 137\n" +
31
+ "Nonce: ohY7vD2Kq9\n" +
32
+ "Issued At: 2026-09-26T20:48:18.648Z",
33
+ );
34
+ });
35
+
36
+ it("eth: chain id defaults to 1 and the evm alias builds the same bytes", () => {
37
+ const opts = { ...common, address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" };
38
+ const message = buildWalletMessage("eth", opts);
39
+ expect(message).toContain("\nChain ID: 1\n");
40
+ expect(buildWalletMessage("evm", opts)).toBe(message);
41
+ });
42
+
43
+ it("sol: SIWS", () => {
44
+ expect(
45
+ buildWalletMessage("sol", {
46
+ ...common,
47
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
48
+ }),
49
+ ).toBe(
50
+ "app.multiplatform.one wants you to sign in with your Solana account:\n" +
51
+ "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS\n" +
52
+ "\n" +
53
+ "Sign in With Solana.\n" +
54
+ "\n" +
55
+ "URI: https://app.multiplatform.one\n" +
56
+ "Version: 1\n" +
57
+ "Chain ID: solana:mainnet\n" +
58
+ "Nonce: ohY7vD2Kq9\n" +
59
+ "Issued At: 2026-09-26T20:48:18.648Z",
60
+ );
61
+ });
62
+
63
+ it("sui", () => {
64
+ expect(
65
+ buildWalletMessage("sui", {
66
+ ...common,
67
+ address: "0x7a1e0b5c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a",
68
+ }),
69
+ ).toBe(
70
+ "app.multiplatform.one wants you to sign in with your Sui account:\n" +
71
+ "0x7a1e0b5c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a\n" +
72
+ "\n" +
73
+ "Sign in With Sui.\n" +
74
+ "\n" +
75
+ "URI: https://app.multiplatform.one\n" +
76
+ "Version: 1\n" +
77
+ "Chain ID: sui:mainnet\n" +
78
+ "Nonce: ohY7vD2Kq9\n" +
79
+ "Issued At: 2026-09-26T20:48:18.648Z",
80
+ );
81
+ });
82
+
83
+ it("btc", () => {
84
+ expect(
85
+ buildWalletMessage("btc", {
86
+ ...common,
87
+ address: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
88
+ }),
89
+ ).toBe(
90
+ "app.multiplatform.one wants you to sign in with your Bitcoin account:\n" +
91
+ "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\n" +
92
+ "\n" +
93
+ "Sign in With Bitcoin.\n" +
94
+ "\n" +
95
+ "URI: https://app.multiplatform.one\n" +
96
+ "Version: 1\n" +
97
+ "Chain ID: bitcoin\n" +
98
+ "Nonce: ohY7vD2Kq9\n" +
99
+ "Issued At: 2026-09-26T20:48:18.648Z",
100
+ );
101
+ });
102
+
103
+ it("gpg: no address or chain line, the GpgProvider default envelope", () => {
104
+ expect(buildWalletMessage("gpg", common)).toBe(
105
+ "app.multiplatform.one wants you to sign in with your GPG key.\n" +
106
+ "\n" +
107
+ "URI: https://app.multiplatform.one\n" +
108
+ "Version: 1\n" +
109
+ "Nonce: ohY7vD2Kq9\n" +
110
+ "Issued At: 2026-09-26T20:48:18.648Z",
111
+ );
112
+ });
113
+
114
+ it("gpg: a statement sits between the header and the fields", () => {
115
+ expect(buildWalletMessage("gpg", { ...common, statement: "Hello." })).toBe(
116
+ "app.multiplatform.one wants you to sign in with your GPG key.\n" +
117
+ "\n" +
118
+ "Hello.\n" +
119
+ "\n" +
120
+ "URI: https://app.multiplatform.one\n" +
121
+ "Version: 1\n" +
122
+ "Nonce: ohY7vD2Kq9\n" +
123
+ "Issued At: 2026-09-26T20:48:18.648Z",
124
+ );
125
+ });
126
+
127
+ it("a null statement drops the statement lines", () => {
128
+ expect(
129
+ buildWalletMessage("sol", {
130
+ ...common,
131
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
132
+ statement: null,
133
+ }),
134
+ ).toBe(
135
+ "app.multiplatform.one wants you to sign in with your Solana account:\n" +
136
+ "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS\n" +
137
+ "\n" +
138
+ "URI: https://app.multiplatform.one\n" +
139
+ "Version: 1\n" +
140
+ "Chain ID: solana:mainnet\n" +
141
+ "Nonce: ohY7vD2Kq9\n" +
142
+ "Issued At: 2026-09-26T20:48:18.648Z",
143
+ );
144
+ });
145
+
146
+ it.each([null, ""])("eth: a %j statement keeps EIP-4361's empty statement line", (statement) => {
147
+ expect(
148
+ buildWalletMessage("eth", {
149
+ ...common,
150
+ address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
151
+ statement,
152
+ }),
153
+ ).toBe(
154
+ "app.multiplatform.one wants you to sign in with your Ethereum account:\n" +
155
+ "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\n" +
156
+ "\n" +
157
+ "\n" +
158
+ "URI: https://app.multiplatform.one\n" +
159
+ "Version: 1\n" +
160
+ "Chain ID: 1\n" +
161
+ "Nonce: ohY7vD2Kq9\n" +
162
+ "Issued At: 2026-09-26T20:48:18.648Z",
163
+ );
164
+ });
165
+
166
+ it.each([
167
+ ["statement", { statement: "Sign in.\nURI: https://evil.example" }],
168
+ ["statement", { statement: "Sign in.\r" }],
169
+ ["uri", { uri: "https://app.multiplatform.one\nNonce: forged" }],
170
+ ["domain", { domain: "app.multiplatform.one\nevil.example" }],
171
+ ])("refuses a %s with a line break", (field, override) => {
172
+ for (const family of ["eth", "sol", "gpg"] as const) {
173
+ expect(() =>
174
+ buildWalletMessage(family, {
175
+ ...common,
176
+ address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
177
+ ...override,
178
+ }),
179
+ ).toThrow(`${field} must be a single line`);
180
+ }
181
+ });
182
+
183
+ it("a numeric chain id on a non-EVM family is a connector's synthetic id and is ignored", () => {
184
+ const message = buildWalletMessage("sol", {
185
+ ...common,
186
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
187
+ chainId: SOLANA_CHAIN_ID,
188
+ });
189
+ expect(message).toContain("\nChain ID: solana:mainnet\n");
190
+ expect(
191
+ buildWalletMessage("sol", {
192
+ ...common,
193
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
194
+ chainId: "solana:devnet",
195
+ }),
196
+ ).toContain("\nChain ID: solana:devnet\n");
197
+ });
198
+
199
+ describe("page defaults", () => {
200
+ afterEach(() => {
201
+ vi.unstubAllGlobals();
202
+ vi.useRealTimers();
203
+ });
204
+
205
+ it("takes domain and uri from the page", () => {
206
+ vi.stubGlobal("location", { host: "login.example.com", origin: "https://login.example.com" });
207
+ const message = buildWalletMessage("gpg", { nonce: "n", issuedAt: common.issuedAt });
208
+ expect(message.split("\n")[0]).toBe(
209
+ "login.example.com wants you to sign in with your GPG key.",
210
+ );
211
+ expect(message).toContain("\nURI: https://login.example.com\n");
212
+ });
213
+
214
+ it("an explicit domain wins, and a page with no origin (file://) falls back to https://<domain>", () => {
215
+ vi.stubGlobal("location", { host: "", origin: "null" });
216
+ const message = buildWalletMessage("gpg", {
217
+ nonce: "n",
218
+ domain: "wallet.example.com",
219
+ issuedAt: common.issuedAt,
220
+ });
221
+ expect(message.split("\n")[0]).toBe(
222
+ "wallet.example.com wants you to sign in with your GPG key.",
223
+ );
224
+ expect(message).toContain("\nURI: https://wallet.example.com\n");
225
+ });
226
+
227
+ it("refuses to build without a domain", () => {
228
+ vi.stubGlobal("location", { host: "", origin: "null" });
229
+ expect(() => buildWalletMessage("gpg", { nonce: "n" })).toThrow(/no domain/);
230
+ });
231
+
232
+ it("issuedAt defaults to now", () => {
233
+ vi.useFakeTimers();
234
+ vi.setSystemTime(new Date("2026-01-02T03:04:05.006Z"));
235
+ expect(buildWalletMessage("gpg", { ...common, issuedAt: undefined })).toMatch(
236
+ /\nIssued At: 2026-01-02T03:04:05\.006Z$/,
237
+ );
238
+ });
239
+ });
240
+
241
+ it("requires an address for wallet families", () => {
242
+ expect(() => buildWalletMessage("eth", common)).toThrow(/needs an address/);
243
+ });
244
+ });
245
+
246
+ describe("builders that delegate to buildWalletMessage", () => {
247
+ it("createWalletMessage picks the family from the connector's chain id", () => {
248
+ vi.useFakeTimers();
249
+ vi.setSystemTime(new Date(common.issuedAt));
250
+ const sol = createWalletMessage({
251
+ ...common,
252
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
253
+ chainId: SOLANA_CHAIN_ID,
254
+ });
255
+ expect(sol).toBe(
256
+ buildWalletMessage("sol", {
257
+ ...common,
258
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
259
+ }),
260
+ );
261
+ const eth = createWalletMessage({
262
+ ...common,
263
+ address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
264
+ chainId: 10,
265
+ });
266
+ expect(eth).toBe(
267
+ buildWalletMessage("eth", {
268
+ ...common,
269
+ address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
270
+ chainId: 10,
271
+ }),
272
+ );
273
+ vi.useRealTimers();
274
+ });
275
+
276
+ it("createSiwsMessage keeps its output (statement optional)", () => {
277
+ const params = {
278
+ domain: common.domain,
279
+ uri: common.uri,
280
+ nonce: common.nonce,
281
+ issuedAt: common.issuedAt,
282
+ address: "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
283
+ };
284
+ expect(createSiwsMessage({ ...params, statement: "Sign in With Solana." })).toBe(
285
+ buildWalletMessage("sol", params),
286
+ );
287
+ expect(createSiwsMessage(params)).toBe(
288
+ buildWalletMessage("sol", { ...params, statement: null }),
289
+ );
290
+ });
291
+ });
@@ -0,0 +1,150 @@
1
+ import { getAddress } from "viem";
2
+
3
+ /**
4
+ * The signer families a wallet sign-in message can be built for. The Keycloak
5
+ * SPIs (SHC `siww`, mpo `wallet`) content-sniff exactly these headers.
6
+ */
7
+ export type WalletMessageFamily = "eth" | "sol" | "sui" | "btc" | "gpg";
8
+
9
+ /** Ecosystem names the connectors use; accepted as aliases of the short family. */
10
+ export type WalletMessageEcosystem = "evm" | "solana" | "sui" | "bitcoin";
11
+
12
+ export type SignerFamily = WalletMessageFamily | WalletMessageEcosystem;
13
+
14
+ export interface WalletMessageOptions {
15
+ nonce: string;
16
+ /** Signer address. Required for every family except `gpg`, whose identity comes from the key. */
17
+ address?: string;
18
+ /**
19
+ * Host the user signs in to, checked against the realm's frontend host and
20
+ * `siww.allowedDomains` / `wallet.allowedDomains`. Defaults to
21
+ * `window.location.host`; pass it explicitly from a WebView or native page,
22
+ * where that host is empty or not the one the realm allows.
23
+ */
24
+ domain?: string;
25
+ /** Defaults to `window.location.origin`, or `https://<domain>` when the page has no origin. */
26
+ uri?: string;
27
+ /**
28
+ * Defaults to the family's statement; `null` or `""` omits it. `eth` then
29
+ * keeps the empty line EIP-4361 puts in its place.
30
+ */
31
+ statement?: string | null;
32
+ /** Defaults to now. */
33
+ issuedAt?: string;
34
+ /**
35
+ * `eth`: the chain id (default 1). Other families keep their fixed `Chain ID:`
36
+ * value (`solana:mainnet`, ...) unless given a string; a number there is a
37
+ * connector's synthetic chain id and is ignored.
38
+ */
39
+ chainId?: number | string;
40
+ version?: string;
41
+ }
42
+
43
+ interface FamilySpec {
44
+ header: string;
45
+ statement: string | null;
46
+ chainId: string | null;
47
+ normalize?: (address: string) => string;
48
+ }
49
+
50
+ const specs: Record<WalletMessageFamily, FamilySpec> = {
51
+ eth: {
52
+ header: "wants you to sign in with your Ethereum account:",
53
+ statement: "Sign in With Ethereum.",
54
+ chainId: "1",
55
+ normalize: (address) => getAddress(address),
56
+ },
57
+ sol: {
58
+ header: "wants you to sign in with your Solana account:",
59
+ statement: "Sign in With Solana.",
60
+ chainId: "solana:mainnet",
61
+ },
62
+ sui: {
63
+ header: "wants you to sign in with your Sui account:",
64
+ statement: "Sign in With Sui.",
65
+ chainId: "sui:mainnet",
66
+ },
67
+ btc: {
68
+ header: "wants you to sign in with your Bitcoin account:",
69
+ statement: "Sign in With Bitcoin.",
70
+ chainId: "bitcoin",
71
+ },
72
+ gpg: {
73
+ header: "wants you to sign in with your GPG key.",
74
+ statement: null,
75
+ chainId: null,
76
+ },
77
+ };
78
+
79
+ const aliases: Record<SignerFamily, WalletMessageFamily> = {
80
+ eth: "eth",
81
+ sol: "sol",
82
+ sui: "sui",
83
+ btc: "btc",
84
+ gpg: "gpg",
85
+ evm: "eth",
86
+ solana: "sol",
87
+ bitcoin: "btc",
88
+ };
89
+
90
+ /** Map an ecosystem name (`evm`, `solana`, `bitcoin`) or a short family to the short family. */
91
+ export function toWalletMessageFamily(family: SignerFamily): WalletMessageFamily {
92
+ const resolved = aliases[family];
93
+ if (!resolved) throw new Error(`unknown wallet message family: ${String(family)}`);
94
+ return resolved;
95
+ }
96
+
97
+ function singleLine(field: string, value: string | null | undefined) {
98
+ if (value && /[\r\n]/.test(value)) {
99
+ throw new Error(`buildWalletMessage: ${field} must be a single line`);
100
+ }
101
+ }
102
+
103
+ function pageLocation(): { host: string; origin: string } {
104
+ const location = (globalThis as { location?: { host?: string; origin?: string } }).location;
105
+ return { host: location?.host ?? "", origin: location?.origin ?? "" };
106
+ }
107
+
108
+ /**
109
+ * Build the sign-in message for one signer family. This is the only builder in
110
+ * mpo web3: EIP-4361 for `eth` (EIP-55 address, no optional fields), SIWS for
111
+ * `sol`, and the same envelope for `sui`, `btc` and `gpg`, in the exact bytes
112
+ * the Keycloak verifiers parse.
113
+ */
114
+ export function buildWalletMessage(family: SignerFamily, opts: WalletMessageOptions): string {
115
+ const key = toWalletMessageFamily(family);
116
+ const spec = specs[key];
117
+ const page = pageLocation();
118
+ const domain = opts.domain ?? page.host;
119
+ if (!domain) {
120
+ throw new Error(
121
+ "buildWalletMessage: no domain. Pass opts.domain; a file:// or native page has no host.",
122
+ );
123
+ }
124
+ const pageOrigin = page.origin && page.origin !== "null" ? page.origin : "";
125
+ const uri = opts.uri ?? (pageOrigin || `https://${domain}`);
126
+ const statement = opts.statement === undefined ? spec.statement : opts.statement;
127
+ singleLine("domain", domain);
128
+ singleLine("uri", uri);
129
+ singleLine("statement", statement);
130
+ const lines = [`${domain} ${spec.header}`];
131
+ if (key !== "gpg") {
132
+ if (!opts.address) throw new Error(`buildWalletMessage: ${key} needs an address`);
133
+ lines.push(spec.normalize ? spec.normalize(opts.address) : opts.address);
134
+ }
135
+ lines.push("");
136
+ if (statement) lines.push(statement, "");
137
+ else if (key === "eth") lines.push("");
138
+ lines.push(`URI: ${uri}`, `Version: ${opts.version ?? "1"}`);
139
+ if (spec.chainId !== null) {
140
+ const chainId =
141
+ key === "eth"
142
+ ? (opts.chainId ?? spec.chainId)
143
+ : typeof opts.chainId === "string"
144
+ ? opts.chainId
145
+ : spec.chainId;
146
+ lines.push(`Chain ID: ${chainId}`);
147
+ }
148
+ lines.push(`Nonce: ${opts.nonce}`, `Issued At: ${opts.issuedAt ?? new Date().toISOString()}`);
149
+ return lines.join("\n");
150
+ }
@@ -0,0 +1,8 @@
1
+ export {
2
+ buildWalletMessage,
3
+ toWalletMessageFamily,
4
+ type SignerFamily,
5
+ type WalletMessageEcosystem,
6
+ type WalletMessageFamily,
7
+ type WalletMessageOptions,
8
+ } from "./buildWalletMessage";
@@ -1,5 +1,5 @@
1
1
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2
- import { ConnectKitProvider, getDefaultConfig } from "../connectkit";
2
+ import { ConnectKitProvider, SIWEProvider, type SIWEConfig, getDefaultConfig } from "../connectkit";
3
3
  import { isWeb } from "@multiplatform.one/platform";
4
4
  import type { PropsWithChildren } from "react";
5
5
  import { useMemo } from "react";
@@ -11,6 +11,12 @@ import { type Web3Config, Web3ConfigContext, resolveChains } from "./walletConfi
11
11
  export interface WalletProviderProps extends PropsWithChildren {
12
12
  config: Web3Config;
13
13
  queryClient?: QueryClient;
14
+ /**
15
+ * Mounts a SIWEProvider around the ConnectKit modal, e.g.
16
+ * `kc.siweConfig(grant.onSign)` for `useDirectLogin`. It has to sit outside
17
+ * ConnectKitProvider, so a child cannot add its own.
18
+ */
19
+ siwe?: SIWEConfig;
14
20
  }
15
21
 
16
22
  const defaultQueryClient = new QueryClient();
@@ -26,6 +32,7 @@ export function WalletProvider({
26
32
  children,
27
33
  config: web3Config,
28
34
  queryClient = defaultQueryClient,
35
+ siwe,
29
36
  }: WalletProviderProps) {
30
37
  const {
31
38
  walletConnectProjectId,
@@ -88,7 +95,13 @@ export function WalletProvider({
88
95
  <Web3ConfigContext.Provider value={web3Config}>
89
96
  <WagmiProvider config={wagmiConfig}>
90
97
  <QueryClientProvider client={queryClient}>
91
- <ConnectKitProvider>{children}</ConnectKitProvider>
98
+ {siwe ? (
99
+ <SIWEProvider {...siwe}>
100
+ <ConnectKitProvider>{children}</ConnectKitProvider>
101
+ </SIWEProvider>
102
+ ) : (
103
+ <ConnectKitProvider>{children}</ConnectKitProvider>
104
+ )}
92
105
  </QueryClientProvider>
93
106
  </WagmiProvider>
94
107
  </Web3ConfigContext.Provider>
@@ -1,3 +1,5 @@
1
+ import { buildWalletMessage } from "../message";
2
+
1
3
  export interface SiwsMessageParams {
2
4
  /** Authority requesting the sign-in, e.g. `app.example.com`. */
3
5
  domain: string;
@@ -21,26 +23,5 @@ export interface SiwsMessageParams {
21
23
  * signature against, so the server must rebuild this from the same params.
22
24
  */
23
25
  export function createSiwsMessage(params: SiwsMessageParams): string {
24
- const {
25
- domain,
26
- address,
27
- statement,
28
- uri,
29
- version = "1",
30
- chainId = "solana:mainnet",
31
- nonce,
32
- issuedAt,
33
- } = params;
34
- const lines = [`${domain} wants you to sign in with your Solana account:`, address, ""];
35
- if (statement) {
36
- lines.push(statement, "");
37
- }
38
- lines.push(
39
- `URI: ${uri}`,
40
- `Version: ${version}`,
41
- `Chain ID: ${chainId}`,
42
- `Nonce: ${nonce}`,
43
- `Issued At: ${issuedAt}`,
44
- );
45
- return lines.join("\n");
26
+ return buildWalletMessage("sol", { ...params, statement: params.statement ?? null });
46
27
  }
package/src/solana.ts CHANGED
@@ -16,6 +16,7 @@ export {
16
16
  type SolanaClient,
17
17
  type SolanaClientConfig,
18
18
  type SolanaCluster,
19
+ type SolanaCommitmentStatus,
19
20
  type SolanaConfirmationFailure,
20
21
  type SolanaConfirmOptions,
21
22
  type SolanaSigner,