@mezo-org/passport 0.4.0-dev.1 → 0.4.0-dev.11

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 (233) hide show
  1. package/dist/src/api/auth.d.ts +57 -52
  2. package/dist/src/api/auth.d.ts.map +1 -1
  3. package/dist/src/api/auth.js +22 -53
  4. package/dist/src/api/auth.js.map +1 -1
  5. package/dist/src/api/client.d.ts +24 -0
  6. package/dist/src/api/client.d.ts.map +1 -0
  7. package/dist/src/api/client.js +54 -0
  8. package/dist/src/api/client.js.map +1 -0
  9. package/dist/src/api/fetch-error.d.ts +5 -0
  10. package/dist/src/api/fetch-error.d.ts.map +1 -0
  11. package/dist/src/api/fetch-error.js +8 -0
  12. package/dist/src/api/fetch-error.js.map +1 -0
  13. package/dist/src/api/index.d.ts +3 -0
  14. package/dist/src/api/index.d.ts.map +1 -0
  15. package/dist/src/api/index.js +3 -0
  16. package/dist/src/api/index.js.map +1 -0
  17. package/dist/src/api/portal.d.ts +32 -0
  18. package/dist/src/api/portal.d.ts.map +1 -0
  19. package/dist/src/api/portal.js +23 -0
  20. package/dist/src/api/portal.js.map +1 -0
  21. package/dist/src/assets/DefaultAvatar.d.ts +5 -0
  22. package/dist/src/assets/DefaultAvatar.d.ts.map +1 -0
  23. package/dist/src/assets/DefaultAvatar.js +21 -0
  24. package/dist/src/assets/DefaultAvatar.js.map +1 -0
  25. package/dist/src/components/Dropdown/AccountAddress.d.ts +8 -0
  26. package/dist/src/components/Dropdown/AccountAddress.d.ts.map +1 -0
  27. package/dist/src/components/Dropdown/AccountAddress.js +66 -0
  28. package/dist/src/components/Dropdown/AccountAddress.js.map +1 -0
  29. package/dist/src/components/Dropdown/AccountAssets.d.ts +14 -0
  30. package/dist/src/components/Dropdown/AccountAssets.d.ts.map +1 -0
  31. package/dist/src/components/Dropdown/AccountAssets.js +44 -0
  32. package/dist/src/components/Dropdown/AccountAssets.js.map +1 -0
  33. package/dist/src/components/Dropdown/AccountBalance.d.ts +7 -0
  34. package/dist/src/components/Dropdown/AccountBalance.d.ts.map +1 -0
  35. package/dist/src/components/Dropdown/AccountBalance.js +18 -0
  36. package/dist/src/components/Dropdown/AccountBalance.js.map +1 -0
  37. package/dist/src/components/Dropdown/ConnectedTrigger.d.ts +7 -0
  38. package/dist/src/components/Dropdown/ConnectedTrigger.d.ts.map +1 -0
  39. package/dist/src/components/Dropdown/ConnectedTrigger.js +30 -0
  40. package/dist/src/components/Dropdown/ConnectedTrigger.js.map +1 -0
  41. package/dist/src/components/Dropdown/Content.d.ts +9 -0
  42. package/dist/src/components/Dropdown/Content.d.ts.map +1 -0
  43. package/dist/src/components/Dropdown/Content.js +69 -0
  44. package/dist/src/components/Dropdown/Content.js.map +1 -0
  45. package/dist/src/components/Dropdown/DisconnectedTrigger.d.ts +7 -0
  46. package/dist/src/components/Dropdown/DisconnectedTrigger.d.ts.map +1 -0
  47. package/dist/src/components/Dropdown/DisconnectedTrigger.js +13 -0
  48. package/dist/src/components/Dropdown/DisconnectedTrigger.js.map +1 -0
  49. package/dist/src/components/Dropdown/Dropdown.d.ts +20 -0
  50. package/dist/src/components/Dropdown/Dropdown.d.ts.map +1 -0
  51. package/dist/src/components/Dropdown/Dropdown.js +64 -0
  52. package/dist/src/components/Dropdown/Dropdown.js.map +1 -0
  53. package/dist/src/components/Dropdown/WelcomeBlock.d.ts +8 -0
  54. package/dist/src/components/Dropdown/WelcomeBlock.d.ts.map +1 -0
  55. package/dist/src/components/Dropdown/WelcomeBlock.js +44 -0
  56. package/dist/src/components/Dropdown/WelcomeBlock.js.map +1 -0
  57. package/dist/src/components/Dropdown/index.d.ts +3 -0
  58. package/dist/src/components/Dropdown/index.d.ts.map +1 -0
  59. package/dist/src/components/Dropdown/index.js +2 -0
  60. package/dist/src/components/Dropdown/index.js.map +1 -0
  61. package/dist/src/components/index.d.ts +2 -0
  62. package/dist/src/components/index.d.ts.map +1 -0
  63. package/dist/src/components/index.js +2 -0
  64. package/dist/src/components/index.js.map +1 -0
  65. package/dist/src/hooks/constants.d.ts +3 -3
  66. package/dist/src/hooks/constants.js +4 -4
  67. package/dist/src/hooks/constants.js.map +1 -1
  68. package/dist/src/hooks/index.d.ts +1 -4
  69. package/dist/src/hooks/index.d.ts.map +1 -1
  70. package/dist/src/hooks/index.js +1 -4
  71. package/dist/src/hooks/index.js.map +1 -1
  72. package/dist/src/hooks/useAssetsUSDConversion.d.ts +8 -0
  73. package/dist/src/hooks/useAssetsUSDConversion.d.ts.map +1 -0
  74. package/dist/src/hooks/useAssetsUSDConversion.js +21 -0
  75. package/dist/src/hooks/useAssetsUSDConversion.js.map +1 -0
  76. package/dist/src/hooks/useAuthApiClient.d.ts +1 -1
  77. package/dist/src/hooks/useAuthApiClient.d.ts.map +1 -1
  78. package/dist/src/hooks/useAuthenticateWithWallet.d.ts +73 -0
  79. package/dist/src/hooks/useAuthenticateWithWallet.d.ts.map +1 -0
  80. package/dist/src/hooks/useAuthenticateWithWallet.js +69 -0
  81. package/dist/src/hooks/useAuthenticateWithWallet.js.map +1 -0
  82. package/dist/src/hooks/useCreateAccount.d.ts +41 -137
  83. package/dist/src/hooks/useCreateAccount.d.ts.map +1 -1
  84. package/dist/src/hooks/useCreateAccount.js +8 -10
  85. package/dist/src/hooks/useCreateAccount.js.map +1 -1
  86. package/dist/src/hooks/useCreateSession.d.ts +12 -182
  87. package/dist/src/hooks/useCreateSession.d.ts.map +1 -1
  88. package/dist/src/hooks/useCreateSession.js +12 -18
  89. package/dist/src/hooks/useCreateSession.js.map +1 -1
  90. package/dist/src/hooks/useDropdownData.d.ts +45 -0
  91. package/dist/src/hooks/useDropdownData.d.ts.map +1 -0
  92. package/dist/src/hooks/useDropdownData.js +74 -0
  93. package/dist/src/hooks/useDropdownData.js.map +1 -0
  94. package/dist/src/hooks/useEnsureNoSessionAndFetchNonce.d.ts +5 -0
  95. package/dist/src/hooks/useEnsureNoSessionAndFetchNonce.d.ts.map +1 -0
  96. package/dist/src/hooks/useEnsureNoSessionAndFetchNonce.js +34 -0
  97. package/dist/src/hooks/useEnsureNoSessionAndFetchNonce.js.map +1 -0
  98. package/dist/src/hooks/useGetAccountByAddress.d.ts +3 -5
  99. package/dist/src/hooks/useGetAccountByAddress.d.ts.map +1 -1
  100. package/dist/src/hooks/useGetAccountByAddress.js +3 -4
  101. package/dist/src/hooks/useGetAccountByAddress.js.map +1 -1
  102. package/dist/src/hooks/useGetAccountByMezoId.d.ts +3 -5
  103. package/dist/src/hooks/useGetAccountByMezoId.d.ts.map +1 -1
  104. package/dist/src/hooks/useGetAccountByMezoId.js +3 -4
  105. package/dist/src/hooks/useGetAccountByMezoId.js.map +1 -1
  106. package/dist/src/hooks/useGetCurrentAccount.d.ts +14 -8
  107. package/dist/src/hooks/useGetCurrentAccount.d.ts.map +1 -1
  108. package/dist/src/hooks/useGetCurrentAccount.js +28 -6
  109. package/dist/src/hooks/useGetCurrentAccount.js.map +1 -1
  110. package/dist/src/hooks/useGetSession.d.ts +3 -20
  111. package/dist/src/hooks/useGetSession.d.ts.map +1 -1
  112. package/dist/src/hooks/useGetSession.js +2 -2
  113. package/dist/src/hooks/useGetSession.js.map +1 -1
  114. package/dist/src/hooks/useLinkAccount.d.ts +15 -121
  115. package/dist/src/hooks/useLinkAccount.d.ts.map +1 -1
  116. package/dist/src/hooks/useLinkAccount.js +8 -21
  117. package/dist/src/hooks/useLinkAccount.js.map +1 -1
  118. package/dist/src/hooks/usePortalApiClient.d.ts +2 -0
  119. package/dist/src/hooks/usePortalApiClient.d.ts.map +1 -0
  120. package/dist/src/hooks/usePortalApiClient.js +6 -0
  121. package/dist/src/hooks/usePortalApiClient.js.map +1 -0
  122. package/dist/src/hooks/useSignInWithDiscord.d.ts +12 -181
  123. package/dist/src/hooks/useSignInWithDiscord.d.ts.map +1 -1
  124. package/dist/src/hooks/useSignInWithDiscord.js +11 -22
  125. package/dist/src/hooks/useSignInWithDiscord.js.map +1 -1
  126. package/dist/src/hooks/useSignInWithWallet.d.ts +12 -181
  127. package/dist/src/hooks/useSignInWithWallet.d.ts.map +1 -1
  128. package/dist/src/hooks/useSignInWithWallet.js +6 -43
  129. package/dist/src/hooks/useSignInWithWallet.js.map +1 -1
  130. package/dist/src/hooks/useSignOut.d.ts +12 -28
  131. package/dist/src/hooks/useSignOut.d.ts.map +1 -1
  132. package/dist/src/hooks/useSignOut.js +11 -6
  133. package/dist/src/hooks/useSignOut.js.map +1 -1
  134. package/dist/src/hooks/useSignUpWithWallet.d.ts +73 -0
  135. package/dist/src/hooks/useSignUpWithWallet.d.ts.map +1 -0
  136. package/dist/src/hooks/useSignUpWithWallet.js +11 -0
  137. package/dist/src/hooks/useSignUpWithWallet.js.map +1 -0
  138. package/dist/src/hooks/useUpdateMezoId.d.ts +30 -82
  139. package/dist/src/hooks/useUpdateMezoId.d.ts.map +1 -1
  140. package/dist/src/hooks/useUpdateMezoId.js +8 -12
  141. package/dist/src/hooks/useUpdateMezoId.js.map +1 -1
  142. package/dist/src/hooks/useWalletAccount.d.ts +12 -0
  143. package/dist/src/hooks/useWalletAccount.d.ts.map +1 -0
  144. package/dist/src/hooks/useWalletAccount.js +28 -0
  145. package/dist/src/hooks/useWalletAccount.js.map +1 -0
  146. package/dist/src/index.d.ts +1 -0
  147. package/dist/src/index.d.ts.map +1 -1
  148. package/dist/src/index.js +1 -0
  149. package/dist/src/index.js.map +1 -1
  150. package/dist/src/provider.d.ts +10 -13
  151. package/dist/src/provider.d.ts.map +1 -1
  152. package/dist/src/provider.js +11 -20
  153. package/dist/src/provider.js.map +1 -1
  154. package/dist/src/utils/address.d.ts +15 -0
  155. package/dist/src/utils/address.d.ts.map +1 -0
  156. package/dist/src/utils/address.js +35 -0
  157. package/dist/src/utils/address.js.map +1 -0
  158. package/dist/src/utils/address.test.d.ts +2 -0
  159. package/dist/src/utils/address.test.d.ts.map +1 -0
  160. package/dist/src/utils/address.test.js +32 -0
  161. package/dist/src/utils/address.test.js.map +1 -0
  162. package/dist/src/utils/cryptoAssets.d.ts +28 -0
  163. package/dist/src/utils/cryptoAssets.d.ts.map +1 -0
  164. package/dist/src/utils/cryptoAssets.js +73 -0
  165. package/dist/src/utils/cryptoAssets.js.map +1 -0
  166. package/dist/src/utils/cryptoAssets.test.d.ts +2 -0
  167. package/dist/src/utils/cryptoAssets.test.d.ts.map +1 -0
  168. package/dist/src/utils/cryptoAssets.test.js +50 -0
  169. package/dist/src/utils/cryptoAssets.test.js.map +1 -0
  170. package/dist/src/utils/currency.d.ts +14 -0
  171. package/dist/src/utils/currency.d.ts.map +1 -0
  172. package/dist/src/utils/currency.js +27 -0
  173. package/dist/src/utils/currency.js.map +1 -0
  174. package/dist/src/utils/currency.test.d.ts +2 -0
  175. package/dist/src/utils/currency.test.d.ts.map +1 -0
  176. package/dist/src/utils/currency.test.js +34 -0
  177. package/dist/src/utils/currency.test.js.map +1 -0
  178. package/dist/src/utils/numbers.d.ts +26 -0
  179. package/dist/src/utils/numbers.d.ts.map +1 -0
  180. package/dist/src/utils/numbers.js +40 -0
  181. package/dist/src/utils/numbers.js.map +1 -0
  182. package/dist/src/utils/numbers.test.d.ts +2 -0
  183. package/dist/src/utils/numbers.test.d.ts.map +1 -0
  184. package/dist/src/utils/numbers.test.js +54 -0
  185. package/dist/src/utils/numbers.test.js.map +1 -0
  186. package/package.json +10 -4
  187. package/src/api/auth.ts +104 -129
  188. package/src/api/client.ts +78 -0
  189. package/src/api/fetch-error.ts +8 -0
  190. package/src/api/index.ts +2 -0
  191. package/src/api/portal.ts +56 -0
  192. package/src/assets/DefaultAvatar.tsx +74 -0
  193. package/src/components/Dropdown/AccountAddress.tsx +130 -0
  194. package/src/components/Dropdown/AccountAssets.tsx +110 -0
  195. package/src/components/Dropdown/AccountBalance.tsx +38 -0
  196. package/src/components/Dropdown/ConnectedTrigger.tsx +56 -0
  197. package/src/components/Dropdown/Content.tsx +148 -0
  198. package/src/components/Dropdown/DisconnectedTrigger.tsx +36 -0
  199. package/src/components/Dropdown/Dropdown.tsx +111 -0
  200. package/src/components/Dropdown/README.md +51 -0
  201. package/src/components/Dropdown/WelcomeBlock.tsx +92 -0
  202. package/src/components/Dropdown/index.ts +2 -0
  203. package/src/components/index.ts +1 -0
  204. package/src/hooks/constants.ts +4 -4
  205. package/src/hooks/index.ts +1 -4
  206. package/src/hooks/useAssetsUSDConversion.ts +31 -0
  207. package/src/hooks/useAuthenticateWithWallet.ts +98 -0
  208. package/src/hooks/useCreateAccount.ts +20 -11
  209. package/src/hooks/useCreateSession.ts +24 -18
  210. package/src/hooks/useDropdownData.ts +131 -0
  211. package/src/hooks/useEnsureNoSessionAndFetchNonce.ts +46 -0
  212. package/src/hooks/useGetAccountByAddress.ts +11 -5
  213. package/src/hooks/useGetAccountByMezoId.ts +11 -5
  214. package/src/hooks/useGetCurrentAccount.ts +53 -7
  215. package/src/hooks/useGetSession.ts +10 -3
  216. package/src/hooks/useLinkAccount.ts +19 -31
  217. package/src/hooks/usePortalApiClient.ts +6 -0
  218. package/src/hooks/useSignInWithDiscord.ts +19 -28
  219. package/src/hooks/useSignInWithWallet.ts +14 -54
  220. package/src/hooks/useSignOut.ts +22 -6
  221. package/src/hooks/useSignUpWithWallet.ts +21 -0
  222. package/src/hooks/useUpdateMezoId.ts +20 -12
  223. package/src/hooks/useWalletAccount.ts +53 -0
  224. package/src/index.ts +1 -0
  225. package/src/provider.ts +30 -37
  226. package/src/utils/address.test.ts +38 -0
  227. package/src/utils/address.ts +43 -0
  228. package/src/utils/cryptoAssets.test.ts +61 -0
  229. package/src/utils/cryptoAssets.ts +93 -0
  230. package/src/utils/currency.test.ts +38 -0
  231. package/src/utils/currency.ts +32 -0
  232. package/src/utils/numbers.test.ts +73 -0
  233. package/src/utils/numbers.ts +55 -0
