@mezo-org/passport 0.4.0-dev.81 → 0.4.0-dev.83

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 (187) hide show
  1. package/dist/src/api/auth.d.ts +1 -1
  2. package/dist/src/api/auth.d.ts.map +1 -1
  3. package/dist/src/components/Dropdown/Content.d.ts +0 -15
  4. package/dist/src/components/Dropdown/Content.d.ts.map +1 -1
  5. package/dist/src/components/Dropdown/Content.js +3 -3
  6. package/dist/src/components/Dropdown/Content.js.map +1 -1
  7. package/dist/src/components/Dropdown/Dropdown.d.ts +0 -4
  8. package/dist/src/components/Dropdown/Dropdown.d.ts.map +1 -1
  9. package/dist/src/components/Dropdown/Dropdown.js +10 -33
  10. package/dist/src/components/Dropdown/Dropdown.js.map +1 -1
  11. package/dist/src/components/Dropdown/ListingItem.d.ts +8 -7
  12. package/dist/src/components/Dropdown/ListingItem.d.ts.map +1 -1
  13. package/dist/src/components/Dropdown/ListingItem.js +36 -28
  14. package/dist/src/components/Dropdown/ListingItem.js.map +1 -1
  15. package/dist/src/components/Dropdown/NestedViewLayout.d.ts +2 -1
  16. package/dist/src/components/Dropdown/NestedViewLayout.d.ts.map +1 -1
  17. package/dist/src/components/Dropdown/NestedViewLayout.js +13 -15
  18. package/dist/src/components/Dropdown/NestedViewLayout.js.map +1 -1
  19. package/dist/src/components/Dropdown/Receive/Receive.d.ts +1 -4
  20. package/dist/src/components/Dropdown/Receive/Receive.d.ts.map +1 -1
  21. package/dist/src/components/Dropdown/Receive/Receive.js +36 -19
  22. package/dist/src/components/Dropdown/Receive/Receive.js.map +1 -1
  23. package/dist/src/components/Dropdown/Root/AccountAddressActions.d.ts +2 -5
  24. package/dist/src/components/Dropdown/Root/AccountAddressActions.d.ts.map +1 -1
  25. package/dist/src/components/Dropdown/Root/AccountAddressActions.js +28 -12
  26. package/dist/src/components/Dropdown/Root/AccountAddressActions.js.map +1 -1
  27. package/dist/src/components/Dropdown/Root/AccountBalance.d.ts +2 -4
  28. package/dist/src/components/Dropdown/Root/AccountBalance.d.ts.map +1 -1
  29. package/dist/src/components/Dropdown/Root/AccountBalance.js +24 -8
  30. package/dist/src/components/Dropdown/Root/AccountBalance.js.map +1 -1
  31. package/dist/src/components/Dropdown/Root/AccountBtcListing.d.ts +6 -0
  32. package/dist/src/components/Dropdown/Root/AccountBtcListing.d.ts.map +1 -0
  33. package/dist/src/components/Dropdown/Root/AccountBtcListing.js +27 -0
  34. package/dist/src/components/Dropdown/Root/AccountBtcListing.js.map +1 -0
  35. package/dist/src/components/Dropdown/Root/AccountError.d.ts +8 -0
  36. package/dist/src/components/Dropdown/Root/AccountError.d.ts.map +1 -0
  37. package/dist/src/components/Dropdown/Root/AccountError.js +17 -0
  38. package/dist/src/components/Dropdown/Root/AccountError.js.map +1 -0
  39. package/dist/src/components/Dropdown/Root/AccountMusdListing.d.ts +4 -0
  40. package/dist/src/components/Dropdown/Root/AccountMusdListing.d.ts.map +1 -0
  41. package/dist/src/components/Dropdown/Root/AccountMusdListing.js +21 -0
  42. package/dist/src/components/Dropdown/Root/AccountMusdListing.js.map +1 -0
  43. package/dist/src/components/Dropdown/Root/AccountOtherAssets.d.ts +2 -3
  44. package/dist/src/components/Dropdown/Root/AccountOtherAssets.d.ts.map +1 -1
  45. package/dist/src/components/Dropdown/Root/AccountOtherAssets.js +34 -39
  46. package/dist/src/components/Dropdown/Root/AccountOtherAssets.js.map +1 -1
  47. package/dist/src/components/Dropdown/Root/Root.d.ts +0 -15
  48. package/dist/src/components/Dropdown/Root/Root.d.ts.map +1 -1
  49. package/dist/src/components/Dropdown/Root/Root.js +22 -34
  50. package/dist/src/components/Dropdown/Root/Root.js.map +1 -1
  51. package/dist/src/components/Dropdown/Root/WalletAddress.d.ts +2 -6
  52. package/dist/src/components/Dropdown/Root/WalletAddress.d.ts.map +1 -1
  53. package/dist/src/components/Dropdown/Root/WalletAddress.js +43 -34
  54. package/dist/src/components/Dropdown/Root/WalletAddress.js.map +1 -1
  55. package/dist/src/components/Dropdown/Root/WelcomeBlock.d.ts +2 -4
  56. package/dist/src/components/Dropdown/Root/WelcomeBlock.d.ts.map +1 -1
  57. package/dist/src/components/Dropdown/Root/WelcomeBlock.js +60 -16
  58. package/dist/src/components/Dropdown/Root/WelcomeBlock.js.map +1 -1
  59. package/dist/src/components/Dropdown/SlotNumber.d.ts +19 -0
  60. package/dist/src/components/Dropdown/SlotNumber.d.ts.map +1 -0
  61. package/dist/src/components/Dropdown/SlotNumber.js +67 -0
  62. package/dist/src/components/Dropdown/SlotNumber.js.map +1 -0
  63. package/dist/src/config.d.ts +1 -11
  64. package/dist/src/config.d.ts.map +1 -1
  65. package/dist/src/config.js +3 -40
  66. package/dist/src/config.js.map +1 -1
  67. package/dist/src/constants.d.ts +0 -2
  68. package/dist/src/constants.d.ts.map +1 -1
  69. package/dist/src/constants.js +0 -2
  70. package/dist/src/constants.js.map +1 -1
  71. package/dist/src/hooks/useAssetsConversionRates.d.ts +8 -13
  72. package/dist/src/hooks/useAssetsConversionRates.d.ts.map +1 -1
  73. package/dist/src/hooks/useAssetsConversionRates.js +44 -67
  74. package/dist/src/hooks/useAssetsConversionRates.js.map +1 -1
  75. package/dist/src/hooks/useAuthenticateWithWallet.d.ts.map +1 -1
  76. package/dist/src/hooks/useAuthenticateWithWallet.js +1 -1
  77. package/dist/src/hooks/useAuthenticateWithWallet.js.map +1 -1
  78. package/dist/src/hooks/useBorrowData.d.ts +31 -5
  79. package/dist/src/hooks/useBorrowData.d.ts.map +1 -1
  80. package/dist/src/hooks/useBorrowData.js +53 -11
  81. package/dist/src/hooks/useBorrowData.js.map +1 -1
  82. package/dist/src/hooks/useCreateAccount.d.ts.map +1 -1
  83. package/dist/src/hooks/useCreateAccount.js +3 -3
  84. package/dist/src/hooks/useCreateAccount.js.map +1 -1
  85. package/dist/src/hooks/useGetCurrentAccount.d.ts +2 -2
  86. package/dist/src/hooks/useGetCurrentAccount.d.ts.map +1 -1
  87. package/dist/src/hooks/useGetCurrentAccount.js +4 -6
  88. package/dist/src/hooks/useGetCurrentAccount.js.map +1 -1
  89. package/dist/src/hooks/useLinkAccount.d.ts.map +1 -1
  90. package/dist/src/hooks/useLinkAccount.js +3 -3
  91. package/dist/src/hooks/useLinkAccount.js.map +1 -1
  92. package/dist/src/hooks/useTokensBalances.d.ts +36 -35
  93. package/dist/src/hooks/useTokensBalances.d.ts.map +1 -1
  94. package/dist/src/hooks/useTokensBalances.js +93 -52
  95. package/dist/src/hooks/useTokensBalances.js.map +1 -1
  96. package/dist/src/hooks/useWalletAccount.d.ts +8 -10
  97. package/dist/src/hooks/useWalletAccount.d.ts.map +1 -1
  98. package/dist/src/hooks/useWalletAccount.js +22 -19
  99. package/dist/src/hooks/useWalletAccount.js.map +1 -1
  100. package/dist/src/index.d.ts +1 -1
  101. package/dist/src/index.d.ts.map +1 -1
  102. package/dist/src/index.js +1 -1
  103. package/dist/src/index.js.map +1 -1
  104. package/dist/src/lib/contracts/index.d.ts +1 -1
  105. package/dist/src/lib/contracts/index.d.ts.map +1 -1
  106. package/dist/src/lib/contracts/index.js +4 -0
  107. package/dist/src/lib/contracts/index.js.map +1 -1
  108. package/dist/src/provider.d.ts +7 -1
  109. package/dist/src/provider.d.ts.map +1 -1
  110. package/dist/src/provider.js +4 -1
  111. package/dist/src/provider.js.map +1 -1
  112. package/dist/src/utils/assets.d.ts +145 -0
  113. package/dist/src/utils/assets.d.ts.map +1 -0
  114. package/dist/src/utils/assets.js +100 -0
  115. package/dist/src/utils/assets.js.map +1 -0
  116. package/dist/src/utils/assets.test.d.ts +2 -0
  117. package/dist/src/utils/assets.test.d.ts.map +1 -0
  118. package/dist/src/utils/assets.test.js +46 -0
  119. package/dist/src/utils/assets.test.js.map +1 -0
  120. package/dist/src/utils/currency.d.ts +6 -3
  121. package/dist/src/utils/currency.d.ts.map +1 -1
  122. package/dist/src/utils/currency.js +13 -10
  123. package/dist/src/utils/currency.js.map +1 -1
  124. package/dist/src/utils/currency.test.js +44 -2
  125. package/dist/src/utils/currency.test.js.map +1 -1
  126. package/dist/src/utils/numbers.d.ts +13 -53
  127. package/dist/src/utils/numbers.d.ts.map +1 -1
  128. package/dist/src/utils/numbers.js +16 -118
  129. package/dist/src/utils/numbers.js.map +1 -1
  130. package/dist/src/utils/numbers.test.js +24 -142
  131. package/dist/src/utils/numbers.test.js.map +1 -1
  132. package/package.json +2 -1
  133. package/src/api/auth.ts +1 -1
  134. package/src/components/Dropdown/Content.tsx +3 -48
  135. package/src/components/Dropdown/Dropdown.tsx +7 -55
  136. package/src/components/Dropdown/ListingItem.tsx +155 -59
  137. package/src/components/Dropdown/NestedViewLayout.tsx +32 -20
  138. package/src/components/Dropdown/Receive/Receive.tsx +69 -32
  139. package/src/components/Dropdown/Root/AccountAddressActions.tsx +64 -35
  140. package/src/components/Dropdown/Root/AccountBalance.tsx +54 -16
  141. package/src/components/Dropdown/Root/AccountBtcListing.tsx +52 -0
  142. package/src/components/Dropdown/Root/AccountError.tsx +34 -0
  143. package/src/components/Dropdown/Root/AccountMusdListing.tsx +45 -0
  144. package/src/components/Dropdown/Root/AccountOtherAssets.tsx +63 -46
  145. package/src/components/Dropdown/Root/Root.tsx +28 -98
  146. package/src/components/Dropdown/Root/WalletAddress.tsx +95 -89
  147. package/src/components/Dropdown/Root/WelcomeBlock.tsx +109 -29
  148. package/src/components/Dropdown/SlotNumber.tsx +131 -0
  149. package/src/config.ts +3 -59
  150. package/src/constants.ts +0 -6
  151. package/src/hooks/useAssetsConversionRates.ts +49 -67
  152. package/src/hooks/useAuthenticateWithWallet.ts +7 -5
  153. package/src/hooks/useBorrowData.ts +71 -12
  154. package/src/hooks/useCreateAccount.ts +5 -4
  155. package/src/hooks/useGetCurrentAccount.ts +5 -7
  156. package/src/hooks/useLinkAccount.ts +5 -4
  157. package/src/hooks/useTokensBalances.ts +152 -74
  158. package/src/hooks/useWalletAccount.ts +27 -36
  159. package/src/index.ts +0 -1
  160. package/src/lib/contracts/index.ts +8 -1
  161. package/src/provider.ts +11 -3
  162. package/src/utils/assets.test.ts +57 -0
  163. package/src/utils/assets.ts +103 -0
  164. package/src/utils/currency.test.ts +76 -2
  165. package/src/utils/currency.ts +20 -15
  166. package/src/utils/numbers.test.ts +29 -180
  167. package/src/utils/numbers.ts +22 -171
  168. package/dist/src/components/Dropdown/Root/AccountAssetItem.d.ts +0 -11
  169. package/dist/src/components/Dropdown/Root/AccountAssetItem.d.ts.map +0 -1
  170. package/dist/src/components/Dropdown/Root/AccountAssetItem.js +0 -9
  171. package/dist/src/components/Dropdown/Root/AccountAssetItem.js.map +0 -1
  172. package/dist/src/hooks/useDropdownData.d.ts +0 -47
  173. package/dist/src/hooks/useDropdownData.d.ts.map +0 -1
  174. package/dist/src/hooks/useDropdownData.js +0 -97
  175. package/dist/src/hooks/useDropdownData.js.map +0 -1
  176. package/dist/src/utils/cryptoAssets.d.ts +0 -44
  177. package/dist/src/utils/cryptoAssets.d.ts.map +0 -1
  178. package/dist/src/utils/cryptoAssets.js +0 -129
  179. package/dist/src/utils/cryptoAssets.js.map +0 -1
  180. package/dist/src/utils/cryptoAssets.test.d.ts +0 -2
  181. package/dist/src/utils/cryptoAssets.test.d.ts.map +0 -1
  182. package/dist/src/utils/cryptoAssets.test.js +0 -67
  183. package/dist/src/utils/cryptoAssets.test.js.map +0 -1
  184. package/src/components/Dropdown/Root/AccountAssetItem.tsx +0 -26
  185. package/src/hooks/useDropdownData.ts +0 -152
  186. package/src/utils/cryptoAssets.test.ts +0 -79
  187. package/src/utils/cryptoAssets.ts +0 -171
