@unisat/wallet-state 1.0.5 → 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
@@ -0,0 +1,411 @@
1
+ import {
2
+ RawTxInfo,
3
+ SignPsbtParams,
4
+ TokenBalance,
5
+ TokenInfo,
6
+ TokenTransfer,
7
+ } from '@unisat/wallet-shared'
8
+ import BigNumber from 'bignumber.js'
9
+ import { startTransition, useCallback, useEffect, useMemo, useState } from 'react'
10
+ import { useI18n, useNavigation, useTools, useWallet } from 'src/context'
11
+ import {
12
+ useCurrentAccount,
13
+ useFeeRateBar,
14
+ useFetchUtxosCallback,
15
+ usePrepareSendOrdinalsInscriptionCallback,
16
+ usePrepareSendOrdinalsInscriptionsCallback,
17
+ usePushOrdinalsTxCallback,
18
+ } from 'src/hooks'
19
+ import { getAddressUtxoDust } from 'src/utils/bitcoin-utils'
20
+
21
+ export enum BRC20SendTabKey {
22
+ STEP1,
23
+ STEP2,
24
+ STEP3,
25
+ }
26
+
27
+ export interface ContextData {
28
+ tabKey: BRC20SendTabKey
29
+ tokenBalance: TokenBalance
30
+ transferAmount: string
31
+ transferableList: TokenTransfer[]
32
+ inscriptionIdSet: Set<string>
33
+ receiver: string
34
+ rawTxInfo: RawTxInfo
35
+ tokenInfo: TokenInfo
36
+ }
37
+
38
+ export interface UpdateContextDataParams {
39
+ tabKey?: BRC20SendTabKey
40
+ tokenBalance?: TokenBalance
41
+ transferAmount?: string
42
+ transferableList?: TokenTransfer[]
43
+ inscriptionIdSet?: Set<string>
44
+ receiver?: string
45
+ rawTxInfo?: RawTxInfo
46
+ }
47
+
48
+ export interface BRC20SendStepParams {
49
+ contextData: ContextData
50
+ updateContextData: (params: UpdateContextDataParams) => void
51
+ }
52
+
53
+ export function useBRC20SendScreenLogic() {
54
+ const nav = useNavigation()
55
+
56
+ const props = nav.getRouteState<'BRC20SendScreen'>()
57
+
58
+ const tokenBalance = props.tokenBalance
59
+ const selectedInscriptionIds = props.selectedInscriptionIds || []
60
+ const selectedAmount = props.selectedAmount || '0'
61
+
62
+ const [contextData, setContextData] = useState<ContextData>({
63
+ tabKey: BRC20SendTabKey.STEP1,
64
+ tokenBalance,
65
+ transferAmount: selectedAmount,
66
+ transferableList: [],
67
+ inscriptionIdSet: new Set(selectedInscriptionIds),
68
+ receiver: '',
69
+ rawTxInfo: {
70
+ psbtHex: '',
71
+ rawtx: '',
72
+ },
73
+ tokenInfo: {
74
+ totalSupply: '0',
75
+ totalMinted: '0',
76
+ decimal: 18,
77
+ holder: '',
78
+ inscriptionId: '',
79
+ historyCount: 0,
80
+ holdersCount: 0,
81
+ logo: '',
82
+ },
83
+ })
84
+
85
+ const updateContextData = useCallback((params: UpdateContextDataParams) => {
86
+ setContextData(prev => {
87
+ let changed = false
88
+ const next = { ...prev }
89
+ for (const key in params) {
90
+ if (prev[key] !== params[key]) {
91
+ next[key] = params[key]
92
+ changed = true
93
+ }
94
+ }
95
+
96
+ return changed ? next : prev
97
+ })
98
+ }, [])
99
+
100
+ const onHeaderBack = () => {
101
+ if (contextData.tabKey === BRC20SendTabKey.STEP2) {
102
+ updateContextData({ tabKey: BRC20SendTabKey.STEP1 })
103
+ return
104
+ }
105
+ nav.goBack()
106
+ }
107
+
108
+ const onTabClick = (key: string) => {
109
+ updateContextData({ tabKey: key as any })
110
+ }
111
+
112
+ const { t } = useI18n()
113
+
114
+ return {
115
+ t,
116
+ contextData,
117
+ updateContextData,
118
+ onHeaderBack,
119
+ onTabClick,
120
+ }
121
+ }
122
+
123
+ export function useBRC20SendScreenLogicStep1({
124
+ contextData,
125
+ updateContextData,
126
+ }: BRC20SendStepParams) {
127
+ const { tokenBalance } = contextData
128
+
129
+ const { t } = useI18n()
130
+
131
+ const [disabled, setDisabled] = useState(true)
132
+
133
+ useEffect(() => {
134
+ setDisabled(true)
135
+ if (new BigNumber(contextData.transferAmount).lte(0)) {
136
+ return
137
+ }
138
+
139
+ setDisabled(false)
140
+ }, [contextData.transferAmount])
141
+
142
+ const onClickNext = () => {
143
+ updateContextData({
144
+ tabKey: BRC20SendTabKey.STEP2,
145
+ })
146
+ }
147
+
148
+ return {
149
+ t,
150
+ disabled,
151
+ tokenBalance,
152
+ onClickNext,
153
+ }
154
+ }
155
+ export function useBRC20SendScreenLogicStep2({
156
+ contextData,
157
+ updateContextData,
158
+ }: BRC20SendStepParams) {
159
+ const nav = useNavigation()
160
+ const fetchUtxos = useFetchUtxosCallback()
161
+ const tools = useTools()
162
+ const { t } = useI18n()
163
+ useEffect(() => {
164
+ tools.showLoading(true)
165
+ fetchUtxos().finally(() => {
166
+ tools.showLoading(false)
167
+ })
168
+ }, [])
169
+
170
+ const feeRateBar = useFeeRateBar()
171
+
172
+ const prepareSendOrdinalsInscriptions = usePrepareSendOrdinalsInscriptionsCallback()
173
+ const prepareSendOrdinalsInscription = usePrepareSendOrdinalsInscriptionCallback()
174
+
175
+ const [disabled, setDisabled] = useState(true)
176
+
177
+ useEffect(() => {
178
+ setDisabled(true)
179
+ if (!contextData.receiver) {
180
+ return
181
+ }
182
+ if (!feeRateBar.feeRate) {
183
+ return
184
+ }
185
+ setDisabled(false)
186
+ }, [contextData.receiver, feeRateBar.feeRate])
187
+
188
+ const onStep2ClickNext = async () => {
189
+ try {
190
+ tools.showLoading(true)
191
+ const inscriptionIds = Array.from(contextData.inscriptionIdSet)
192
+ if (inscriptionIds.length === 1) {
193
+ const toSignData = await prepareSendOrdinalsInscription({
194
+ toAddressInfo: { address: contextData.receiver, domain: '' },
195
+ inscriptionId: inscriptionIds[0],
196
+ feeRate: feeRateBar.feeRate,
197
+ outputValue: getAddressUtxoDust(contextData.receiver),
198
+ })
199
+ nav.navigate('TxConfirmScreen', { toSignData })
200
+ } else {
201
+ const toSignData = await prepareSendOrdinalsInscriptions({
202
+ toAddressInfo: { address: contextData.receiver, domain: '' },
203
+ inscriptionIds,
204
+ feeRate: feeRateBar.feeRate,
205
+ })
206
+ nav.navigate('TxConfirmScreen', { toSignData })
207
+ }
208
+
209
+ // updateContextData({ tabKey: TabKey.STEP3, rawTxInfo: txInfo });
210
+ } catch (e) {
211
+ const error = e as Error
212
+ console.log(error)
213
+ tools.toastError(error.message)
214
+ } finally {
215
+ tools.showLoading(false)
216
+ }
217
+ }
218
+
219
+ const onStep2ClickBack = async () => {
220
+ if (contextData.tabKey === BRC20SendTabKey.STEP2) {
221
+ updateContextData({ tabKey: BRC20SendTabKey.STEP1 })
222
+ }
223
+ }
224
+ return {
225
+ t,
226
+ disabled,
227
+ onStep2ClickNext,
228
+ onStep2ClickBack,
229
+ }
230
+ }
231
+
232
+ export function useBRC20SendScreenLogicStep3({
233
+ contextData,
234
+ updateContextData,
235
+ }: BRC20SendStepParams) {
236
+ const { t } = useI18n()
237
+ const nav = useNavigation()
238
+ const pushOrdinalsTx = usePushOrdinalsTxCallback()
239
+
240
+ const onSignPsbtConfirm = async res => {
241
+ try {
242
+ let txData = ''
243
+
244
+ if (res && res.psbtHex) {
245
+ txData = res.psbtHex
246
+ } else if (res && res.rawtx) {
247
+ txData = res.rawtx
248
+ } else if (contextData.rawTxInfo.rawtx) {
249
+ txData = contextData.rawTxInfo.rawtx
250
+ } else {
251
+ throw new Error(t('invalid_transaction_data'))
252
+ }
253
+
254
+ const { success, txid, error } = await pushOrdinalsTx(txData)
255
+ if (success) {
256
+ nav.navigate('TxSuccessScreen', { txid })
257
+ } else {
258
+ throw new Error(error)
259
+ }
260
+ } catch (e) {
261
+ nav.navigate('TxFailScreen', { error: (e as any).message })
262
+ }
263
+ }
264
+
265
+ const signPsbtParams: SignPsbtParams = {
266
+ data: {
267
+ toSignDatas: [
268
+ {
269
+ psbtHex: contextData.rawTxInfo.psbtHex,
270
+ toSignInputs: undefined,
271
+ autoFinalized: true,
272
+ },
273
+ ],
274
+ },
275
+ }
276
+
277
+ return {
278
+ signPsbtParams,
279
+ onSignPsbtConfirm,
280
+ }
281
+ }
282
+
283
+ export function useTransferableListLogic({ contextData, updateContextData }: BRC20SendStepParams) {
284
+ const wallet = useWallet()
285
+ const currentAccount = useCurrentAccount()
286
+ const { t } = useI18n()
287
+
288
+ const [items, setItems] = useState<TokenTransfer[]>([])
289
+ const [total, setTotal] = useState(0)
290
+ const [loading, setLoading] = useState(false)
291
+ const [loadingLump, setLoadingLump] = useState(false)
292
+ const [pagination, setPagination] = useState({ currentPage: 1, pageSize: 100 })
293
+ const [allSelected, setAllSelected] = useState(false)
294
+
295
+ const tools = useTools()
296
+ const fetchData = async () => {
297
+ try {
298
+ setLoading(true)
299
+ const { list, total } = await wallet.getBRC20TransferableList(
300
+ currentAccount.address,
301
+ contextData.tokenBalance.ticker,
302
+ pagination.currentPage,
303
+ pagination.pageSize
304
+ )
305
+ setItems(list)
306
+ setTotal(total)
307
+ } catch (e) {
308
+ tools.toastError((e as Error).message)
309
+ } finally {
310
+ setLoading(false)
311
+ }
312
+ }
313
+
314
+ useEffect(() => {
315
+ fetchData()
316
+ }, [pagination])
317
+ const totalAmount = items
318
+ .reduce((pre, cur) => new BigNumber(cur.amount).plus(pre), new BigNumber(0))
319
+ .toString()
320
+
321
+ const selectedCount = useMemo(() => contextData.inscriptionIdSet.size, [contextData])
322
+
323
+ const onClickItem = (item: TokenTransfer) => {
324
+ if (contextData.inscriptionIdSet.has(item.inscriptionId)) {
325
+ const inscriptionIdSet = new Set(contextData.inscriptionIdSet)
326
+ inscriptionIdSet.delete(item.inscriptionId)
327
+ const transferAmount = new BigNumber(contextData.transferAmount).minus(
328
+ new BigNumber(item.amount)
329
+ )
330
+ updateContextData({
331
+ inscriptionIdSet,
332
+ transferAmount: transferAmount.toString(),
333
+ })
334
+ if (allSelected) {
335
+ setAllSelected(false)
336
+ }
337
+ } else {
338
+ const inscriptionIdSet = new Set(contextData.inscriptionIdSet)
339
+ inscriptionIdSet.add(item.inscriptionId)
340
+ const transferAmount = new BigNumber(contextData.transferAmount)
341
+ .plus(new BigNumber(item.amount))
342
+ .toString()
343
+ updateContextData({
344
+ inscriptionIdSet,
345
+ transferAmount,
346
+ })
347
+ if (allSelected == false && transferAmount === totalAmount) {
348
+ setAllSelected(true)
349
+ }
350
+ }
351
+ }
352
+
353
+ const onCheckBoxChange = e => {
354
+ const val = e.target.checked
355
+ setAllSelected(val)
356
+ if (val) {
357
+ const inscriptionIdSet = new Set(items.map(v => v.inscriptionId))
358
+ updateContextData({
359
+ inscriptionIdSet,
360
+ transferAmount: totalAmount,
361
+ })
362
+ } else {
363
+ updateContextData({
364
+ inscriptionIdSet: new Set(),
365
+ transferAmount: '0',
366
+ })
367
+ }
368
+ }
369
+
370
+ const onClickCheckBoxInMobile = () => {
371
+ setLoadingLump(true)
372
+ setAllSelected(!allSelected)
373
+ startTransition(() => {
374
+ if (!allSelected) {
375
+ const inscriptionIdSet = new Set(items.map(v => v.inscriptionId))
376
+ updateContextData({
377
+ inscriptionIdSet,
378
+ transferAmount: totalAmount,
379
+ })
380
+ } else {
381
+ updateContextData({
382
+ inscriptionIdSet: new Set(),
383
+ transferAmount: '0',
384
+ })
385
+ }
386
+ })
387
+ setLoadingLump(false)
388
+ }
389
+
390
+ const onClickRefresh = () => {
391
+ fetchData()
392
+ }
393
+
394
+ return {
395
+ // data
396
+ items,
397
+ selectedCount,
398
+ allSelected,
399
+ loading,
400
+ loadingLump,
401
+
402
+ // actions
403
+ onClickItem,
404
+ onCheckBoxChange,
405
+ onClickCheckBoxInMobile,
406
+ onClickRefresh,
407
+
408
+ // tools
409
+ t,
410
+ }
411
+ }
@@ -0,0 +1,208 @@
1
+ import { bnUtils } from '@unisat/base-utils'
2
+ import { Inscription, SignPsbtParams, SignPsbtResult, ToSignData } from '@unisat/wallet-shared'
3
+ import { useEffect, useMemo, useRef, useState } from 'react'
4
+ import { useI18n, useNavigation, useTools, useWallet } from 'src/context'
5
+ import { useCurrentAccount, useFeeRateBar, useRunesTx } from 'src/hooks'
6
+ import { getAddressUtxoDust, isValidAddress } from 'src/utils/bitcoin-utils'
7
+
8
+ export enum BRC20SingleStepKey {
9
+ STEP1 = 'STEP1',
10
+ STEP2 = 'STEP2',
11
+ STEP3 = 'STEP3',
12
+ }
13
+
14
+ export function useBRC20SingleStepScreenLogic() {
15
+ const nav = useNavigation()
16
+ const props = nav.getRouteState<'BRC20SingleStepScreen'>()
17
+ const { t } = useI18n()
18
+
19
+ const tokenBalance = props.tokenBalance
20
+ const tokenInfo = props.tokenInfo
21
+
22
+ const tools = useTools()
23
+
24
+ const runesTx = useRunesTx()
25
+ const [inputAmount, setInputAmount] = useState('')
26
+ const [disabled, setDisabled] = useState(true)
27
+ const [toInfo, setToInfo] = useState<{
28
+ address: string
29
+ domain: string
30
+ inscription?: Inscription
31
+ }>({
32
+ address: runesTx.toAddress,
33
+ domain: runesTx.toDomain,
34
+ inscription: undefined,
35
+ })
36
+
37
+ const [availableBalance, setAvailableBalance] = useState(tokenBalance.overallBalance)
38
+ const [error, setError] = useState('')
39
+
40
+ const defaultOutputValue = 546
41
+
42
+ const currentAccount = useCurrentAccount()
43
+ const [outputValue, setOutputValue] = useState(defaultOutputValue)
44
+ const minOutputValue = useMemo(() => {
45
+ if (toInfo.address) {
46
+ const dust1 = getAddressUtxoDust(currentAccount.address)
47
+ const dust2 = getAddressUtxoDust(toInfo.address)
48
+ return Math.max(dust1, dust2)
49
+ } else {
50
+ return 0
51
+ }
52
+ }, [toInfo.address, currentAccount.address])
53
+
54
+ const { feeRate } = useFeeRateBar()
55
+
56
+ useEffect(() => {
57
+ setError('')
58
+ setDisabled(true)
59
+
60
+ if (!isValidAddress(toInfo.address)) {
61
+ return
62
+ }
63
+ if (!inputAmount) {
64
+ return
65
+ }
66
+
67
+ if (feeRate <= 0) {
68
+ return
69
+ }
70
+
71
+ if (bnUtils.compareAmount(inputAmount, availableBalance)! > 0) {
72
+ setError(t('insufficient_balance'))
73
+ return
74
+ }
75
+
76
+ setDisabled(false)
77
+ }, [toInfo, inputAmount, feeRate, outputValue, minOutputValue, availableBalance])
78
+
79
+ const wallet = useWallet()
80
+ const transferData = useRef<{
81
+ id: string
82
+ commitToSignData: ToSignData
83
+ revealToSignData: ToSignData
84
+ }>({
85
+ id: '',
86
+ commitToSignData: {
87
+ psbtHex: '',
88
+ toSignInputs: [],
89
+ },
90
+ revealToSignData: {
91
+ psbtHex: '',
92
+ toSignInputs: [],
93
+ },
94
+ })
95
+ const [step, setStep] = useState<BRC20SingleStepKey>(BRC20SingleStepKey.STEP1)
96
+
97
+ const signPsbtParamsStep2: SignPsbtParams = {
98
+ data: {
99
+ toSignDatas: [transferData.current.commitToSignData],
100
+ },
101
+ }
102
+
103
+ const signPsbtParamsStep3: SignPsbtParams = {
104
+ data: {
105
+ toSignDatas: [transferData.current.revealToSignData],
106
+ },
107
+ }
108
+
109
+ const onClickBack = () => {
110
+ if (step === BRC20SingleStepKey.STEP1) {
111
+ nav.goBack()
112
+ } else if (step === BRC20SingleStepKey.STEP2) {
113
+ setStep(BRC20SingleStepKey.STEP1)
114
+ } else if (step === BRC20SingleStepKey.STEP3) {
115
+ setStep(BRC20SingleStepKey.STEP2)
116
+ } else {
117
+ nav.goBack()
118
+ }
119
+ }
120
+
121
+ const onClickConfirmStep1 = async () => {
122
+ tools.showLoading(true)
123
+ try {
124
+ const step1 = await wallet.singleStepTransferBRC20Step1({
125
+ userAddress: currentAccount.address,
126
+ userPubkey: currentAccount.pubkey,
127
+ receiver: toInfo.address,
128
+ ticker: tokenBalance.ticker,
129
+ amount: inputAmount,
130
+ feeRate,
131
+ })
132
+ if (step1) {
133
+ transferData.current.id = step1.orderId
134
+ transferData.current.commitToSignData = step1.toSignData
135
+ setStep(BRC20SingleStepKey.STEP2)
136
+ }
137
+ } catch (e) {
138
+ const msg = (e as any).message
139
+ setError((e as any).message)
140
+ } finally {
141
+ tools.showLoading(false)
142
+ }
143
+ }
144
+
145
+ const onClickConfirmStep2 = async (signPsbtResult: SignPsbtResult) => {
146
+ try {
147
+ tools.showLoading(true)
148
+
149
+ const step2 = await wallet.singleStepTransferBRC20Step2({
150
+ orderId: transferData.current.id,
151
+ commitTx: signPsbtResult[0].psbtHex,
152
+ })
153
+
154
+ transferData.current.revealToSignData = step2.toSignData
155
+
156
+ setStep(BRC20SingleStepKey.STEP3)
157
+ } catch (e) {
158
+ console.log(e)
159
+ } finally {
160
+ tools.showLoading(false)
161
+ }
162
+ }
163
+
164
+ const onClickConfirmStep3 = async (signPsbtResult: SignPsbtResult) => {
165
+ tools.showLoading(true)
166
+ try {
167
+ const step3 = await wallet.singleStepTransferBRC20Step3({
168
+ orderId: transferData.current.id,
169
+ revealTx: signPsbtResult[0].psbtHex,
170
+ })
171
+ nav.navigate('TxSuccessScreen', { txid: step3.txid })
172
+ } catch (e) {
173
+ nav.navigate('TxFailScreen', { error: (e as any).message })
174
+ } finally {
175
+ tools.showLoading(false)
176
+ }
177
+ }
178
+
179
+ return {
180
+ // data
181
+ signPsbtParamsStep2,
182
+ signPsbtParamsStep3,
183
+
184
+ availableBalance,
185
+ tokenBalance,
186
+ tokenInfo,
187
+ inputAmount,
188
+ setInputAmount,
189
+ disabled,
190
+ error,
191
+ toInfo,
192
+ setToInfo,
193
+
194
+ // state
195
+ step,
196
+
197
+ // actions
198
+ onClickBack,
199
+
200
+ onClickConfirmStep1,
201
+ onClickConfirmStep2,
202
+ onClickConfirmStep3,
203
+
204
+ // utils
205
+ t,
206
+ tools,
207
+ }
208
+ }