@mezo-org/passport 0.4.0-dev.82 → 0.4.0-dev.84

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 (173) hide show
  1. package/dist/src/components/Dropdown/Content.d.ts +0 -15
  2. package/dist/src/components/Dropdown/Content.d.ts.map +1 -1
  3. package/dist/src/components/Dropdown/Content.js +3 -3
  4. package/dist/src/components/Dropdown/Content.js.map +1 -1
  5. package/dist/src/components/Dropdown/Dropdown.d.ts +0 -4
  6. package/dist/src/components/Dropdown/Dropdown.d.ts.map +1 -1
  7. package/dist/src/components/Dropdown/Dropdown.js +10 -36
  8. package/dist/src/components/Dropdown/Dropdown.js.map +1 -1
  9. package/dist/src/components/Dropdown/ListingItem.d.ts +8 -7
  10. package/dist/src/components/Dropdown/ListingItem.d.ts.map +1 -1
  11. package/dist/src/components/Dropdown/ListingItem.js +36 -28
  12. package/dist/src/components/Dropdown/ListingItem.js.map +1 -1
  13. package/dist/src/components/Dropdown/NestedViewLayout.d.ts +2 -1
  14. package/dist/src/components/Dropdown/NestedViewLayout.d.ts.map +1 -1
  15. package/dist/src/components/Dropdown/NestedViewLayout.js +13 -15
  16. package/dist/src/components/Dropdown/NestedViewLayout.js.map +1 -1
  17. package/dist/src/components/Dropdown/Receive/Receive.d.ts +1 -4
  18. package/dist/src/components/Dropdown/Receive/Receive.d.ts.map +1 -1
  19. package/dist/src/components/Dropdown/Receive/Receive.js +30 -19
  20. package/dist/src/components/Dropdown/Receive/Receive.js.map +1 -1
  21. package/dist/src/components/Dropdown/Root/AccountAddressActions.d.ts +2 -5
  22. package/dist/src/components/Dropdown/Root/AccountAddressActions.d.ts.map +1 -1
  23. package/dist/src/components/Dropdown/Root/AccountAddressActions.js +13 -12
  24. package/dist/src/components/Dropdown/Root/AccountAddressActions.js.map +1 -1
  25. package/dist/src/components/Dropdown/Root/AccountBalance.d.ts +2 -4
  26. package/dist/src/components/Dropdown/Root/AccountBalance.d.ts.map +1 -1
  27. package/dist/src/components/Dropdown/Root/AccountBalance.js +24 -8
  28. package/dist/src/components/Dropdown/Root/AccountBalance.js.map +1 -1
  29. package/dist/src/components/Dropdown/Root/AccountBtcListing.d.ts +6 -0
  30. package/dist/src/components/Dropdown/Root/AccountBtcListing.d.ts.map +1 -0
  31. package/dist/src/components/Dropdown/Root/AccountBtcListing.js +27 -0
  32. package/dist/src/components/Dropdown/Root/AccountBtcListing.js.map +1 -0
  33. package/dist/src/components/Dropdown/Root/AccountError.d.ts +8 -0
  34. package/dist/src/components/Dropdown/Root/AccountError.d.ts.map +1 -0
  35. package/dist/src/components/Dropdown/Root/AccountError.js +17 -0
  36. package/dist/src/components/Dropdown/Root/AccountError.js.map +1 -0
  37. package/dist/src/components/Dropdown/Root/AccountMusdListing.d.ts +4 -0
  38. package/dist/src/components/Dropdown/Root/AccountMusdListing.d.ts.map +1 -0
  39. package/dist/src/components/Dropdown/Root/AccountMusdListing.js +21 -0
  40. package/dist/src/components/Dropdown/Root/AccountMusdListing.js.map +1 -0
  41. package/dist/src/components/Dropdown/Root/AccountOtherAssets.d.ts +2 -3
  42. package/dist/src/components/Dropdown/Root/AccountOtherAssets.d.ts.map +1 -1
  43. package/dist/src/components/Dropdown/Root/AccountOtherAssets.js +34 -39
  44. package/dist/src/components/Dropdown/Root/AccountOtherAssets.js.map +1 -1
  45. package/dist/src/components/Dropdown/Root/Root.d.ts +0 -15
  46. package/dist/src/components/Dropdown/Root/Root.d.ts.map +1 -1
  47. package/dist/src/components/Dropdown/Root/Root.js +22 -34
  48. package/dist/src/components/Dropdown/Root/Root.js.map +1 -1
  49. package/dist/src/components/Dropdown/Root/WalletAddress.d.ts +2 -6
  50. package/dist/src/components/Dropdown/Root/WalletAddress.d.ts.map +1 -1
  51. package/dist/src/components/Dropdown/Root/WalletAddress.js +37 -34
  52. package/dist/src/components/Dropdown/Root/WalletAddress.js.map +1 -1
  53. package/dist/src/components/Dropdown/Root/WelcomeBlock.d.ts +2 -4
  54. package/dist/src/components/Dropdown/Root/WelcomeBlock.d.ts.map +1 -1
  55. package/dist/src/components/Dropdown/Root/WelcomeBlock.js +60 -16
  56. package/dist/src/components/Dropdown/Root/WelcomeBlock.js.map +1 -1
  57. package/dist/src/components/Dropdown/SlotNumber.d.ts +19 -0
  58. package/dist/src/components/Dropdown/SlotNumber.d.ts.map +1 -0
  59. package/dist/src/components/Dropdown/SlotNumber.js +67 -0
  60. package/dist/src/components/Dropdown/SlotNumber.js.map +1 -0
  61. package/dist/src/config.d.ts +0 -1
  62. package/dist/src/config.d.ts.map +1 -1
  63. package/dist/src/config.js +1 -9
  64. package/dist/src/config.js.map +1 -1
  65. package/dist/src/hooks/useAssetsConversionRates.d.ts +8 -13
  66. package/dist/src/hooks/useAssetsConversionRates.d.ts.map +1 -1
  67. package/dist/src/hooks/useAssetsConversionRates.js +44 -67
  68. package/dist/src/hooks/useAssetsConversionRates.js.map +1 -1
  69. package/dist/src/hooks/useAuthenticateWithWallet.d.ts.map +1 -1
  70. package/dist/src/hooks/useAuthenticateWithWallet.js +1 -1
  71. package/dist/src/hooks/useAuthenticateWithWallet.js.map +1 -1
  72. package/dist/src/hooks/useBorrowData.d.ts +30 -4
  73. package/dist/src/hooks/useBorrowData.d.ts.map +1 -1
  74. package/dist/src/hooks/useBorrowData.js +53 -11
  75. package/dist/src/hooks/useBorrowData.js.map +1 -1
  76. package/dist/src/hooks/useCreateAccount.d.ts.map +1 -1
  77. package/dist/src/hooks/useCreateAccount.js +3 -3
  78. package/dist/src/hooks/useCreateAccount.js.map +1 -1
  79. package/dist/src/hooks/useGetCurrentAccount.d.ts.map +1 -1
  80. package/dist/src/hooks/useGetCurrentAccount.js +4 -6
  81. package/dist/src/hooks/useGetCurrentAccount.js.map +1 -1
  82. package/dist/src/hooks/useLinkAccount.d.ts.map +1 -1
  83. package/dist/src/hooks/useLinkAccount.js +3 -3
  84. package/dist/src/hooks/useLinkAccount.js.map +1 -1
  85. package/dist/src/hooks/useTokensBalances.d.ts +36 -35
  86. package/dist/src/hooks/useTokensBalances.d.ts.map +1 -1
  87. package/dist/src/hooks/useTokensBalances.js +93 -52
  88. package/dist/src/hooks/useTokensBalances.js.map +1 -1
  89. package/dist/src/hooks/useWalletAccount.d.ts +8 -6
  90. package/dist/src/hooks/useWalletAccount.d.ts.map +1 -1
  91. package/dist/src/hooks/useWalletAccount.js +9 -6
  92. package/dist/src/hooks/useWalletAccount.js.map +1 -1
  93. package/dist/src/lib/contracts/index.d.ts +1 -1
  94. package/dist/src/lib/contracts/index.d.ts.map +1 -1
  95. package/dist/src/lib/contracts/index.js +4 -0
  96. package/dist/src/lib/contracts/index.js.map +1 -1
  97. package/dist/src/provider.d.ts +7 -1
  98. package/dist/src/provider.d.ts.map +1 -1
  99. package/dist/src/provider.js +4 -1
  100. package/dist/src/provider.js.map +1 -1
  101. package/dist/src/utils/assets.d.ts +145 -0
  102. package/dist/src/utils/assets.d.ts.map +1 -0
  103. package/dist/src/utils/assets.js +100 -0
  104. package/dist/src/utils/assets.js.map +1 -0
  105. package/dist/src/utils/assets.test.d.ts +2 -0
  106. package/dist/src/utils/assets.test.d.ts.map +1 -0
  107. package/dist/src/utils/assets.test.js +46 -0
  108. package/dist/src/utils/assets.test.js.map +1 -0
  109. package/dist/src/utils/currency.d.ts +6 -3
  110. package/dist/src/utils/currency.d.ts.map +1 -1
  111. package/dist/src/utils/currency.js +13 -10
  112. package/dist/src/utils/currency.js.map +1 -1
  113. package/dist/src/utils/currency.test.js +44 -2
  114. package/dist/src/utils/currency.test.js.map +1 -1
  115. package/dist/src/utils/numbers.d.ts +13 -53
  116. package/dist/src/utils/numbers.d.ts.map +1 -1
  117. package/dist/src/utils/numbers.js +16 -118
  118. package/dist/src/utils/numbers.js.map +1 -1
  119. package/dist/src/utils/numbers.test.js +24 -142
  120. package/dist/src/utils/numbers.test.js.map +1 -1
  121. package/package.json +2 -1
  122. package/src/components/Dropdown/Content.tsx +3 -48
  123. package/src/components/Dropdown/Dropdown.tsx +7 -58
  124. package/src/components/Dropdown/ListingItem.tsx +155 -59
  125. package/src/components/Dropdown/NestedViewLayout.tsx +32 -20
  126. package/src/components/Dropdown/Receive/Receive.tsx +57 -32
  127. package/src/components/Dropdown/Root/AccountAddressActions.tsx +33 -35
  128. package/src/components/Dropdown/Root/AccountBalance.tsx +54 -16
  129. package/src/components/Dropdown/Root/AccountBtcListing.tsx +52 -0
  130. package/src/components/Dropdown/Root/AccountError.tsx +34 -0
  131. package/src/components/Dropdown/Root/AccountMusdListing.tsx +45 -0
  132. package/src/components/Dropdown/Root/AccountOtherAssets.tsx +63 -46
  133. package/src/components/Dropdown/Root/Root.tsx +28 -98
  134. package/src/components/Dropdown/Root/WalletAddress.tsx +87 -89
  135. package/src/components/Dropdown/Root/WelcomeBlock.tsx +112 -30
  136. package/src/components/Dropdown/SlotNumber.tsx +131 -0
  137. package/src/config.ts +1 -11
  138. package/src/hooks/useAssetsConversionRates.ts +49 -67
  139. package/src/hooks/useAuthenticateWithWallet.ts +7 -5
  140. package/src/hooks/useBorrowData.ts +71 -12
  141. package/src/hooks/useCreateAccount.ts +5 -4
  142. package/src/hooks/useGetCurrentAccount.ts +5 -7
  143. package/src/hooks/useLinkAccount.ts +5 -4
  144. package/src/hooks/useTokensBalances.ts +152 -74
  145. package/src/hooks/useWalletAccount.ts +19 -13
  146. package/src/lib/contracts/index.ts +8 -1
  147. package/src/provider.ts +11 -3
  148. package/src/utils/assets.test.ts +57 -0
  149. package/src/utils/assets.ts +103 -0
  150. package/src/utils/currency.test.ts +76 -2
  151. package/src/utils/currency.ts +20 -15
  152. package/src/utils/numbers.test.ts +29 -180
  153. package/src/utils/numbers.ts +22 -171
  154. package/dist/src/components/Dropdown/Root/AccountAssetItem.d.ts +0 -11
  155. package/dist/src/components/Dropdown/Root/AccountAssetItem.d.ts.map +0 -1
  156. package/dist/src/components/Dropdown/Root/AccountAssetItem.js +0 -9
  157. package/dist/src/components/Dropdown/Root/AccountAssetItem.js.map +0 -1
  158. package/dist/src/hooks/useDropdownData.d.ts +0 -47
  159. package/dist/src/hooks/useDropdownData.d.ts.map +0 -1
  160. package/dist/src/hooks/useDropdownData.js +0 -97
  161. package/dist/src/hooks/useDropdownData.js.map +0 -1
  162. package/dist/src/utils/cryptoAssets.d.ts +0 -44
  163. package/dist/src/utils/cryptoAssets.d.ts.map +0 -1
  164. package/dist/src/utils/cryptoAssets.js +0 -129
  165. package/dist/src/utils/cryptoAssets.js.map +0 -1
  166. package/dist/src/utils/cryptoAssets.test.d.ts +0 -2
  167. package/dist/src/utils/cryptoAssets.test.d.ts.map +0 -1
  168. package/dist/src/utils/cryptoAssets.test.js +0 -67
  169. package/dist/src/utils/cryptoAssets.test.js.map +0 -1
  170. package/src/components/Dropdown/Root/AccountAssetItem.tsx +0 -26
  171. package/src/hooks/useDropdownData.ts +0 -152
  172. package/src/utils/cryptoAssets.test.ts +0 -79
  173. package/src/utils/cryptoAssets.ts +0 -171