@@ -1,6 +1,7 @@
1
- import { useAccount, useReadContracts } from "wagmi"
1
+ import { useReadContracts } from "wagmi"
2
2
  import { useCallback, useMemo } from "react"
3
3
  import { useQueryClient } from "@tanstack/react-query"
4
+ import { formatUnits } from "viem"
4
5
  import { ONE_MINUTE_MS } from "../utils/time"
5
6
  import {
6
7
  mainnetBorrowContracts,
@@ -8,7 +9,12 @@ import {
8
9
  } from "../lib/contracts"
9
10
  import { usePassportContext } from "./usePassportContext"
10
11
  import { CHAIN_ID } from "../constants"
11
- import { bigIntMax } from "../utils/numbers"
12
+ import { bigIntMax, normalizePrecision } from "../utils/numbers"
13
+ import useWalletAccount from "./useWalletAccount"
14
+ import { getAsset } from "../utils/assets"
15
+ import { convertToUsd } from "../utils/currency"
16
+
17
+ const DEBT_AND_COLL_PRECISION = 18
12
18
 
13
19
  // Wagmi handles typesafety with ABI const assertions. TypeScript doesn't
14
20
  // support importing JSON as const yet so types cannot be inferred from the
@@ -79,6 +85,22 @@ const BORROWER_OPERATIONS_ABI = [
79
85
  },
80
86
  ] as const
