@unisat/wallet-state 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +0 -5
  2. package/lib/index.d.mts +2012 -200
  3. package/lib/index.d.ts +2012 -200
  4. package/lib/index.js +6951 -570
  5. package/lib/index.js.map +1 -1
  6. package/lib/index.mjs +6754 -517
  7. package/lib/index.mjs.map +1 -1
  8. package/lib/types/index.d.mts +1 -1
  9. package/lib/types/index.d.ts +1 -1
  10. package/package.json +19 -15
  11. package/src/.DS_Store +0 -0
  12. package/src/context/ApprovalContext.tsx +27 -0
  13. package/src/context/DeviceContext.tsx +36 -0
  14. package/src/context/I18nContext.tsx +14 -172
  15. package/src/context/NavigationContext.tsx +305 -0
  16. package/src/context/PriceContext.tsx +2 -2
  17. package/src/context/StorageContext.tsx +393 -0
  18. package/src/context/ToolsContext.tsx +50 -0
  19. package/src/context/WalletContext.tsx +119 -108
  20. package/src/context/index.ts +17 -2
  21. package/src/hooks/accounts.ts +11 -5
  22. package/src/hooks/browser.ts +11 -0
  23. package/src/hooks/global.ts +170 -7
  24. package/src/hooks/index.ts +1 -2
  25. package/src/hooks/settings.ts +28 -37
  26. package/src/hooks/transactions.ts +28 -155
  27. package/src/hooks/ui.ts +232 -36
  28. package/src/index.ts +33 -24
  29. package/src/reducers/accounts.ts +19 -2
  30. package/src/reducers/browser.ts +223 -0
  31. package/src/reducers/global.ts +67 -1
  32. package/src/reducers/index.ts +1 -0
  33. package/src/reducers/transactions.ts +0 -9
  34. package/src/reducers/ui.ts +127 -8
  35. package/src/types/index.ts +1 -1
  36. package/src/ui-hooks/index.ts +107 -0
  37. package/src/ui-hooks/useActionOverviewSectionLogic.ts +150 -0
  38. package/src/ui-hooks/useAddressTypeScreenLogic.ts +160 -0
  39. package/src/ui-hooks/useAlkanesBalanceCardLogic.ts +41 -0
  40. package/src/ui-hooks/useAlkanesCollectionListLogic.ts +68 -0
  41. package/src/ui-hooks/useAlkanesListLogic.ts +69 -0
  42. package/src/ui-hooks/useAlkanesNFTListLogic.ts +42 -0
  43. package/src/ui-hooks/useAlkanesNFTScreenLogic.ts +45 -0
  44. package/src/ui-hooks/useAlkanesTokenScreenLogic.ts +130 -0
  45. package/src/ui-hooks/useAmountInputLogic.ts +80 -0
  46. package/src/ui-hooks/useAnnouncementCardLogic.ts +91 -0
  47. package/src/ui-hooks/useBRC20BalanceCardLogic.ts +115 -0
  48. package/src/ui-hooks/useBRC20InscribeTransferLogic.ts +398 -0
  49. package/src/ui-hooks/useBRC20ListLogic.ts +75 -0
  50. package/src/ui-hooks/useBRC20ProgListLogic.ts +77 -0
  51. package/src/ui-hooks/useBRC20SendScreenLogic.ts +411 -0
  52. package/src/ui-hooks/useBRC20SingleStepScreenLogic.ts +208 -0
  53. package/src/ui-hooks/useBRC20TokenScreenLogic.ts +469 -0
  54. package/src/ui-hooks/useBalanceCardLogic.ts +164 -0
  55. package/src/ui-hooks/useBtcDisplayLogic.ts +16 -0
  56. package/src/ui-hooks/useCAT20BalanceCardLogic.ts +35 -0
  57. package/src/ui-hooks/useCAT20ListLogic.ts +83 -0
  58. package/src/ui-hooks/useCAT20TokenScreenLogic.ts +122 -0
  59. package/src/ui-hooks/useCAT721ListLogic.ts +68 -0
  60. package/src/ui-hooks/useCAT721NFTScreenLogic.ts +37 -0
  61. package/src/ui-hooks/useCreatePasswordScreenLogic.ts +92 -0
  62. package/src/ui-hooks/useCreateWalletLogicImportWordsStep.ts +299 -0
  63. package/src/ui-hooks/useEditAccountNameScreenLogic.ts +71 -0
  64. package/src/ui-hooks/useEditContactScreenLogic.ts +162 -0
  65. package/src/ui-hooks/useEditWalletNameScreenLogic.ts +58 -0
  66. package/src/ui-hooks/useExportMnemonicsScreenLogic.ts +75 -0
  67. package/src/ui-hooks/useExportPrivateKeyScreenLogic.ts +64 -0
  68. package/src/ui-hooks/useFeeRateBarLogic.ts +303 -0
  69. package/src/ui-hooks/useInfiniteList.ts +85 -0
  70. package/src/ui-hooks/useInscriptionListLogic.ts +68 -0
  71. package/src/ui-hooks/useLockTimePageLogic.ts +43 -0
  72. package/src/ui-hooks/useNotificationsLogic.ts +115 -0
  73. package/src/ui-hooks/useOrdinalsInscriptionScreenLogic.ts +130 -0
  74. package/src/ui-hooks/useRunesBalanceCardLogic.ts +44 -0
  75. package/src/ui-hooks/useRunesListLogic.ts +74 -0
  76. package/src/ui-hooks/useRunesTokenScreenLogic.ts +149 -0
  77. package/src/ui-hooks/useSecurityCardLogic.ts +0 -0
  78. package/src/ui-hooks/useSendAlkanesNFTScreenLogic.ts +138 -0
  79. package/src/ui-hooks/useSendAlkanesScreenLogic.ts +192 -0
  80. package/src/ui-hooks/useSendCAT20ScreenLogic.ts +297 -0
  81. package/src/ui-hooks/useSendCAT721ScreenLogic.ts +205 -0
  82. package/src/ui-hooks/useSendOrdinalsInscriptionScreenLogic.ts +137 -0
  83. package/src/ui-hooks/useSendRunesScreenLogic.ts +172 -0
  84. package/src/ui-hooks/useSettingsTabScreenLogic.ts +211 -0
  85. package/src/ui-hooks/useSignMessageLogic.ts +302 -0
  86. package/src/ui-hooks/useSignPsbtLogic.ts +517 -0
  87. package/src/ui-hooks/useSplitOrdinalsInscriptionScreenLogic.ts +95 -0
  88. package/src/ui-hooks/useTxConfirmScreenLogic.ts +47 -0
  89. package/src/ui-hooks/useTxCreateScreenLogic.ts +161 -0
  90. package/src/ui-hooks/useTxFailScreenLogic.ts +26 -0
  91. package/src/ui-hooks/useTxSuccessScreenLogic.ts +33 -0
  92. package/src/updater/accounts.ts +11 -11
  93. package/src/utils/bitcoin-utils.ts +17 -8
  94. package/src/utils/eventBus.ts +2 -1
  95. package/src/utils/password-utils.ts +78 -0
  96. package/src/utils/ui-utils.ts +28 -0
  97. package/src/hooks/approval.ts +0 -72
  98. package/src/hooks/i18n.ts +0 -53
  99. package/src/utils/i18n.ts +0 -41