@@ -1,15 +1,26 @@
1
- import { useReadContracts } from "wagmi"
2
- import { useCallback, useMemo } from "react"
3
- import { Abi } from "viem"
4
- import { useQueryClient } from "@tanstack/react-query"
5
- import { usePassportContext } from "./usePassportContext"
1
+ import { useConfig } from "wagmi"
2
+ import { Abi, formatUnits } from "viem"
3
+ import {
4
+ useQuery,
5
+ useQueryClient,
6
+ UseQueryOptions,
7
+ } from "@tanstack/react-query"
8
+ import { getBalance, readContracts } from "wagmi/actions"
6
9
  import {
7
10
  mainnetTokenContracts,
8
- testnetTokenContracts,
9
11
  MezoChainToken,
12
+ testnetTokenContracts,
10
13
  } from "../lib/contracts"
11
14
  import useWalletAccount from "./useWalletAccount"
15
+ import {
16
+ getAsset,
17
+ isBitcoinLikeCryptoAsset,
18
+ isTTokenCryptoAsset,
19
+ } from "../utils/assets"
20
+ import { convertToUsd } from "../utils/currency"
12
21
  import { CHAIN_ID } from "../constants"
22
+ import { useAssetsConversionRates } from "./useAssetsConversionRates"
23
+ import { normalizePrecision } from "../utils/numbers"
13
24
 