81
87
 
88
+ const PRICE_FEED_ABI = [
89
+ {
90
+ inputs: [],
91
+ name: "fetchPrice",
92
+ outputs: [
93
+ {
94
+ internalType: "uint256",
95
+ name: "",
96
+ type: "uint256",
97
+ },
98
+ ],
99
+ stateMutability: "view",
100
+ type: "function",
101
+ },
102
+ ] as const
103
+
82
104
  /**
83
105
  * Query hook for getting borrow data. Returns collateral and trove debt for the
84
106
  * connected account, based on it's evm address.
@@ -86,18 +108,20 @@ const BORROWER_OPERATIONS_ABI = [
86
108
  */
87
109
  export function useBorrowData(queryOptions = {}) {
88
110
  const { environment = "mainnet" } = usePassportContext()
89
- const { address } = useAccount()
111
+ const { data: walletAccountData } = useWalletAccount()
90
112
 
91
113
  const contractAddress = useMemo(() => {
92
114
  if (environment === "mainnet") {
93
115
  return {
94
116
  troveManager: mainnetBorrowContracts.TroveManager.address,
95
117
  borrowerOperations: mainnetBorrowContracts.BorrowerOperations.address,
118
+ priceFeed: mainnetBorrowContracts.PriceFeed.address,
96
119
  }
97
120
  }
98
121
  return {
99
122
  troveManager: testnetBorrowContracts.TroveManager.address,
100
123
  borrowerOperations: testnetBorrowContracts.BorrowerOperations.address,
124
+ priceFeed: testnetBorrowContracts.PriceFeed.address,
101
125
  }
102
126
  }, [environment])
103
127
 
@@ -109,36 +133,71 @@ export function useBorrowData(queryOptions = {}) {
109
133
  abi: TROVE_MANAGER_ABI,
110
134
  address: contractAddress.troveManager,
111
135
  functionName: "getEntireDebtAndColl",
112
- args: [address || "0x"],
136
+ args: walletAccountData
137
+ ? [walletAccountData.accountAddress]
138
+ : undefined,
113
139
  chainId,
114
140
  },
115
141
  {
116
142
  abi: BORROWER_OPERATIONS_ABI,
117
143
  address: contractAddress.borrowerOperations,
118
144
  functionName: "MUSD_GAS_COMPENSATION",
119
- args: [],
145
+ chainId,
146
+ },
147
+ {
148
+ abi: PRICE_FEED_ABI,
149
+ address: contractAddress.priceFeed,
150
+ functionName: "fetchPrice",
120
151
  chainId,
121
152
  },
122
153
  ],