@@ -0,0 +1,51 @@
1
+ # Passport Dropdown component
2
+
3
+ This component is a layer of interaction with Passport API in form of Dropdown
4
+ component. It allows to establish the session and interact with the API.
5
+
6
+ ## Props
7
+
8
+ - `onSignIn` (`() => void`) - The callback to be executed on trigger click when
9
+ the state is disconnected. It's optional since by default it triggers the
10
+ [Rainbow Kit's wallet connection modal](https://www.rainbowkit.com/docs/modal-hooks).
11
+ If the callback is not provided it will automatically establish the Passport
12
+ Session. If not, you have to handle it manually using `useSignInWithWallet`
13
+ hook. - **optional**
14
+ - `onSignOut` (`() => void`) - The callback to be executed on click of the
15
+ **Sign out** button. It's optional since by default it disconnects the current
16
+ wallet connector and closes the Passport session. - **optional**
17
+ - `evmNativeAssets` (`Asset<"tbtc" | "wbtc">[]`) - Array of Matsnet assets. -
18
+ **optional**
19
+ - `matsnetAssets` (`Asset<"mbtc" | "musd">[]`) - Array of Matsnet assets. -
20
+ **optional**
21
+ ```ts
22
+ type Asset = {
23
+ type: "btc" | "tbtc" | "wbtc" | "mbtc" | "musd"
24
+ decimals: number
25
+ amount: {
26
+ token: bigint
27
+ usd: number
28
+ }
29
+ }
30
+ ```
31
+
32
+ Besides that, component allows
33
+ [Clay's `StatefulPopover` props](https://baseweb.design/components/popover/)
34
+ excluding the `children` and `content`.
35
+
36
+ ## Overview
37
+
38
+ The component has two distinguishable states - disconnected and connected. In
39
+ disconnected state the component offers the trigger to initiate the connection
40
+ flow. It can be fully customizable by providing your own one. As long as it's
41
+ compliant with Wagmi/RainbowKit it will work. Component will automatically
42
+ detect connected connector and change the state of component displaying the
43
+ avatar thumbnail instead of button.
44
+
45
+ Component has the following features:
46
+
47
+ - displays wallet address that can be copied,
48
+ - displays total balance in USD,
49
+ - displays partial balances per asset with token amounts and USD conversions,
50
+ - serves _Log out_ button which disconnects the wallet connector and closes
51
+ Passport API session.
@@ -0,0 +1,92 @@
1
+ import {
2
+ Block,
3
+ HeadingSmall,
4
+ LabelSmall,
5
+ Mats,
6
+ useStyletron,
7
+ } from "@mezo-org/mezo-clay"
8
+ import React from "react"
9
+ import DefaultAvatar from "../../assets/DefaultAvatar"
10
+ import { formatHumanReadableNumber } from "../../utils/numbers"
11
+
12
+ const DOT_DELIMITER_REGEX = /(?=\.)/
13
+
14
+ type WelcomeBlockProps = {
15
+ mezoId: string
16
+ matsBalance: number
17
+ }
18
+
19
+ export default function WelcomeBlock(props: WelcomeBlockProps) {
20
+ const { mezoId, matsBalance } = props
21
+
22
+ const [name, nameSuffix] = mezoId.split(DOT_DELIMITER_REGEX)
23
+ const [, theme] = useStyletron()
24
+
25
+ return (
26
+ <Block
27
+ display="flex"
28
+ alignItems="center"
29
+ padding={`${theme.sizing.scale600} 0`}
30
+ marginBottom={theme.sizing.scale300}
31
+ overrides={{
32
+ Block: {
33
+ style: {
34
+ gap: theme.sizing.scale600,
35
+ },
36
+ },
37
+ }}
38
+ >
39
+ <Block
40
+ as={DefaultAvatar}
41
+ width={theme.sizing.scale1200}
42
+ height={theme.sizing.scale1200}
43
+ overrides={{
44
+ Block: {
45
+ style: {
46
+ borderRadius: "100%",
47
+ },
48
+ },
49
+ }}
50
+ />
51
+
52
+ <Block
53
+ display="flex"
54
+ flexDirection="column"
55
+ overrides={{
56
+ Block: {
57
+ style: {
58
+ gap: theme.sizing.scale100,
59
+ },
60
+ },
61
+ }}
62
+ >
63
+ <HeadingSmall as="span">
64
+ <Block as="span">{name}</Block>
65
+ <Block as="span" color={theme.colors.gray500}>
66
+ {nameSuffix}
67
+ </Block>
68
+ </HeadingSmall>
69
+
70
+ <LabelSmall
71
+ display="flex"
72
+ alignItems="center"
73
+ margin={0}
74
+ color={theme.colors.contentTertiary}
75
+ overrides={{
76
+ Block: {
77
+ style: {
78
+ gap: theme.sizing.scale300,
79
+ },
80
+ },
81
+ }}
82
+ >
83
+ <Mats
84
+ color={theme.colors.contentPrimary}
85
+ size={theme.sizing.scale600}
86
+ />
87
+ {formatHumanReadableNumber(matsBalance, 2)}
88
+ </LabelSmall>
89
+ </Block>
90
+ </Block>
91
+ )
92
+ }
@@ -0,0 +1,2 @@
1
+ export { Dropdown } from "./Dropdown"
2
+ export type { DropdownProps } from "./Dropdown"
@@ -0,0 +1 @@
1
+ export { Dropdown, DropdownProps } from "./Dropdown"
@@ -1,6 +1,6 @@
1
1
  export const QUERY_KEYS = {
2
- ACCOUNT_BY_ADDRESS: "getAccountByAddress",
3
- ACCOUNT_BY_MEZO_ID: "getAccountByMezoId",
4
- SESSION: "getSession",
5
- CURRENT_ACCOUNT: "getCurrentAccount",
2
+ ACCOUNT: "account",
3
+ SESSION: "session",
4
+ CURRENT: "current",
5
+ ASSETS_USD_CONVERSION: "assetsUsdConversion",
6
6
  }
@@ -6,16 +6,13 @@ export {
6
6
  useSubscribeToConnectorEvent,
7
7
  useSubscribeToWalletNetworkDoesNotMatchProviderChain,
8
8
  } from "@mezo-org/orangekit"
9
- export * from "./constants"
10
- export * from "./useAuthApiClient"
11
- export * from "./useCreateAccount"
12
9
  export * from "./useGetAccountByAddress"
13
10
  export * from "./useGetAccountByMezoId"
14
11
  export * from "./useGetCurrentAccount"
15
12
  export * from "./useGetSession"
16
13
  export * from "./useLinkAccount"
17
- export * from "./usePassportContext"
18
14
  export * from "./useSignInWithDiscord"
19
15
  export * from "./useSignInWithWallet"
20
16
  export * from "./useSignOut"
17
+ export * from "./useSignUpWithWallet"
21
18
  export * from "./useUpdateMezoId"
@@ -0,0 +1,31 @@
1
+ import { UseBaseQueryOptions, useQuery } from "@tanstack/react-query"
2
+ import { ONE_MINUTE_MS } from "../utils/time"
3
+ import { QUERY_KEYS } from "./constants"
4
+ import { usePortalApiClient } from "./usePortalApiClient"
5
+
6
+ type AssetsUsdConversion = {
7
+ btcUsd: string
8
+ ethUsd: string
9
+ }
10
+
11
+ export function useAssetsUsdConversion(
12
+ useQueryOptions: Partial<UseBaseQueryOptions<AssetsUsdConversion>> = {},
13
+ ) {
14
+ const portalApiClient = usePortalApiClient()
15
+
16
+ return useQuery({
17
+ queryKey: [QUERY_KEYS.ASSETS_USD_CONVERSION],
18
+ queryFn: async () => {
19
+ const { currentUsdPerBtc, currentUsdPerEth } =
20
+ await portalApiClient.getPortalStatistics()
21
+
22
+ return {
23
+ btcUsd: currentUsdPerBtc,
24
+ ethUsd: currentUsdPerEth,
25
+ }
26
+ },
27
+ staleTime: 30 * ONE_MINUTE_MS,
28
+ retry: 1,
29
+ ...useQueryOptions,
30
+ })
31
+ }
@@ -0,0 +1,98 @@
1
+ import { useSignMessage } from "wagmi"
2
+ import { MutationOptions, useMutation } from "@tanstack/react-query"
3
+ import { useCreateAccount } from "./useCreateAccount"
4
+ import { useCreateSession } from "./useCreateSession"
5
+ import { useEnsureNoSessionAndFetchNonce } from "./useEnsureNoSessionAndFetchNonce"
6
+ import { createSignInWithWalletMessage } from "../utils/siww"
7
+ import { useGetAccountByAddress } from "./useGetAccountByAddress"
8
+ import type { Session } from "../api"
9
+ import useWalletAccount from "./useWalletAccount"
10
+
11
+ function useAuthenticateWithWallet(
12
+ shouldCreateAccount = false,
13
+ mutationOptions: Omit<
14
+ MutationOptions<Session>,
15
+ "mutationFn" | "mutationKey"
16
+ > = {},
17
+ ) {
18
+ const { address, chainId, connector, networkFamily } = useWalletAccount()
19
+ const { ensureNoSessionAndFetchNonce } = useEnsureNoSessionAndFetchNonce()
20
+ const { createSessionAsync } = useCreateSession()
21
+ const { createAccountAsync } = useCreateAccount()
22
+ const { signMessageAsync } = useSignMessage()
23
+
24
+ const { refetch: getAccountByAddress } = useGetAccountByAddress(address, {
25
+ enabled: false,
26
+ retry: false,
27
+ })
28
+
29
+ const { mutate, mutateAsync, ...signInMutationRestParameters } = useMutation({
30
+ mutationFn: async () => {
31
+ if (!address) {
32
+ throw new Error("Sign in error: Wallet not connected!")
33
+ }
34
+
35
+ const nonce = await ensureNoSessionAndFetchNonce()
36
+
37
+ const messageResult = createSignInWithWalletMessage(
38
+ address,
39
+ nonce,
40
+ networkFamily,
41
+ chainId,
42
+ )
43
+ const signatureResult = await signMessageAsync({
44
+ message: messageResult,
45
+ connector,
46
+ })
47
+
48
+ if (shouldCreateAccount) {
49
+ const getAccountByAddressResult = await getAccountByAddress()
50
+
51
+ if (getAccountByAddressResult.data) {
52
+ throw new Error(
53
+ "Wallet authentication failed: Account creation failed. Account already exists.",
54
+ )
55
+ }
56
+
57
+ if (getAccountByAddressResult.error) {
58
+ throw new Error(
59
+ `Wallet authentication failed: Account creation failed. Could not verify if account already exists: ${getAccountByAddressResult.error}`,
60
+ )
61
+ }
62
+
63
+ // Fetch was successful, but no account was found
64
+ try {
65
+ const createAccountResult = await createAccountAsync({
66
+ type: "wallet",
67
+ message: messageResult,
68
+ signature: signatureResult,
69
+ })
70
+
71
+ if (!createAccountResult) {
72
+ throw new Error("Failed to create new account")
73
+ }
74
+ } catch (error) {
75
+ throw new Error(
76
+ `Wallet authentication failed: Account creation failed: ${error}`,
77
+ )
78
+ }
79
+ }
80
+
81
+ return (await createSessionAsync({
82
+ type: "wallet",
83
+ message: messageResult,
84
+ signature: signatureResult,
85
+ })) as Session
86
+ // ^ By passing type: "wallet" we know for sure the return type is Session
87
+ },
88
+ ...mutationOptions,
89
+ })
90
+
91
+ return {
92
+ authenticateWithWallet: mutate,
93
+ authenticateWithWalletAsync: mutateAsync,
94
+ ...signInMutationRestParameters,
95
+ }
96
+ }
97
+
98
+ export { useAuthenticateWithWallet }
@@ -1,26 +1,35 @@
1
- import { useQueryClient, useMutation } from "@tanstack/react-query"
1
+ import {
2
+ useQueryClient,
3
+ useMutation,
4
+ MutationOptions,
5
+ DefaultError,
6
+ } from "@tanstack/react-query"
2
7
  import { useAuthApiClient } from "./useAuthApiClient"
3
8
  import { QUERY_KEYS } from "./constants"
4
- import { CreateAccountRequest } from "../api/auth"
9
+ import type { CreateAccountRequest, CreateAccountResponse } from "../api"
5
10
 
6
- export function useCreateAccount(useMutationOptions = {}) {
11
+ export function useCreateAccount(
12
+ mutationOptions: Omit<
13
+ MutationOptions<CreateAccountResponse, DefaultError, CreateAccountRequest>,
14
+ "mutationFn" | "mutationKey"
15
+ > = {},
16
+ ) {
7
17
  const queryClient = useQueryClient()
8
18
  const authApiClient = useAuthApiClient()
9
19
 
20
+ const { onSuccess: customOnSuccess, ...restMutationOptions } = mutationOptions
21
+
10
22
  const { mutate, mutateAsync, ...rest } = useMutation({
11
23
  mutationFn: (createAccountRequest: CreateAccountRequest) =>
12
24
  authApiClient.createAccount(createAccountRequest),
13
- onSuccess: () => {
14
- queryClient.resetQueries({
15
- queryKey: [QUERY_KEYS.ACCOUNT_BY_ADDRESS],
16
- exact: false,
17
- })
25
+ onSuccess: (data, variables, context) => {
18
26
  queryClient.resetQueries({
19
- queryKey: [QUERY_KEYS.ACCOUNT_BY_MEZO_ID],
20
- exact: false,
27
+ queryKey: [QUERY_KEYS.ACCOUNT],
21
28
  })
29
+
30
+ if (customOnSuccess) customOnSuccess(data, variables, context)
22
31
  },
23
- ...useMutationOptions,
32
+ ...restMutationOptions,
24
33
  })
25
34
 
26
35
  return { createAccount: mutate, createAccountAsync: mutateAsync, ...rest }
@@ -1,37 +1,43 @@
1
- import { useQueryClient, useMutation } from "@tanstack/react-query"
1
+ import {
2
+ useQueryClient,
3
+ useMutation,
4
+ MutationOptions,
5
+ DefaultError,
6
+ } from "@tanstack/react-query"
2
7
  import { useAuthApiClient } from "./useAuthApiClient"
3
- import { CreateSessionRequest } from "../api/auth"
8
+ import type { CreateSessionRequest, CreateSessionResponse } from "../api"
4
9
  import { QUERY_KEYS } from "./constants"
5
10
 
6
11
  /**
7
12
  * This hook is not exposed for external consumers. For creating session they
8
13
  * should use `useSignIn` hook related to the authentication method.
9
14
  */
10
- export function useCreateSession(useMutationOptions = {}) {
15
+ export function useCreateSession(
16
+ mutationOptions: Omit<
17
+ MutationOptions<CreateSessionResponse, DefaultError, CreateSessionRequest>,
18
+ "mutationFn" | "mutationKey"
19
+ > = {},
20
+ ) {
11
21
  const queryClient = useQueryClient()
12
22
  const authApiClient = useAuthApiClient()
13
23
 
24
+ const { onSuccess: customOnSuccess, ...restMutationOptions } = mutationOptions
25
+
14
26
  const { mutate, mutateAsync, ...rest } = useMutation({
15
27
  mutationFn: (createSessionRequest: CreateSessionRequest) =>
16
28
  authApiClient.createSession(createSessionRequest),
17
- onSuccess: (data) => {
18
- // Since `getSession` query also has code in it's query keys we can't
19
- // set query data for a specific query, because we don't know if the
20
- // code was used or not. Because of that we just reset all getSession
21
- // queries
29
+ onSuccess: (data, variables, context) => {
30
+ // Since `getSession` query also has code in its query keys we can't set
31
+ // query data for a specific query, because we don't know if the code was
32
+ // used or not. Because of that we just reset all getSession queries
33
+ queryClient.resetQueries({ queryKey: [QUERY_KEYS.SESSION] })
22
34
  queryClient.resetQueries({
23
- queryKey: [QUERY_KEYS.SESSION],
24
- exact: false,
35
+ queryKey: [QUERY_KEYS.ACCOUNT, QUERY_KEYS.CURRENT],
25
36
  })
26
- if ("user" in data) {
27
- queryClient.setQueryData([QUERY_KEYS.CURRENT_ACCOUNT], data.user)
28
- } else {
29
- queryClient.resetQueries({
30
- queryKey: [QUERY_KEYS.CURRENT_ACCOUNT],
31
- })
32
- }
37
+
38
+ if (customOnSuccess) customOnSuccess(data, variables, context)
33
39
  },
34
- ...useMutationOptions,
40
+ ...restMutationOptions,
35
41
  })
36
42
 
37
43
  return { createSession: mutate, createSessionAsync: mutateAsync, ...rest }
@@ -0,0 +1,131 @@
1
+ import { useBitcoinAccount } from "@mezo-org/orangekit"
2
+ import { useGetCurrentAccount } from "."
3
+ import {
4
+ CryptoAssetKey,
5
+ getCryptoAsset,
6
+ isBitcoinLikeCryptoAsset,
7
+ isUsdLikeCryptoAsset,
8
+ } from "../utils/cryptoAssets"
9
+ import { fromFixedPoint } from "../utils/numbers"
10
+ import { useAssetsUsdConversion } from "./useAssetsUSDConversion"
11
+ import useWalletAccount from "./useWalletAccount"
12
+
13
+ /**
14
+ * Formats crypto asset to balance details (balance in USD and decimals)
15
+ * @param type The type of crypto asset
16
+ * @param balance The balance of crypto asset
17
+ * @param btcUsdConversionRate The USD conversion rate
18
+ * @returns The balance details
19
+ */
20
+ function formatCryptoAsset(
21
+ type: CryptoAssetKey,
22
+ balance: bigint,
23
+ btcUsdConversionRate: number,
24
+ ) {
25
+ const { decimals } = getCryptoAsset(type)
26
+
27
+ const nativeBalance = fromFixedPoint(balance, decimals, 4)
28
+ let balanceInUsd = 0
29
+ if (isBitcoinLikeCryptoAsset(type)) {
30
+ balanceInUsd = nativeBalance * btcUsdConversionRate
31
+ }
32
+ if (isUsdLikeCryptoAsset(type)) {
33
+ balanceInUsd = nativeBalance
34
+ }
35
+
36
+ return {
37
+ type,
38
+ balance: nativeBalance,
39
+ balanceInUsd,
40
+ decimals,
41
+ }
42
+ }
43
+
44
+ export type DropdownCryptoAsset<T = CryptoAssetKey> = {
45
+ type: T
46
+ balance: bigint
47
+ }
48
+
49
+ type DropdownDetailedCryptoAsset = ReturnType<typeof formatCryptoAsset>
50
+
51
+ export type DropdownData = {
52
+ mezoId: string
53
+ address: string
54
+ walletType: "bitcoin" | "evm"
55
+ totalBalanceInUsd: number
56
+ formattedNativeAssets: DropdownDetailedCryptoAsset[]
57
+ matsnet: {
58
+ mats: number
59
+ formattedAssets: DropdownDetailedCryptoAsset[]
60
+ }
61
+ }
62
+
63
+ type UseDropdownDataOptions = {
64
+ // This is workaround. It should be read from contracts or fetched from API.
65
+ evmNativeAssets?: DropdownCryptoAsset[]
66
+ matsnetAssets?: DropdownCryptoAsset[]
67
+ }
68
+
69
+ /**
70
+ * Aggregates dropdown data for Dropdown component.
71
+ * @param options - Options for the dropdown data.
72
+ * @param options.evmNativeAssets - Native assets for EVM wallet.
73
+ * @param options.matsnetAssets - Matsnet tokens. Rendered as separate section.
74
+ * @returns Dropdown data.
75
+ * @dev This hook is for internal use only.
76
+ */
77
+ export default function useDropdownData(
78
+ options?: UseDropdownDataOptions,
79
+ ): DropdownData | null {
80
+ const { evmNativeAssets = [], matsnetAssets = [] } = options || {}
81
+
82
+ const { btcBalance } = useBitcoinAccount()
83
+ const { address, networkFamily, isConnected } = useWalletAccount()
84
+ const { data: passportAccount } = useGetCurrentAccount()
85
+ const { data: assetsUsdConversion } = useAssetsUsdConversion()
86
+
87
+ if (!address || !isConnected || !passportAccount) {
88
+ return null
89
+ }
90
+
91
+ const mezoId = passportAccount.mezoId!
92
+
93
+ const nativeAssets: DropdownCryptoAsset[] =
94
+ networkFamily === "bitcoin"
95
+ ? [
96
+ {
97
+ type: "btc",
98
+ balance: BigInt(btcBalance?.total ?? 0),
99
+ },
100
+ ]
101
+ : evmNativeAssets
102
+
103
+ const btcUsdConversionRate = Number(assetsUsdConversion?.btcUsd ?? 0)
104
+
105
+ const formattedNativeAssets = nativeAssets.map((asset) =>
106
+ formatCryptoAsset(asset.type, asset.balance, btcUsdConversionRate),
107
+ )
108
+
109
+ const totalBalanceInUsd = formattedNativeAssets.reduce(
110
+ (sum, value) => sum + value.balanceInUsd,
111
+ 0,
112
+ )
113
+
114
+ const matsBalance = passportAccount.mats.totalMats
115
+
116
+ const matsnetFormattedAssets = matsnetAssets.map((asset) =>
117
+ formatCryptoAsset(asset.type, asset.balance, btcUsdConversionRate),
118
+ )
119
+
120
+ return {
121
+ mezoId,
122
+ address,
123
+ walletType: networkFamily,
124
+ totalBalanceInUsd,
125
+ formattedNativeAssets,
126
+ matsnet: {
127
+ mats: matsBalance,
128
+ formattedAssets: matsnetFormattedAssets,
129
+ },
130
+ }
131
+ }
@@ -0,0 +1,46 @@
1
+ import { useCallback } from "react"
2
+ import { useGetSession } from "./useGetSession"
3
+ import { useSignOut } from "./useSignOut"
4
+
5
+ function useEnsureNoSessionAndFetchNonce() {
6
+ const { refetch: getSession } = useGetSession(undefined, {
7
+ enabled: false,
8
+ retry: false,
9
+ })
10
+ const { signOutAsync } = useSignOut()
11
+
12
+ const getAndValidateSession = useCallback(async () => {
13
+ const getSessionResult = await getSession()
14
+
15
+ // TODO: We should create a separate endpoint that will always return nonce
16
+ if (getSessionResult.error) {
17
+ throw new Error(
18
+ `Sign in error: Failed to fetch the current session: ${getSessionResult.error}`,
19
+ )
20
+ }
21
+ if (!getSessionResult.data) {
22
+ throw new Error(
23
+ "Sign in error: Failed to fetch the current session; no data returned.",
24
+ )
25
+ }
26
+
27
+ return getSessionResult.data
28
+ }, [getSession])
29
+
30
+ const ensureNoSessionAndFetchNonce = useCallback(async () => {
31
+ let getSessionResult = await getAndValidateSession()
32
+
33
+ if (!("nonce" in getSessionResult)) {
34
+ // If there is active session we are terminating it
35
+ await signOutAsync()
36
+ // Because we've signed out we can assume nonce will be returned here
37
+ getSessionResult = (await getAndValidateSession()) as { nonce: string }
38
+ }
39
+
40
+ return getSessionResult.nonce
41
+ }, [getAndValidateSession, signOutAsync])
42
+
43
+ return { ensureNoSessionAndFetchNonce }
44
+ }
45
+
46
+ export { useEnsureNoSessionAndFetchNonce }
@@ -1,19 +1,25 @@
1
- import { useQuery, skipToken } from "@tanstack/react-query"
1
+ import { useQuery, skipToken, UseBaseQueryOptions } from "@tanstack/react-query"
2
2
  import { useAuthApiClient } from "./useAuthApiClient"
3
3
  import { QUERY_KEYS } from "./constants"
4
4
  import { ONE_MINUTE_MS } from "../utils/time"
5
+ import type { GetAccountByMezoIdOrAddressResponse } from "../api"
5
6
 
6
- export function useGetAccountByAddress(address?: string, useQueryOptions = {}) {
7
+ export function useGetAccountByAddress(
8
+ address?: string,
9
+ queryOptions: Omit<
10
+ UseBaseQueryOptions<GetAccountByMezoIdOrAddressResponse | null>,
11
+ "queryKey" | "queryFn"
12
+ > = {},
13
+ ) {
7
14
  const authApiClient = useAuthApiClient()
8
15
 
9
16
  return useQuery({
10
- queryKey: [QUERY_KEYS.ACCOUNT_BY_ADDRESS, address],
17
+ queryKey: [QUERY_KEYS.ACCOUNT, address],
11
18
  queryFn: address
12
19
  ? () => authApiClient.getAccountByMezoIdOrAddress(address)
13
20
  : skipToken,
14
21
  staleTime: ONE_MINUTE_MS,
15
22
  retry: 1,
16
- enabled: !!address,
17
- ...useQueryOptions,
23
+ ...queryOptions,
18
24
  })
19
25
  }
@@ -1,19 +1,25 @@
1
- import { useQuery, skipToken } from "@tanstack/react-query"
1
+ import { useQuery, skipToken, UseBaseQueryOptions } from "@tanstack/react-query"
2
2
  import { useAuthApiClient } from "./useAuthApiClient"
3
3
  import { QUERY_KEYS } from "./constants"
4
4
  import { ONE_MINUTE_MS } from "../utils/time"
5
+ import type { GetAccountByMezoIdOrAddressResponse } from "../api"
5
6
 
6
- export function useGetAccountByMezoId(mezoId?: string, useQueryOptions = {}) {
7
+ export function useGetAccountByMezoId(
8
+ mezoId?: string,
9
+ queryOptions: Omit<
10
+ UseBaseQueryOptions<GetAccountByMezoIdOrAddressResponse | null>,
11
+ "queryKey" | "queryFn"
12
+ > = {},
13
+ ) {
7
14
  const authApiClient = useAuthApiClient()
8
15
 
9
16
  return useQuery({
10
- queryKey: [QUERY_KEYS.ACCOUNT_BY_MEZO_ID, mezoId],
17
+ queryKey: [QUERY_KEYS.ACCOUNT, mezoId],
11
18
  queryFn: mezoId
12
19
  ? () => authApiClient.getAccountByMezoIdOrAddress(mezoId)
13
20
  : skipToken,
14
21
  staleTime: ONE_MINUTE_MS,
15
22
  retry: 1,
16
- enabled: !!mezoId,
17
- ...useQueryOptions,
23
+ ...queryOptions,
18
24
  })
19
25
  }