14
25
  // Wagmi handles typesafety with ABI const assertions. TypeScript doesn't
15
26
  // support importing JSON as const yet so types cannot be inferred from the
@@ -17,7 +28,7 @@ import { CHAIN_ID } from "../constants"
17
28
  // be asserted types from.
18
29
  // Ref: https://wagmi.sh/core/typescript#const-assert-abis-typed-data
19
30
 
20
- const BALANCE_OF_ABI = [
31
+ export const BALANCE_OF_ABI = [
21
32
  {
22
33
  inputs: [
23
34
  {
@@ -53,11 +64,27 @@ const BALANCE_TOKENS: MezoChainToken[] = [
53
64
  "MUSD",
54
65
  ]
55
66
 
56
- type UseMezoChainTokensBalancesOptions<T> = {
67
+ type UseMezoChainTokensBalancesOptions<T extends MezoChainToken[]> = {
57
68
  tokens?: T
58
- queryOptions?: object
69
+ queryOptions?: Omit<
70
+ UseQueryOptions<Record<T[number], TokenBalance>>,
71
+ "queryKey" | "queryFn" | "select" | "enabled"
72
+ >
59
73
  }
60
74
 
75
+ export type TokenBalance = {
76
+ decimals: number
77
+ formatted: string
78
+ symbol: string
79
+ value: bigint
80
+ usd: {
81
+ value: bigint
82
+ formatted: string
83
+ }
84
+ }
85
+
86
+ const TOKEN_BALANCES_QUERY_KEY = "passport.tokenBalances"
87
+
61
88
  /**
62
89
  * Hook to get the balance of a list of tokens for the current account
63
90
  * @param options.tokens The list of tokens to get the balance for. It will
@@ -67,93 +94,150 @@ type UseMezoChainTokensBalancesOptions<T> = {
67
94
  * @returns Tanstack's `useQuery` returnings with balance of tokens for the
68
95
  * current account in form of typesafe object with token names as keys
69
96
  * and balances as values.
70
- * @dev In case of error data fallbacks to `0n`. To determine if an error
71
- * occurred, check the `isError` property.
72
97
  * @example
73
98
  * const mezoTokensBalance = useTokensBalances({
74
99
  * tokens: ["mT", "mxSolvBTC"],
75
100
  * })
76
- * console.log(mezoTokensBalance?.data.mT) // Eg. 0n
77
- * console.log(Object.keys(mezoTokensBalance?.data)) // ["mT", "mxSolvBTC"]
101
+ * // Assuming the status is "success"
102
+ * console.log(mezoTokensBalance.data.mT) // Eg. { value: 0n ... }
103
+ * console.log(Object.keys(mezoTokensBalance.data)) // ["mT", "mxSolvBTC"]
78
104
  */
79
105
  export function useTokensBalances<T extends MezoChainToken[]>(
80
106
  options: UseMezoChainTokensBalancesOptions<T> = {},
81
107
  ) {
82
- const { environment = "mainnet" } = usePassportContext()
108
+ const { tokens = BALANCE_TOKENS, ...restQueryOptions } = options
83
109
 
84
- const { accountAddress } = useWalletAccount()
110
+ const { data: walletAccountData } = useWalletAccount()
85
111
 
86
- const contractsMap = useMemo(() => {
87
- const contracts =
88
- environment === "mainnet" ? mainnetTokenContracts : testnetTokenContracts
112
+ const config = useConfig()
89
113
 
90
- const tokenContracts = Object.fromEntries(
91
- Object.entries(contracts).filter(([key]) =>
92
- BALANCE_TOKENS.includes(key as MezoChainToken),
93
- ),
94
- ) as typeof contracts
114
+ const { data: conversionRatesData } = useAssetsConversionRates()
95
115
 
96
- return tokenContracts
97
- }, [environment])
116
+ return useQuery({
117
+ queryKey: [
118
+ TOKEN_BALANCES_QUERY_KEY,
119
+ walletAccountData?.accountAddress,
120
+ options.tokens,
121
+ ],
122
+ enabled: !!walletAccountData?.accountAddress && !!conversionRatesData,
123
+ queryFn: async () => {
124
+ const isMainnet = config.state.chainId === CHAIN_ID.mainnet
125
+ const contractsMap = isMainnet
126
+ ? mainnetTokenContracts
127
+ : testnetTokenContracts
98
128
 
99
- const { tokens = Object.keys(contractsMap) as T, queryOptions = {} } = options
129
+ const accountAddress = walletAccountData?.accountAddress
100
130
 
101
- const contracts = useMemo(() => {
102
- if (!accountAddress) return []
131
+ if (!accountAddress) {
132
+ throw new Error("Account address is not available.")
133
+ }
103
134
 
104
- return tokens.map((token) => {
105
- const { address } = contractsMap[token]
135
+ const tokenContracts = tokens.map((token) => {
136
+ const { address } = contractsMap[token]
137
+ return {
138
+ address,
139
+ abi: BALANCE_OF_ABI,
140
+ functionName: "balanceOf" as const,
141
+ args: [accountAddress],
142
+ chainId: config.state.chainId,
143
+ }
144
+ })
106
145
 
107
- return {
108
- address,
109
- abi: BALANCE_OF_ABI,
110
- functionName: "balanceOf",
111
- args: [accountAddress],
112
- chainId: CHAIN_ID[environment],
146
+ return Promise.all([
147
+ getBalance(config, { address: accountAddress }),
148
+ readContracts(config, {
149
+ contracts: tokenContracts,
150
+ }),
151
+ ])
152
+ },
153
+ select: (data) => {
154
+ const [btcBalance, tokensBalancesData] = data
155
+ if (!conversionRatesData) {
156
+ throw new Error("Conversion rates data is not available.")
113
157
  }
114
- })
115
- }, [accountAddress, tokens, contractsMap, environment])
116
-
117
- return useReadContracts({
118
- contracts,
119
- query: {
120
- select: (data) =>
121
- data.reduce(
122
- (acc, item) => {
123
- const token = tokens[data.indexOf(item)]
124
-
125
- return {
126
- ...acc,
127
- [token]: item.result ?? 0n,
128
- }
129
- },
130
- {} as Record<T[number], bigint>,
158
+
159
+ const parsedBtcBalance = {
160
+ ...btcBalance,
161
+ symbol: getAsset("BTC").symbol,
162
+ usd: convertToUsd(
163
+ btcBalance.value,
164
+ btcBalance.decimals,
165
+ conversionRatesData.rates.BTC,
166
+ conversionRatesData.decimals,
131
167
  ),
132
- ...queryOptions,
168
+ }
169
+
170
+ const parsedTokensBalances = tokensBalancesData.map((item, index) => {
171
+ const token = tokens[index]
172
+ const { decimals, symbol } = getAsset(token)
173
+
174
+ if (item.status === "failure") {
175
+ throw new Error(
176
+ `Failed to fetch balance of ${token} for ${walletAccountData?.accountAddress}.`,
177
+ )
178
+ }
179
+
180
+ const tokenBalance: Omit<TokenBalance, "usd"> = {
181
+ value: item.result,
182
+ decimals,
183
+ symbol,
184
+ formatted: formatUnits(item.result, decimals),
185
+ }
186
+
187
+ let usd = {
188
+ value: normalizePrecision(
189
+ tokenBalance.value,
190
+ tokenBalance.decimals,
191
+ conversionRatesData.decimals,
192
+ ),
193
+ formatted: formatUnits(tokenBalance.value, tokenBalance.decimals),
194
+ }
195
+ if (isBitcoinLikeCryptoAsset(tokenBalance.symbol)) {
196
+ usd = convertToUsd(
197
+ tokenBalance.value,
198
+ tokenBalance.decimals,
199
+ conversionRatesData.rates.BTC,
200
+ conversionRatesData.decimals,
201
+ )
202
+ }
203
+ if (isTTokenCryptoAsset(tokenBalance.symbol)) {
204
+ usd = convertToUsd(
205
+ tokenBalance.value,
206
+ tokenBalance.decimals,
207
+ conversionRatesData.rates.mT,
208
+ conversionRatesData.decimals,
209
+ )
210
+ }
211
+
212
+ return { ...tokenBalance, usd }
213
+ })
214
+
215
+ return [parsedBtcBalance, ...parsedTokensBalances].reduce(
216
+ (acc, token) => ({
217
+ ...acc,
218
+ [token.symbol]: token,
219
+ }),
220
+ {} as Record<T[number] | "BTC", TokenBalance>,
221
+ )
133
222
  },
223
+ ...restQueryOptions,
134
224
  })
135
225
  }
136
226
 
137
227
  /**
138
228
  * Hook for invalidating current user's token balances. Can be used to
139
229
  * invalidate the balances manually, which forces the data to be re-fetched.
140
- * @param tokens The list of tokens (as string arrays) for which we want to
141
- * invalidate query for.
142
230
  * @returns Function `invalidateTokenBalances` that invalidates token balances
143
231
  * @example
144
- * const { invalidateTokenBalances } = useInvalidateTokensBalances(["mT", "mUSD"])
232
+ * const { invalidateTokenBalances } = useInvalidateTokensBalances()
145
233
  * (...)
146
234
  * await invalidateTokenBalances()
147
235
  */
148
- export function useInvalidateTokensBalances(tokens?: MezoChainToken[]) {
236
+ export function useInvalidateTokensBalances() {
149
237
  const queryClient = useQueryClient()
150
238
 
151
- const { queryKey } = useTokensBalances({ tokens })
152
-
153
- const invalidateTokensBalancesHandler = useCallback(
154
- () => queryClient.invalidateQueries({ queryKey }),
155
- [queryClient, queryKey],
156
- )
239
+ const invalidateTokensBalancesHandler = () =>
240
+ queryClient.invalidateQueries({ queryKey: [TOKEN_BALANCES_QUERY_KEY] })
157
241
 
158
242
  return {
159
243
  invalidateTokensBalances: invalidateTokensBalancesHandler,
@@ -163,23 +247,17 @@ export function useInvalidateTokensBalances(tokens?: MezoChainToken[]) {
163
247
  /**
164
248
  * Hook for resetting current user's token balances. Can be used to reset the
165
249
  * balances manually, which forces the data to be re-fetched.
166
- * @param tokens The list of tokens (as string arrays) for which we want to
167
- * reset query for.
168
250
  * @returns Function `resetTokenBalances` that invalidates token balances
169
251
  * @example
170
- * const { resetTokenBalances } = useResetTokensBalances(["mT", "mUSD"])
252
+ * const { resetTokenBalances } = useResetTokensBalances()
171
253
  * (...)
172
254
  * await resetTokenBalances()
173
255
  */
174
- export function useResetTokensBalances(tokens?: MezoChainToken[]) {
256
+ export function useResetTokensBalances() {
175
257
  const queryClient = useQueryClient()
176
258
 
177
- const { queryKey } = useTokensBalances({ tokens })
178
-
179
- const resetTokenBalancesHandler = useCallback(
180
- () => queryClient.resetQueries({ queryKey }),
181
- [queryClient, queryKey],
182
- )
259
+ const resetTokenBalancesHandler = () =>
260
+ queryClient.resetQueries({ queryKey: [TOKEN_BALANCES_QUERY_KEY] })
183
261
 
184
262
  return {
185
263
  resetTokenBalances: resetTokenBalancesHandler,
@@ -5,14 +5,18 @@ import { Address } from "viem"
5
5
  import { Connector, useAccount } from "wagmi"
6
6
 
7
7
  type UseWalletAccountReturn = {
8
- accountAddress?: Address
9
- walletAddress?: string
10
- isConnected: boolean
11
- networkFamily: "bitcoin" | "evm"
12
- connector?: Connector
13
- chainId?: number
8
+ data: {
9
+ accountAddress?: Address
10
+ walletAddress?: string
11
+ isConnected: boolean
12
+ networkFamily: "bitcoin" | "evm"
13
+ connector?: Connector
14
+ chainId?: number
15
+ }
14
16
  }
15
17
 
18
+ // TODO: Invesitgate race conditions and refactor
19
+
16
20
  export default function useWalletAccount(): UseWalletAccountReturn {
17
21
  const { address: evmAddress, connector, chainId } = useAccount()
18
22
 
@@ -41,11 +45,13 @@ export default function useWalletAccount(): UseWalletAccountReturn {
41
45
  const { address: btcAddress } = btcData || {}
42
46
 
43
47
  return {
44
- accountAddress: evmAddress,
45
- walletAddress: btcAddress ?? evmAddress,
46
- isConnected: networkFamily === "bitcoin" ? !!btcAddress : !!evmAddress,
47
- networkFamily,
48
- connector,
49
- chainId,
50
- } as const
48
+ data: {
49
+ accountAddress: evmAddress,
50
+ walletAddress: btcAddress ?? evmAddress,
51
+ isConnected: networkFamily === "bitcoin" ? !!btcAddress : !!evmAddress,
52
+ networkFamily,
53
+ connector,
54
+ chainId,
55
+ },
56
+ }
51
57
  }
@@ -25,6 +25,8 @@ import xsolvbtcTestnet from "@mezo-org/mezod-contracts/deployments/testnet/mxSol
25
25
  import musdTestnet from "@mezo-org/musd-contracts/deployments/matsnet/MUSD.json"
26
26
  import troveManagerTestnet from "@mezo-org/musd-contracts/deployments/matsnet/TroveManager.json"
27
27
  import borrowerOperationsTestnet from "@mezo-org/musd-contracts/deployments/matsnet/BorrowerOperations.json"
28
+ import priceFeed from "@mezo-org/musd-contracts/deployments/mainnet/PriceFeed.json"
29
+ import priceFeedTestnet from "@mezo-org/musd-contracts/deployments/matsnet/PriceFeed.json"
28
30
 
29
31
  import { Abi, Address } from "viem"
30
32
 
@@ -41,7 +43,10 @@ export type MezoChainToken =
41
43
  | "mxSolvBTC"
42
44
  | "MUSD"
43
45
 
44
- export type MezoBorrowContract = "TroveManager" | "BorrowerOperations"
46
+ export type MezoBorrowContract =
47
+ | "TroveManager"
48
+ | "BorrowerOperations"
49
+ | "PriceFeed"
45
50
 
46
51
  type ContractsMap<K extends string> = Record<
47
52
  K,
@@ -82,11 +87,13 @@ export const mainnetTokenContracts = {
82
87
  export const mainnetBorrowContracts = {
83
88
  TroveManager: troveManagerMainnet,
84
89
  BorrowerOperations: borrowerOperationsMainnet,
90
+ PriceFeed: priceFeed,
85
91
  } as unknown as ContractsMap<MezoBorrowContract>
86
92
 
87
93
  export const testnetBorrowContracts = {
88
94
  TroveManager: troveManagerTestnet,
89
95
  BorrowerOperations: borrowerOperationsTestnet,
96
+ PriceFeed: priceFeedTestnet,
90
97
  } as unknown as ContractsMap<MezoBorrowContract>
91
98
 
92
99
  export { default as priceOracleContract } from "./priceOracle"
package/src/provider.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import { createContext, createElement } from "react"
2
2
  import { AuthApiClient, PortalApiClient } from "./api"
3
+ import { ONE_SECOND_MS } from "./utils/time"
3
4
 
4
5
  export interface PassportContextValue {
5
6
  authApiClient: AuthApiClient
6
7
  portalApiClient: PortalApiClient
7
8
  environment?: Environment
9
+ accountDataRefetchInterval: number
10
+ nativeBalanceRefetchInterval: number
8
11
  }
9
12
 
10
13
  export const PassportContext = createContext<PassportContextValue | undefined>(
@@ -15,12 +18,13 @@ type Environment = "mainnet" | "testnet"
15
18
 
16
19
  type PassportProviderProps = {
17
20
  children: React.ReactNode
18
- // eslint-disable-next-line react/require-default-props
19
21
  environment?: Environment
20
- // eslint-disable-next-line react/require-default-props
21
22
  authApiUrl?: string
22
- // eslint-disable-next-line react/require-default-props
23
23
  portalApiUrl?: string
24
+ /** Time in milliseconds after which account data (like mats or mezo id) in dropdown should be re-fetched. Default is 90000 (90 secs) */
25
+ accountDataRefetchInterval?: number
26
+ /** Time in milliseconds after which native balance in dropdown should be re-fetched. Default is 90000 (90 secs) */
27
+ nativeBalanceRefetchInterval?: number
24
28
  }
25
29
 
26
30
  export function PassportProvider({
@@ -28,6 +32,8 @@ export function PassportProvider({
28
32
  authApiUrl,
29
33
  portalApiUrl,
30
34
  children,
35
+ accountDataRefetchInterval = 90 * ONE_SECOND_MS,
36
+ nativeBalanceRefetchInterval = 90 * ONE_SECOND_MS,
31
37
  }: PassportProviderProps) {
32
38
  if (environment && !["mainnet", "testnet"].includes(environment)) {
33
39
  throw new Error("Wrong environment passed to PassportProvider.")
@@ -43,6 +49,8 @@ export function PassportProvider({
43
49
  portalApiUrl,
44
50
  ),
45
51
  environment,
52
+ accountDataRefetchInterval,
53
+ nativeBalanceRefetchInterval,
46
54
  },
47
55
  },
48
56
  children,
@@ -0,0 +1,57 @@
1
+ import {
2
+ getAsset,
3
+ isBitcoinLikeCryptoAsset,
4
+ isUsdLikeCryptoAsset,
5
+ isTTokenCryptoAsset,
6
+ } from "./assets"
7
+
8
+ describe("getAsset", () => {
9
+ it("should return correct asset data", () => {
10
+ const asset = getAsset("BTC")
11
+ expect(asset).toEqual({
12
+ name: "Bitcoin",
13
+ symbol: "BTC",
14
+ decimals: 18,
15
+ })
16
+ })
17
+ })
18
+
19
+ describe("isBitcoinLikeCryptoAsset", () => {
20
+ it('should return true for keys containing "btc"', () => {
21
+ expect(isBitcoinLikeCryptoAsset("BTC")).toBe(true)
22
+ expect(isBitcoinLikeCryptoAsset("mFBTC")).toBe(true)
23
+ expect(isBitcoinLikeCryptoAsset("mcbBTC")).toBe(true)
24
+ expect(isBitcoinLikeCryptoAsset("mxSolvBTC")).toBe(true)
25
+ })
26
+
27
+ it("should return false for non-Bitcoin assets", () => {
28
+ expect(isBitcoinLikeCryptoAsset("ETH")).toBe(false)
29
+ expect(isBitcoinLikeCryptoAsset("mUSDC")).toBe(false)
30
+ })
31
+ })
32
+
33
+ describe("isUsdLikeCryptoAsset", () => {
34
+ it('should return true for keys containing "usd" or "dai"', () => {
35
+ expect(isUsdLikeCryptoAsset("mUSDC")).toBe(true)
36
+ expect(isUsdLikeCryptoAsset("mUSDT")).toBe(true)
37
+ expect(isUsdLikeCryptoAsset("mUSDe")).toBe(true)
38
+ expect(isUsdLikeCryptoAsset("mDAI")).toBe(true)
39
+ })
40
+
41
+ it("should return false for other tokens", () => {
42
+ expect(isUsdLikeCryptoAsset("BTC")).toBe(false)
43
+ expect(isUsdLikeCryptoAsset("mT")).toBe(false)
44
+ })
45
+ })
46
+
47
+ describe("isTTokenCryptoAsset", () => {
48
+ it('should return true for keys like "mT" or "t"', () => {
49
+ expect(isTTokenCryptoAsset("mT")).toBe(true)
50
+ expect(isTTokenCryptoAsset("T")).toBe(true)
51
+ })
52
+
53
+ it("should return false for other tokens", () => {
54
+ expect(isTTokenCryptoAsset("BTC")).toBe(false)
55
+ expect(isTTokenCryptoAsset("mUSDT")).toBe(false)
56
+ })
57
+ })
@@ -0,0 +1,103 @@
1
+ const ASSETS = {
2
+ BTC: {
3
+ name: "Bitcoin",
4
+ symbol: "BTC",
5
+ decimals: 18,
6
+ },
7
+ ETH: {
8
+ name: "Ethereum",
9
+ symbol: "ETH",
10
+ decimals: 18,
11
+ },
12
+ MUSD: {
13
+ name: "MUSD",
14
+ symbol: "MUSD",
15
+ decimals: 18,
16
+ },
17
+ mDAI: {
18
+ name: "Mezo Dai Stablecoin",
19
+ symbol: "mDAI",
20
+ decimals: 18,
21
+ },
22
+ mFBTC: {
23
+ name: "Mezo Fire Bitcoin",
24
+ symbol: "mFBTC",
25
+ decimals: 8,
26
+ },
27
+ mcbBTC: {
28
+ name: "Mezo Coinbase Wrapped BTC",
29
+ symbol: "mcbBTC",
30
+ decimals: 8,
31
+ },
32
+ mSolvBTC: {
33
+ name: "Mezo SolvBTC",
34
+ symbol: "mSolvBTC",
35
+ decimals: 18,
36
+ },
37
+ mswBTC: {
38
+ name: "Mezo swBTC",
39
+ symbol: "mswBTC",
40
+ decimals: 8,
41
+ },
42
+ mT: {
43
+ name: "Mezo Threshold Network Token",
44
+ symbol: "mT",
45
+ decimals: 18,
46
+ },
47
+ mUSDC: {
48
+ name: "Mezo Circle USDC",
49
+ symbol: "mUSDC",
50
+ decimals: 6,
51
+ },
52
+ mUSDe: {
53
+ name: "Mezo Ethena USDe",
54
+ symbol: "mUSDe",
55
+ decimals: 18,
56
+ },
57
+ mUSDT: {
58
+ name: "Mezo Tether USDe",
59
+ symbol: "mUSDT",
60
+ decimals: 6,
61
+ },
62
+ mxSolvBTC: {
63
+ name: "Mezo xSolvBTC",
64
+ symbol: "mxSolvBTC",
65
+ decimals: 18,
66
+ },
67
+ }
68
+
69
+ /**
70
+ * Gets details of given crypto asset
71
+ * @param key The key of crypto asset
72
+ * @returns The crypto asset details
73
+ */
74
+ export function getAsset(key: keyof typeof ASSETS) {
75
+ return ASSETS[key]
76
+ }
77
+
78
+ /**
79
+ * Checks if given crypto asset is Bitcoin-like
80
+ * @param key The key of crypto asset
81
+ * @returns True if crypto asset is Bitcoin-like
82
+ */
83
+ export function isBitcoinLikeCryptoAsset(key: string) {
84
+ return /(btc)/i.test(key)
85
+ }
86
+
87
+ /**
88
+ * Checks if given crypto asset is USD-like
89
+ * @param key The key of crypto asset
90
+ * @returns True if crypto asset is USD-like
91
+ */
92
+ export function isUsdLikeCryptoAsset(key: string) {
93
+ return /(usd|dai)/i.test(key)
94
+ }
95
+
96
+ /**
97
+ * Checks if given crypto asset is T token
98
+ * @param key The key of crypto asset
99
+ * @returns True if crypto asset is T token
100
+ */
101
+ export function isTTokenCryptoAsset(key: string) {
102
+ return /^(mt|t)$/i.test(key)
103
+ }
@@ -1,4 +1,4 @@
1
- import { formatCurrency, formatUsd } from "./currency"
1
+ import { convertToUsd, formatCurrency, formatUsd } from "./currency"
2
2
 
3
3
  describe("formatCurrency", () => {
4
4
  it("formats a number as currency with default options", () => {
@@ -37,4 +37,78 @@ describe("formatUsd", () => {
37
37
  })
38
38
  })
39
39
 
40
- // TODO: Add tests for convertToUsd function
40
+ describe("convertToUsd", () => {
41
+ it("converts 1 BTC (8 decimals) with $30,000 rate (6 decimals)", () => {
42
+ const assetAmount = 1_00000000n // 1 BTC
43
+ const assetDecimals = 8
44
+ const conversionRate = 30_000_000000n // $30,000 in 6 decimals
45
+ const conversionRateDecimals = 6
46
+
47
+ const result = convertToUsd(
48
+ assetAmount,
49
+ assetDecimals,
50
+ conversionRate,
51
+ conversionRateDecimals,
52
+ )
53
+
54
+ expect(result.value).toBe(30_000_000000n)
55
+ expect(result.formatted).toBe("30000")
56
+ })
57
+
58
+ it("converts 0.5 BTC correctly", () => {
59
+ const assetAmount = 50_000000n // 0.5 BTC
60
+ const assetDecimals = 8
61
+ const conversionRate = 40_000_000000n // $40,000
62
+ const conversionRateDecimals = 6
63
+
64
+ const result = convertToUsd(
65
+ assetAmount,
66
+ assetDecimals,
67
+ conversionRate,
68
+ conversionRateDecimals,
69
+ )
70
+
71
+ expect(result.value).toBe(20_000_000000n)
72
+ expect(result.formatted).toBe("20000")
73
+ })
74
+
75
+ it("converts 1 ETH (18 decimals) with $2,000 rate (6 decimals)", () => {
76
+ const assetAmount = 1_000000000000000000n // 1 ETH
77
+ const assetDecimals = 18
78
+ const conversionRate = 2_000_000000n
79
+ const conversionRateDecimals = 6
80
+
81
+ const result = convertToUsd(
82
+ assetAmount,
83
+ assetDecimals,
84
+ conversionRate,
85
+ conversionRateDecimals,
86
+ )
87
+
88
+ expect(result.value).toBe(2_000_000000n)
89
+ expect(result.formatted).toBe("2000")
90
+ })
91
+
92
+ it("handles zero amount correctly", () => {
93
+ const result = convertToUsd(0n, 18, 999_999999n, 6)
94
+ expect(result.value).toBe(0n)
95
+ expect(result.formatted).toBe("0")
96
+ })
97
+
98
+ it("handles assets with fewer decimals than conversion rate", () => {
99
+ const assetAmount = 100n
100
+ const assetDecimals = 2
101
+ const conversionRate = 1_500_000000n // $1500
102
+ const conversionRateDecimals = 6
103
+
104
+ const result = convertToUsd(
105
+ assetAmount,
106
+ assetDecimals,
107
+ conversionRate,
108
+ conversionRateDecimals,
109
+ )
110
+
111
+ expect(result.value).toBe(1_500_000000n)
112
+ expect(result.formatted).toBe("1500")
113
+ })
114
+ })