123
154
  query: {
124
- enabled: !!address,
155
+ enabled: !!walletAccountData,
125
156
  staleTime: 5 * ONE_MINUTE_MS,
126
157
  retry: 1,
127
158
  select: (data) => {
128
- if (!data || data.some((item) => !item.result)) return undefined
159
+ if (!data || data.some((item) => !item.result))
160
+ throw new Error("No borrow data available")
129
161
 
130
- const [collateral, principal, interest] = data[0].result!
162
+ const [rawCollateral, principal, interest] = data[0].result!
131
163
  const gasCompensation = data[1].result!
164
+ const collateralPrice = data[2].result!
165
+
166
+ const btcDetails = getAsset("BTC")
167
+
168
+ const collateral = {
169
+ value: rawCollateral,
170
+ decimals: btcDetails.decimals,
171
+ symbol: btcDetails.symbol,
172
+ formatted: formatUnits(rawCollateral, DEBT_AND_COLL_PRECISION),
173
+ usd: convertToUsd(
174
+ rawCollateral,
175
+ DEBT_AND_COLL_PRECISION,
176
+ collateralPrice,
177
+ DEBT_AND_COLL_PRECISION,
178
+ ),
179
+ }
132
180
 
133
- const troveDebt = bigIntMax(
134
- principal + interest - gasCompensation,
181
+ const debtInUsdValue = bigIntMax(
182
+ normalizePrecision(
183
+ principal + interest - gasCompensation,
184
+ DEBT_AND_COLL_PRECISION,
185
+ ),
135
186
  0n, // Ensure that debt is not negative
136
187
  )
188
+ const formattedDebtInUsd = formatUnits(
189
+ debtInUsdValue,
190
+ DEBT_AND_COLL_PRECISION,
191
+ )
192
+
193
+ const debtInUsd = {
194
+ value: debtInUsdValue,
195
+ formatted: formattedDebtInUsd,
196
+ }
137
197
 
138
198
  return {
139
199
  collateral,
140
- // Principal includes gas compensation value which is not
141
- troveDebt,
200
+ debtInUsd,
142
201
  }
143
202
  },
144
203
  ...queryOptions,
@@ -18,7 +18,7 @@ export function useCreateAccount(
18
18
  ) {
19
19
  const queryClient = useQueryClient()
20
20
  const authApiClient = useAuthApiClient()
21
- const { connector } = useWalletAccount()
21
+ const walletAccount = useWalletAccount()
22
22
 
23
23
  const { onSuccess: customOnSuccess, ...restMutationOptions } = mutationOptions
24
24
 
@@ -27,12 +27,13 @@ export function useCreateAccount(
27
27
  createAccountMutationFnParameters: CreateAccountRequest,
28
28
  ) => {
29
29
  if (createAccountMutationFnParameters.type === "wallet") {
30
- if (!connector) {
30
+ if (!walletAccount.data?.connector) {
31
31
  throw new Error("Connector not defined.")
32
32
  }
33
33
 
34
- const bitcoinPublicKey =
35
- await getBitcoinPublicKeyFromConnector(connector)
34
+ const bitcoinPublicKey = await getBitcoinPublicKeyFromConnector(
35
+ walletAccount.data.connector,
36
+ )
36
37
 
37
38
  // Creating bitcoin mezo account
38
39
  if (bitcoinPublicKey) {
@@ -24,16 +24,15 @@ export function useGetCurrentAccount(
24
24
  queryKey: [QUERY_KEYS.ACCOUNT, QUERY_KEYS.CURRENT],
25
25
  queryFn: async () => {
26
26
  const currentAccount = await authApiClient.getCurrentAccount()
27
+ if (!currentAccount) {
28
+ throw new Error("No current account found")
29
+ }
30
+
27
31
  const linkedWallets = currentAccount?.linkedAccounts?.filter(
28
32
  (account) => account.type === "wallet",
29
33
  )
30
34
  if (!linkedWallets || linkedWallets.length === 0) {
31
- return {
32
- ...currentAccount,
33
- mats: {
34
- totalMats: 0,
35
- },
36
- }
35
+ throw new Error("No linked wallets found for the current account")
37
36
  }
38
37
 
39
38
  const addresses = linkedWallets.map(
@@ -42,7 +41,6 @@ export function useGetCurrentAccount(
42
41
  const mats = await Promise.all(
43
42
  addresses.map((address) => portalApiClient.getPortalMats(address)),
44
43
  )
45
-
46
44
  const totalMats = mats.reduce(
47
45
  (sumMats, currentMats) => sumMats + currentMats.totalMats,
48
46
  0,
@@ -26,7 +26,7 @@ export function useLinkAccount(
26
26
  ) {
27
27
  const queryClient = useQueryClient()
28
28
  const authApiClient = useAuthApiClient()
29
- const { connector } = useWalletAccount()
29
+ const walletAccount = useWalletAccount()
30
30
 
31
31
  const { onSuccess: customOnSuccess, ...restMutationOptions } = mutationOptions
32
32
 
@@ -35,12 +35,13 @@ export function useLinkAccount(
35
35
  linkAccountMutationFnParameters: LinkAccountMutationFnParameters,
36
36
  ) => {
37
37
  if (linkAccountMutationFnParameters.type === "wallet") {
38
- if (!connector) {
38
+ if (!walletAccount.data?.connector) {
39
39
  throw new Error("Connector not defined.")
40
40
  }
41
41
 
42
- const bitcoinPublicKey =
43
- await getBitcoinPublicKeyFromConnector(connector)
42
+ const bitcoinPublicKey = await getBitcoinPublicKeyFromConnector(
43
+ walletAccount.data.connector,
44
+ )
44
45
 
45
46
  // Linking bitcoin account
46
47
  if (bitcoinPublicKey) {
@@ -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,
@@ -1,51 +1,42 @@
1
1
  import { OrangeKitConnector } from "@mezo-org/orangekit"
2
2
  import { useQuery } from "@tanstack/react-query"
3
- import { useMemo } from "react"
4
- import { Address } from "viem"
5
3
  import { Connector, useAccount } from "wagmi"
6
4
 
7
- type UseWalletAccountReturn = {
8
- accountAddress?: Address
9
- walletAddress?: string
10
- isConnected: boolean
11
- networkFamily: "bitcoin" | "evm"
12
- connector?: Connector
13
- chainId?: number
14
- }
5
+ export const WALLET_ACCOUNT_QUERY_KEY = "passport.walletAccount"
6
+
7
+ const getBitcoinProviderFromConnector = (connector: Connector) =>
8
+ connector.type === "orangekit"
9
+ ? (connector as unknown as OrangeKitConnector)?.getBitcoinProvider()
10
+ : undefined
15
11
 
16
- export default function useWalletAccount(): UseWalletAccountReturn {
17
- const { address: evmAddress, connector, chainId } = useAccount()
12
+ // TODO: Rename to `usePassportAccount`
18
13
 
19
- const networkFamily = useMemo(
20
- () => (connector?.type !== "orangekit" ? "evm" : "bitcoin"),
21
- [connector],
22
- )
14
+ export default function useWalletAccount() {
15
+ const { address: evmAddress, connector, chainId, isConnected } = useAccount()
23
16
 
24
- const { data: btcData } = useQuery({
25
- queryKey: [connector?.id],
17
+ return useQuery({
18
+ queryKey: [WALLET_ACCOUNT_QUERY_KEY, evmAddress, chainId],
19
+ enabled: !!evmAddress,
26
20
  queryFn: async () => {
27
- const bitcoinProvider = (
28
- connector as unknown as OrangeKitConnector
29
- ).getBitcoinProvider()
21
+ if (!evmAddress || !connector || !chainId) {
22
+ throw new Error("Failed to retrieve wallet account information")
23
+ }
30
24
 
31
- const address = await bitcoinProvider.getAddress()
32
- const balance = await bitcoinProvider.getBalance()
25
+ const bitcoinProvider = getBitcoinProviderFromConnector(connector)
26
+ const btcAddress = await bitcoinProvider?.getAddress()
27
+
28
+ const walletAddress = btcAddress ?? evmAddress
29
+ const networkFamily: "evm" | "bitcoin" =
30
+ connector.type !== "orangekit" ? "evm" : "bitcoin"
33
31
 
34
32
  return {
35
- address,
36
- balance,
33
+ accountAddress: evmAddress,
34
+ walletAddress,
35
+ isConnected,
36
+ networkFamily,
37
+ connector,
38
+ chainId,
37
39
  }
38
40
  },
39
41
  })
40
-
41
- const { address: btcAddress } = btcData || {}
42
-
43
- return {
44
- accountAddress: evmAddress,
45
- walletAddress: btcAddress ?? evmAddress,
46
- isConnected: networkFamily === "bitcoin" ? !!btcAddress : !!evmAddress,
47
- networkFamily,
48
- connector,
49
- chainId,
50
- } as const
51
42
  }
package/src/index.ts CHANGED
@@ -9,7 +9,6 @@ export {
9
9
  xverseWalletMezoTestnet,
10
10
  getDefaultWallets,
11
11
  getConfig,
12
- safeWalletConnectWallet,
13
12
  } from "./config"
14
13
  export * from "./constants"
15
14
  export * from "./hooks"
@@ -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"