@@ -1,5 +1,5 @@
1
- import { Inscription } from '@unisat/wallet-shared'
2
1
  import { createSlice, Slice } from '@reduxjs/toolkit'
2
+ import { Inscription } from '@unisat/wallet-shared'
3
3
 
4
4
  import { updateVersion } from '../actions/global'
5
5
  import {
@@ -10,6 +10,14 @@ import {
10
10
  OrdinalsAssetTabKey,
11
11
  } from '../types'
12
12
 
13
+ export enum WallettopTabScreenTabKey {
14
+ Ordinals,
15
+ Atomicals,
16
+ Runes,
17
+ CAT20,
18
+ Alkanes,
19
+ }
20
+
13
21
  export interface UIState {
14
22
  assetTabKey: AssetTabKey
15
23
  ordinalsAssetTabKey: OrdinalsAssetTabKey
@@ -22,8 +30,21 @@ export interface UIState {
22
30
  inscription?: Inscription
23
31
  }
24
32
  inputAmount: string
25
- enableRBF: boolean
33
+ }
34
+ addressInput: {
35
+ address: string
36
+ domain: string
37
+ inscription?: Inscription
38
+ }
39
+ amountInput: {
40
+ amount: string
41
+ }
42
+ feeRateBar: {
26
43
  feeRate: number
44
+ feeRateInputVal: string
45
+ enableLowFeeRate: boolean
46
+ feeOptionIndex: number
47
+ showCustomInput: boolean
27
48
  }
28
49
  babylonSendScreen: {
29
50
  inputAmount: string
@@ -31,6 +52,11 @@ export interface UIState {
31
52
  }
32
53
  navigationSource: NavigationSource
33
54
  isBalanceHidden: boolean
55
+ balanceDetailExpanded: boolean
56
+
57
+ walletTopTabScreen: {
58
+ toptabKey: WallettopTabScreenTabKey
59
+ }
34
60
  }
35
61
 
36
62
  export const initialState: UIState = {
@@ -44,8 +70,20 @@ export const initialState: UIState = {
44
70
  domain: '',
45
71
  },
46
72
  inputAmount: '',
47
- enableRBF: false,
73
+ },
74
+ addressInput: {
75
+ address: '',
76
+ domain: '',
77
+ },
78
+ amountInput: {
79
+ amount: '',
80
+ },
81
+ feeRateBar: {
48
82
  feeRate: 1,
83
+ feeRateInputVal: '',
84
+ enableLowFeeRate: false,
85
+ feeOptionIndex: 1, // Default to AVG
86
+ showCustomInput: false,
49
87
  },
50
88
  babylonSendScreen: {
51
89
  inputAmount: '',
@@ -53,6 +91,11 @@ export const initialState: UIState = {
53
91
  },
54
92
  navigationSource: NavigationSource.NORMAL,
55
93
  isBalanceHidden: false,
94
+ balanceDetailExpanded: true,
95
+
96
+ walletTopTabScreen: {
97
+ toptabKey: WallettopTabScreenTabKey.Ordinals,
98
+ },
56
99
  }
57
100
 
58
101
  const slice: Slice<UIState> = createSlice({
@@ -99,8 +142,6 @@ const slice: Slice<UIState> = createSlice({
99
142
  inscription?: Inscription
100
143
  }
101
144
  inputAmount?: string
102
- enableRBF?: boolean
103
- feeRate?: number
104
145
  }
105
146
  }
106
147
  ) {
@@ -110,13 +151,82 @@ const slice: Slice<UIState> = createSlice({
110
151
  if (action.payload.inputAmount !== undefined) {
111
152
  state.uiTxCreateScreen.inputAmount = action.payload.inputAmount
112
153
  }
113
- if (action.payload.enableRBF !== undefined) {
114
- state.uiTxCreateScreen.enableRBF = action.payload.enableRBF
154
+
155
+ state.uiTxCreateScreen = { ...state.uiTxCreateScreen }
156
+ },
157
+ updateFeeRateBar(
158
+ state,
159
+ action: {
160
+ payload: {
161
+ feeRate?: number
162
+ feeRateInputVal?: string
163
+ enableLowFeeRate?: boolean
164
+ feeOptionIndex?: number
165
+ showCustomInput?: boolean
166
+ }
115
167
  }
168
+ ) {
116
169
  if (action.payload.feeRate !== undefined) {
117
- state.uiTxCreateScreen.feeRate = action.payload.feeRate
170
+ state.feeRateBar.feeRate = action.payload.feeRate
171
+ }
172
+ if (action.payload.feeRateInputVal !== undefined) {
173
+ state.feeRateBar.feeRateInputVal = action.payload.feeRateInputVal
174
+ }
175
+ if (action.payload.enableLowFeeRate !== undefined) {
176
+ state.feeRateBar.enableLowFeeRate = action.payload.enableLowFeeRate
118
177
  }
178
+ if (action.payload.feeOptionIndex !== undefined) {
179
+ state.feeRateBar.feeOptionIndex = action.payload.feeOptionIndex
180
+ }
181
+ if (action.payload.showCustomInput !== undefined) {
182
+ state.feeRateBar.showCustomInput = action.payload.showCustomInput
183
+ }
184
+ state.feeRateBar = { ...state.feeRateBar }
185
+ },
186
+ resetFeeRateBar(state) {
187
+ state.feeRateBar = initialState.feeRateBar
119
188
  },
189
+
190
+ updateAddressInput(
191
+ state,
192
+ action: {
193
+ payload: {
194
+ address?: string
195
+ domain?: string
196
+ }
197
+ }
198
+ ) {
199
+ if (action.payload.address !== undefined) {
200
+ state.addressInput.address = action.payload.address
201
+ }
202
+ if (action.payload.domain !== undefined) {
203
+ state.addressInput.domain = action.payload.domain
204
+ }
205
+ state.addressInput = { ...state.addressInput }
206
+ },
207
+
208
+ resetAddressInput(state) {
209
+ state.addressInput = initialState.addressInput
210
+ },
211
+
212
+ updateAmountInput(
213
+ state,
214
+ action: {
215
+ payload: {
216
+ amount?: string
217
+ }
218
+ }
219
+ ) {
220
+ if (action.payload.amount !== undefined) {
221
+ state.amountInput.amount = action.payload.amount
222
+ }
223
+ state.amountInput = { ...state.amountInput }
224
+ },
225
+
226
+ resetAmountInput(state) {
227
+ state.amountInput = initialState.amountInput
228
+ },
229
+
120
230
  resetTxCreateScreen(state) {
121
231
  state.uiTxCreateScreen = initialState.uiTxCreateScreen
122
232
  },
@@ -145,6 +255,9 @@ const slice: Slice<UIState> = createSlice({
145
255
  setBalanceHidden(state, action: { payload: boolean }) {
146
256
  state.isBalanceHidden = action.payload
147
257
  },
258
+ setBalanceDetailExpanded(state, action: { payload: boolean }) {
259
+ state.balanceDetailExpanded = action.payload
260
+ },
148
261
  },
149
262
  extraReducers: builder => {
150
263
  builder.addCase(updateVersion, state => {
@@ -164,12 +277,18 @@ const slice: Slice<UIState> = createSlice({
164
277
  if (!state.uiTxCreateScreen) {
165
278
  state.uiTxCreateScreen = initialState.uiTxCreateScreen
166
279
  }
280
+ if (!state.feeRateBar) {
281
+ state.feeRateBar = initialState.feeRateBar
282
+ }
167
283
  if (!state.babylonSendScreen) {
168
284
  state.babylonSendScreen = initialState.babylonSendScreen
169
285
  }
170
286
  if (state.isBalanceHidden === undefined) {
171
287
  state.isBalanceHidden = false
172
288
  }
289
+ if (state.balanceDetailExpanded === undefined) {
290
+ state.balanceDetailExpanded = true
291
+ }
173
292
  })
174
293
  },
175
294
  })
@@ -1,3 +1,3 @@
1
1
  export * from './ui'
2
2
 
3
- export type TabOption = 'home' | 'discover' | 'settings'
3
+ export type TabOption = 'home' | 'discover' | 'settings' | 'app'
@@ -0,0 +1,107 @@
1
+ export { useAddressTypeScreenLogic } from './useAddressTypeScreenLogic'
2
+ export { useAlkanesListLogic } from './useAlkanesListLogic'
3
+ export { useAmountInputLogic } from './useAmountInputLogic'
4
+ export { useAnnouncementCardLogic } from './useAnnouncementCardLogic'
5
+ export {
6
+ BRC20SendTabKey,
7
+ useBRC20SendScreenLogic,
8
+ useBRC20SendScreenLogicStep1,
9
+ useBRC20SendScreenLogicStep2,
10
+ useBRC20SendScreenLogicStep3,
11
+ useTransferableListLogic,
12
+ type BRC20SendStepParams,
13
+ type ContextData,
14
+ type UpdateContextDataParams,
15
+ } from './useBRC20SendScreenLogic'
16
+ export { BRC20SingleStepKey, useBRC20SingleStepScreenLogic } from './useBRC20SingleStepScreenLogic'
17
+ export {
18
+ type BRC20OutWalletBalanceItem,
19
+ BRC20TokenScreenTabKey,
20
+ useBRC20TokenHistoryLogic,
21
+ useBRC20TokenScreenLogic,
22
+ } from './useBRC20TokenScreenLogic'
23
+ export { useEditWalletNameScreenLogic } from './useEditWalletNameScreenLogic'
24
+ export { useFeeRateBarLogic } from './useFeeRateBarLogic'
25
+ export { useLockTimePageLogic } from './useLockTimePageLogic'
26
+ export { useNotificationsLogic, useUnreadNotificationsCount } from './useNotificationsLogic'
27
+ export { useSendOrdinalsInscriptionScreenLogic } from './useSendOrdinalsInscriptionScreenLogic'
28
+ export { useTxCreateScreenLogic } from './useTxCreateScreenLogic'
29
+
30
+ export {
31
+ useBRC20InscribeTransferLogic,
32
+ useBRC20InscribeTransferLogicStep1,
33
+ useBRC20InscribeTransferLogicStep2,
34
+ useBRC20InscribeTransferLogicStep3,
35
+ useBRC20InscribeTransferLogicStep4,
36
+ type BRC20InscribeTransferParams,
37
+ } from './useBRC20InscribeTransferLogic'
38
+
39
+ export { useAlkanesNFTScreenLogic } from './useAlkanesNFTScreenLogic'
40
+ export { useAlkanesTokenScreenLogic } from './useAlkanesTokenScreenLogic'
41
+ export { useCreateWalletLogicImportWordsStep } from './useCreateWalletLogicImportWordsStep'
42
+ export { useOrdinalsInscriptionScreenLogic } from './useOrdinalsInscriptionScreenLogic'
43
+
44
+ export { useRunesTokenScreenLogic } from './useRunesTokenScreenLogic'
45
+
46
+ export { useBRC20BalanceCardLogic, type BRC20BalanceCardProps } from './useBRC20BalanceCardLogic'
47
+
48
+ export { useExportMnemonicsScreenLogic } from './useExportMnemonicsScreenLogic'
49
+ export { useExportPrivateKeyScreenLogic } from './useExportPrivateKeyScreenLogic'
50
+ export { useSendRunesScreenLogic } from './useSendRunesScreenLogic'
51
+
52
+ export { useEditContactScreenLogic } from './useEditContactScreenLogic'
53
+
54
+ export { useEditAccountNameScreenLogic } from './useEditAccountNameScreenLogic'
55
+
56
+ export { useAlkanesCollectionListLogic } from './useAlkanesCollectionListLogic'
57
+ export { useBRC20ListLogic } from './useBRC20ListLogic'
58
+
59
+ export { useInscriptionListLogic } from './useInscriptionListLogic'
60
+ export { useRunesListLogic } from './useRunesListLogic'
61
+
62
+ export { useCAT20ListLogic } from './useCAT20ListLogic'
63
+ export { SendCAT20ScreenStep, useSendCAT20ScreenLogic } from './useSendCAT20ScreenLogic'
64
+ export { SendCAT721ScreenStep, useSendCAT721ScreenLogic } from './useSendCAT721ScreenLogic'
65
+
66
+ export { useAlkanesNFTListLogic } from './useAlkanesNFTListLogic'
67
+ export { useBRC20ProgListLogic } from './useBRC20ProgListLogic'
68
+ export { useCAT721ListLogic } from './useCAT721ListLogic'
69
+
70
+ export { useCAT20TokenScreenLogic } from './useCAT20TokenScreenLogic'
71
+
72
+ export { useSplitOrdinalsInscriptionScreenLogic } from './useSplitOrdinalsInscriptionScreenLogic'
73
+
74
+ export { useCreatePasswordScreenLogic } from './useCreatePasswordScreenLogic'
75
+ export {
76
+ SendAlkanesNFTScreenStep,
77
+ useSendAlkanesNFTScreenLogic,
78
+ } from './useSendAlkanesNFTScreenLogic'
79
+ export { SendAlkanesScreenStep, useSendAlkanesScreenLogic } from './useSendAlkanesScreenLogic'
80
+
81
+ export { useRunesBalanceCardLogic, type RunesBalanceCardProps } from './useRunesBalanceCardLogic'
82
+
83
+ export { useCAT20BalanceCardLogic, type CAT20BalanceCardProps } from './useCAT20BalanceCardLogic'
84
+
85
+ export {
86
+ useAlkanesBalanceCardLogic,
87
+ type AlkanesBalanceCardProps,
88
+ } from './useAlkanesBalanceCardLogic'
89
+
90
+ export { useCAT721NFTScreenLogic } from './useCAT721NFTScreenLogic'
91
+
92
+ export { useSignMessageLogic, type SignMessageProps } from './useSignMessageLogic'
93
+ export { useSignPsbtLogic, type SignPsbtProps } from './useSignPsbtLogic'
94
+ export type { PsbtLocalInfo } from '@unisat/wallet-shared'
95
+
96
+ export { useTxConfirmScreenLogic } from './useTxConfirmScreenLogic'
97
+ export { useTxFailScreenLogic } from './useTxFailScreenLogic'
98
+ export { useTxSuccessScreenLogic } from './useTxSuccessScreenLogic'
99
+
100
+ export {
101
+ useActionOverviewSectionLogic,
102
+ type ActionOverviewSectionProps,
103
+ } from './useActionOverviewSectionLogic'
104
+ export { useSettingsTabScreenLogic, type SettingsItemType } from './useSettingsTabScreenLogic'
105
+
106
+ export { useBalanceCardLogic } from './useBalanceCardLogic'
107
+ export { useBtcDisplayLogic } from './useBtcDisplayLogic'
@@ -0,0 +1,150 @@
1
+ import {
2
+ DecodedPsbt,
3
+ Inscription,
4
+ PsbtActionDetailType,
5
+ PsbtActionInfo,
6
+ PsbtActionType,
7
+ } from '@unisat/wallet-shared'
8
+ import { useMemo } from 'react'
9
+ import { useI18n } from 'src/context'
10
+ import { useChain, useCurrentAddress } from 'src/hooks'
11
+
12
+ export interface ActionOverviewSectionProps {
13
+ action: PsbtActionInfo
14
+ decodedPsbt: DecodedPsbt
15
+ }
16
+
17
+ export function useActionOverviewSectionLogic({ action, decodedPsbt }: ActionOverviewSectionProps) {
18
+ const { t } = useI18n()
19
+
20
+ const chain = useChain()
21
+
22
+ const currentAddress = useCurrentAddress()
23
+
24
+ const spendSatoshis = useMemo(() => {
25
+ const inValue = decodedPsbt.inputInfos
26
+ .filter(v => v.address === currentAddress)
27
+ .reduce((pre, cur) => cur.value + pre, 0)
28
+ const outValue = decodedPsbt.outputInfos
29
+ .filter(v => v.address === currentAddress)
30
+ .reduce((pre, cur) => cur.value + pre, 0)
31
+ const spend = inValue - outValue
32
+ return spend
33
+ }, [decodedPsbt, currentAddress])
34
+
35
+ const spendingInscriptionCount = useMemo(() => {
36
+ let count = 0
37
+ decodedPsbt.inputInfos.forEach(inputInfo => {
38
+ if (inputInfo.address === currentAddress) {
39
+ inputInfo.inscriptions.forEach(inscription => {
40
+ const inscriptionInfo: Inscription = decodedPsbt.inscriptions[inscription.inscriptionId]
41
+ if (inscriptionInfo.brc20 && inscriptionInfo.brc20.op === 'transfer') {
42
+ // skip brc20
43
+ } else {
44
+ count++
45
+ }
46
+ })
47
+ }
48
+ })
49
+ return count
50
+ }, [decodedPsbt, currentAddress])
51
+
52
+ const spendingBrc20Count = useMemo(() => {
53
+ let count = 0
54
+ decodedPsbt.inputInfos.forEach(inputInfo => {
55
+ if (inputInfo.address === currentAddress) {
56
+ inputInfo.inscriptions.forEach(inscription => {
57
+ const inscriptionInfo: Inscription = decodedPsbt.inscriptions[inscription.inscriptionId]
58
+ if (inscriptionInfo.brc20 && inscriptionInfo.brc20.op === 'transfer') {
59
+ count++
60
+ }
61
+ })
62
+ }
63
+ })
64
+ return count
65
+ }, [decodedPsbt, currentAddress])
66
+
67
+ const spendingRunesCount = useMemo(() => {
68
+ const runeMap: { [key: string]: string } = {}
69
+ decodedPsbt.inputInfos.forEach(inputInfo => {
70
+ if (inputInfo.address === currentAddress) {
71
+ inputInfo.runes.forEach(rune => {
72
+ runeMap[rune.runeid] = rune.runeid
73
+ })
74
+ }
75
+ })
76
+ return Object.keys(runeMap).length
77
+ }, [decodedPsbt, currentAddress])
78
+
79
+ const spendingAlkanesCount = useMemo(() => {
80
+ const alkaneMap: { [key: string]: string } = {}
81
+ decodedPsbt.inputInfos.forEach(inputInfo => {
82
+ if (inputInfo.address === currentAddress) {
83
+ inputInfo.alkanes.forEach(alkane => {
84
+ alkaneMap[alkane.alkaneid] = alkane.alkaneid
85
+ })
86
+ }
87
+ })
88
+ return Object.keys(alkaneMap).length
89
+ }, [decodedPsbt, currentAddress])
90
+
91
+ if (!action) {
92
+ action = {
93
+ name: '',
94
+ description: '',
95
+ type: PsbtActionType.DEFAULT,
96
+ }
97
+ }
98
+
99
+ if (action.details?.length === 0) {
100
+ action.details = []
101
+ }
102
+
103
+ if (action.type === PsbtActionType.DEFAULT) {
104
+ action.name = t('sign_transaction')
105
+ action.description = ''
106
+ action.details = []
107
+
108
+ if (
109
+ spendingInscriptionCount > 0 ||
110
+ spendingBrc20Count > 0 ||
111
+ spendingAlkanesCount > 0 ||
112
+ spendingRunesCount > 0
113
+ ) {
114
+ action.details.push({
115
+ type: PsbtActionDetailType.MULTIASSETS,
116
+ label: t('spending_assets'),
117
+ value: {
118
+ inscriptionCount: spendingInscriptionCount,
119
+ brc20Count: spendingBrc20Count,
120
+ runesCount: spendingRunesCount,
121
+ alkanesCount: spendingAlkanesCount,
122
+ },
123
+ })
124
+ }
125
+ }
126
+
127
+ const commonDetails: any[] = []
128
+ if (spendSatoshis > 0) {
129
+ commonDetails.push({
130
+ type: PsbtActionDetailType.SATOSHIS,
131
+ label: t('spending_amount'),
132
+ value: `${spendSatoshis}`,
133
+ })
134
+ }
135
+
136
+ if (spendSatoshis < 0) {
137
+ commonDetails.push({
138
+ type: PsbtActionDetailType.SATOSHIS,
139
+ label: t('receive'),
140
+ value: `${-spendSatoshis}`,
141
+ })
142
+ }
143
+
144
+ return {
145
+ decodedPsbt,
146
+ action,
147
+ commonDetails,
148
+ chain,
149
+ }
150
+ }
@@ -0,0 +1,160 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react'
2
+
3
+ import { numUtils } from '@unisat/base-utils'
4
+ import { ADDRESS_TYPES, KeyringType } from '@unisat/keyring-service/types'
5
+ import { getAccountDerivationPath } from '@unisat/wallet-shared'
6
+ import { AddressType } from '@unisat/wallet-types'
7
+ import {
8
+ useAppDispatch,
9
+ useCurrentAccount,
10
+ useCurrentKeyring,
11
+ useI18n,
12
+ useNavigation,
13
+ useReloadAccounts,
14
+ useTools,
15
+ useWallet,
16
+ } from '..'
17
+
18
+ interface AddressTypeItem {
19
+ address: string
20
+ assets: { total_btc: string; satoshis: number; total_inscription: number }
21
+ name: string
22
+ value: AddressType
23
+ }
24
+
25
+ export function useAddressTypeScreenLogic() {
26
+ // const isInTab = useExtensionIsInTab()
27
+ const { t } = useI18n()
28
+
29
+ const wallet = useWallet()
30
+ const currentKeyring = useCurrentKeyring()
31
+ const account = useCurrentAccount()
32
+
33
+ const nav = useNavigation()
34
+ const dispatch = useAppDispatch()
35
+ const reloadAccounts = useReloadAccounts()
36
+ const [addresses, setAddresses] = useState<string[]>([])
37
+ const [addressAssets, setAddressAssets] = useState<{
38
+ [key: string]: { total_btc: string; satoshis: number; total_inscription: number }
39
+ }>({})
40
+
41
+ const selfRef = useRef<{
42
+ addressAssets: {
43
+ [key: string]: { total_btc: string; satoshis: number; total_inscription: number }
44
+ }
45
+ }>({
46
+ addressAssets: {},
47
+ })
48
+ const self = selfRef.current
49
+
50
+ const tools = useTools()
51
+ const loadAddresses = async () => {
52
+ try {
53
+ tools.showLoading(true)
54
+ const _res = await wallet.getAllAddresses(currentKeyring, account.index || 0)
55
+ setAddresses(_res)
56
+ const balances = await wallet.getMultiAddressAssets(_res.join(','))
57
+ for (let i = 0; i < _res.length; i++) {
58
+ const address = _res[i]
59
+ const balance = balances[i]
60
+ const satoshis = balance.totalSatoshis
61
+ self.addressAssets[address] = {
62
+ total_btc: numUtils.satoshisToAmount(balance.totalSatoshis),
63
+ satoshis,
64
+ total_inscription: balance.inscriptionCount,
65
+ }
66
+ }
67
+ setAddressAssets(self.addressAssets)
68
+ } catch (e) {
69
+ console.error(e)
70
+ } finally {
71
+ tools.showLoading(false)
72
+ }
73
+ }
74
+
75
+ useEffect(() => {
76
+ loadAddresses()
77
+ }, [])
78
+
79
+ const addressTypes = useMemo(() => {
80
+ // Cold wallets do not allow switching address types, only show the current type
81
+ if (currentKeyring.type === KeyringType.ColdWalletKeyring) {
82
+ return ADDRESS_TYPES.filter(v => v.value === currentKeyring.addressType)
83
+ }
84
+
85
+ if (currentKeyring.type === KeyringType.HdKeyring) {
86
+ return ADDRESS_TYPES.filter(v => {
87
+ if (v.displayIndex < 0) {
88
+ return false
89
+ }
90
+ // MagicEden only supports P2WPKH and P2TR
91
+ if (currentKeyring.accountIndexDerivation) {
92
+ return v.value === AddressType.P2WPKH || v.value === AddressType.P2TR
93
+ }
94
+ const address = addresses[v.value]
95
+ const balance = addressAssets[address]
96
+ if (v.isUnisatLegacy) {
97
+ if (!balance || balance.satoshis == 0) {
98
+ return false
99
+ }
100
+ }
101
+ return true
102
+ }).sort((a, b) => a.displayIndex - b.displayIndex)
103
+ } else {
104
+ return ADDRESS_TYPES.filter(v => v.displayIndex >= 0 && v.isUnisatLegacy != true).sort(
105
+ (a, b) => a.displayIndex - b.displayIndex
106
+ )
107
+ }
108
+ }, [currentKeyring.type, currentKeyring.addressType, addressAssets, addresses])
109
+
110
+ const items: AddressTypeItem[] = useMemo(() => {
111
+ return addressTypes.map(v => {
112
+ const address = addresses[v.value]
113
+ const assets = addressAssets[address] || {
114
+ total_btc: '--',
115
+ satoshis: 0,
116
+ total_inscription: 0,
117
+ }
118
+ const derivedPath = getAccountDerivationPath(v.hdPath, account.index || 0, currentKeyring.accountIndexDerivation)
119
+ let name = `${v.name} (${derivedPath})`
120
+ if (currentKeyring.type === KeyringType.SimpleKeyring) {
121
+ name = `${v.name}`
122
+ } else if (currentKeyring.type === KeyringType.ColdWalletKeyring) {
123
+ name = `❄️ ${v.name} (${derivedPath}) - ${t('Fixed by cold wallet')}`
124
+ }
125
+
126
+ return {
127
+ address,
128
+ assets,
129
+ name,
130
+ value: v.value,
131
+ }
132
+ })
133
+ }, [addressTypes])
134
+
135
+ const onClickItem = async (item: AddressTypeItem) => {
136
+ if (item.value == currentKeyring.addressType) {
137
+ return
138
+ }
139
+
140
+ // Cold wallets do not allow switching address types
141
+ if (currentKeyring.type === KeyringType.ColdWalletKeyring) {
142
+ tools.toastError(t('Cold wallet address type cannot be changed'))
143
+ return
144
+ }
145
+
146
+ await wallet.changeAddressType(item.value)
147
+ reloadAccounts()
148
+ // navigate('MainScreen')
149
+ tools.toastSuccess(t('address_type_changed'))
150
+
151
+ nav.navToTab()
152
+ }
153
+
154
+ return {
155
+ currentKeyring,
156
+ items,
157
+ wallet,
158
+ onClickItem,
159
+ }
160
+ }
@@ -0,0 +1,41 @@
1
+ import { bnUtils, numUtils } from '@unisat/base-utils'
2
+ import { AlkanesBalance, TickPriceItem } from '@unisat/wallet-shared'
3
+ import { useAlkanesIconInfo, useChain } from 'src/hooks'
4
+
5
+ export interface AlkanesBalanceCardProps {
6
+ tokenBalance: AlkanesBalance
7
+ onClick?: () => void
8
+ price?: TickPriceItem
9
+ }
10
+ export function useAlkanesBalanceCardLogic(props: AlkanesBalanceCardProps) {
11
+ const { tokenBalance, onClick, price } = props
12
+
13
+ const chain = useChain()
14
+ const showPrice = chain.showPrice && price !== undefined
15
+
16
+ const balance = bnUtils.toDecimalNumber(tokenBalance.amount, tokenBalance.divisibility)
17
+ let balanceStr = balance.toString()
18
+ if (balance.lt(0.0001)) {
19
+ balanceStr = '<0.0001'
20
+ } else {
21
+ balanceStr = numUtils.showLongNumber(balance.toString())
22
+ }
23
+
24
+ const iconInfo = useAlkanesIconInfo(tokenBalance.name, tokenBalance.alkaneid)
25
+
26
+ return {
27
+ // balance
28
+ tokenBalance,
29
+ balance,
30
+ balanceStr,
31
+
32
+ // price
33
+ showPrice,
34
+ price,
35
+
36
+ // icon
37
+ iconInfo,
38
+
39
+ onClick,
40
+ }
41
+ }