edge-core-js 2.41.2 → 2.42.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.
- package/CHANGELOG.md +14 -0
- package/android/src/main/assets/edge-core-js/edge-core.js +1 -1
- package/ios/EdgeCoreModule.swift +16 -1
- package/lib/core/account/account-api.js +39 -11
- package/lib/core/account/memory-wallet.js +48 -40
- package/lib/core/actions.js +1 -0
- package/lib/core/currency/wallet/currency-wallet-api.js +20 -1
- package/lib/core/currency/wallet/currency-wallet-callbacks.js +17 -3
- package/lib/core/currency/wallet/currency-wallet-reducer.js +9 -4
- package/lib/core/login/splitting.js +114 -55
- package/lib/flow/types.js +47 -7
- package/lib/flow/webby.js +35 -0
- package/lib/node/index.js +1177 -1080
- package/lib/types/types.js +40 -0
- package/lib/util/edgeResult.js +11 -0
- package/package.json +1 -1
- package/src/types/types.ts +47 -7
- package/src/types/webby.js +33 -0
package/ios/EdgeCoreModule.swift
CHANGED
|
@@ -7,9 +7,24 @@ class EdgeCoreModule: NSObject {
|
|
|
7
7
|
@objc static func requiresMainQueueSetup() -> Bool { return false }
|
|
8
8
|
|
|
9
9
|
@objc func constantsToExport() -> [AnyHashable: Any]! {
|
|
10
|
+
// Derive the app root URI using the same two-level Bundle lookup that
|
|
11
|
+
// plugin native modules use: find a .bundle resource, create a sub-Bundle,
|
|
12
|
+
// then call url(forResource:) on the sub-Bundle. This produces file:// URLs
|
|
13
|
+
// without /private, matching the plugin sourceUri values.
|
|
14
|
+
var rootBaseUri = Bundle.main.bundleURL.absoluteString
|
|
15
|
+
if let bundleUrl = Bundle.main.url(forResource: "edge-core-js", withExtension: "bundle"),
|
|
16
|
+
let bundle = Bundle(url: bundleUrl),
|
|
17
|
+
let coreUrl = bundle.url(forResource: "edge-core", withExtension: "js")
|
|
18
|
+
{
|
|
19
|
+
// Go up two levels: edge-core.js -> edge-core-js.bundle/ -> Edge.app/
|
|
20
|
+
rootBaseUri = coreUrl
|
|
21
|
+
.deletingLastPathComponent()
|
|
22
|
+
.deletingLastPathComponent()
|
|
23
|
+
.absoluteString
|
|
24
|
+
}
|
|
10
25
|
return [
|
|
11
26
|
"bundleBaseUri": BUNDLE_BASE_URI,
|
|
12
|
-
"rootBaseUri":
|
|
27
|
+
"rootBaseUri": rootBaseUri,
|
|
13
28
|
]
|
|
14
29
|
}
|
|
15
30
|
}
|
|
@@ -28,6 +28,7 @@ import { AccountSync, fixUsername } from '../../client-side'
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
import { makeEdgeResult } from '../../util/edgeResult'
|
|
31
32
|
import { base58 } from '../../util/encoding'
|
|
32
33
|
import { getPublicWalletInfo } from '../currency/wallet/currency-wallet-pixie'
|
|
33
34
|
import {
|
|
@@ -502,7 +503,42 @@ export function makeAccountApi(ai, accountId) {
|
|
|
502
503
|
walletId,
|
|
503
504
|
newWalletType
|
|
504
505
|
) {
|
|
505
|
-
|
|
506
|
+
const { allWalletInfosFull } = accountState()
|
|
507
|
+
const walletInfo = allWalletInfosFull.find(
|
|
508
|
+
walletInfo => walletInfo.id === walletId
|
|
509
|
+
)
|
|
510
|
+
if (walletInfo == null) throw new Error(`Invalid wallet id ${walletId}`)
|
|
511
|
+
const existingWallet =
|
|
512
|
+
_optionalChain([ai, 'access', _2 => _2.props, 'access', _3 => _3.output, 'optionalAccess', _4 => _4.currency, 'optionalAccess', _5 => _5.wallets, 'access', _6 => _6[walletInfo.id], 'optionalAccess', _7 => _7.walletApi])
|
|
513
|
+
|
|
514
|
+
// The following check has not been needed since about 2021,
|
|
515
|
+
// when the currency plugins became responsible for listing
|
|
516
|
+
// their own splittable types, but keep it for safety:
|
|
517
|
+
if (
|
|
518
|
+
walletInfo.type === 'wallet:bitcoin' &&
|
|
519
|
+
walletInfo.keys.format === 'bip49' &&
|
|
520
|
+
newWalletType === 'wallet:bitcoincash'
|
|
521
|
+
) {
|
|
522
|
+
throw new Error(
|
|
523
|
+
'Cannot split segwit-format Bitcoin wallets to Bitcoin Cash'
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const [result] = await splitWalletInfo(
|
|
528
|
+
ai,
|
|
529
|
+
accountId,
|
|
530
|
+
walletInfo,
|
|
531
|
+
[
|
|
532
|
+
{
|
|
533
|
+
walletType: newWalletType,
|
|
534
|
+
name: _nullishCoalesce(_optionalChain([existingWallet, 'optionalAccess', _8 => _8.name]), () => ( undefined)),
|
|
535
|
+
fiatCurrencyCode: _optionalChain([existingWallet, 'optionalAccess', _9 => _9.fiatCurrencyCode])
|
|
536
|
+
}
|
|
537
|
+
],
|
|
538
|
+
true
|
|
539
|
+
)
|
|
540
|
+
if (result.ok) return result.result.id
|
|
541
|
+
throw result.error
|
|
506
542
|
},
|
|
507
543
|
|
|
508
544
|
async listSplittableWalletTypes(walletId) {
|
|
@@ -750,7 +786,7 @@ export function makeAccountApi(ai, accountId) {
|
|
|
750
786
|
throw new Error(
|
|
751
787
|
`activateWallet unsupported by walletId ${activateWalletId}`
|
|
752
788
|
)
|
|
753
|
-
const walletId = _nullishCoalesce(_optionalChain([paymentInfo, 'optionalAccess',
|
|
789
|
+
const walletId = _nullishCoalesce(_optionalChain([paymentInfo, 'optionalAccess', _10 => _10.walletId]), () => ( ''))
|
|
754
790
|
const wallet = currencyWallets[walletId]
|
|
755
791
|
|
|
756
792
|
if (wallet == null) {
|
|
@@ -769,7 +805,7 @@ export function makeAccountApi(ai, accountId) {
|
|
|
769
805
|
|
|
770
806
|
// Added for backward compatibility for plugins using core 1.x
|
|
771
807
|
// @ts-expect-error
|
|
772
|
-
paymentTokenId: _optionalChain([paymentInfo, 'optionalAccess',
|
|
808
|
+
paymentTokenId: _optionalChain([paymentInfo, 'optionalAccess', _11 => _11.tokenId]),
|
|
773
809
|
paymentWallet: wallet
|
|
774
810
|
})
|
|
775
811
|
|
|
@@ -828,11 +864,3 @@ function getRawPrivateKey(
|
|
|
828
864
|
}
|
|
829
865
|
return info
|
|
830
866
|
}
|
|
831
|
-
|
|
832
|
-
async function makeEdgeResult(promise) {
|
|
833
|
-
try {
|
|
834
|
-
return { ok: true, result: await promise }
|
|
835
|
-
} catch (error) {
|
|
836
|
-
return { ok: false, error }
|
|
837
|
-
}
|
|
838
|
-
}
|
|
@@ -11,6 +11,8 @@ import { bridgifyObject, close, update, watchMethod } from 'yaob'
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
|
|
15
|
+
|
|
14
16
|
import { makePeriodicTask, } from '../../util/periodic-task'
|
|
15
17
|
import { snooze } from '../../util/snooze'
|
|
16
18
|
import { getMaxSpendableInner } from '../currency/wallet/max-spend'
|
|
@@ -43,7 +45,7 @@ export const makeMemoryWalletInner = async (
|
|
|
43
45
|
const log = makeLog(ai.props.logBackend, `${walletId}-${walletType}`)
|
|
44
46
|
let balanceMap = new Map()
|
|
45
47
|
let detectedTokenIds = []
|
|
46
|
-
let
|
|
48
|
+
let syncStatus = { totalRatio: 0 }
|
|
47
49
|
|
|
48
50
|
let needsUpdate = false
|
|
49
51
|
const updateWallet = () => {
|
|
@@ -58,51 +60,54 @@ export const makeMemoryWalletInner = async (
|
|
|
58
60
|
}, 0)
|
|
59
61
|
|
|
60
62
|
const plugin = ai.props.state.plugins.currency[config.currencyInfo.pluginId]
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
syncRatio = progressRatio
|
|
69
|
-
needsUpdate = true
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
onNewTokens: (tokenIds) => {
|
|
73
|
-
const sortedTokenIds = tokenIds.sort((a, b) => a.localeCompare(b))
|
|
63
|
+
const callbacks = {
|
|
64
|
+
onAddressChanged: () => {},
|
|
65
|
+
onAddressesChecked(totalRatio) {
|
|
66
|
+
callbacks.onSyncStatusChanged({ totalRatio })
|
|
67
|
+
},
|
|
68
|
+
onNewTokens: (tokenIds) => {
|
|
69
|
+
const sortedTokenIds = tokenIds.sort((a, b) => a.localeCompare(b))
|
|
74
70
|
|
|
75
|
-
|
|
71
|
+
if (detectedTokenIds.length !== sortedTokenIds.length) {
|
|
72
|
+
detectedTokenIds = sortedTokenIds
|
|
73
|
+
needsUpdate = true
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
for (let i = 0; i < sortedTokenIds.length; i++) {
|
|
77
|
+
if (detectedTokenIds[i] !== sortedTokenIds[i]) {
|
|
76
78
|
detectedTokenIds = sortedTokenIds
|
|
77
79
|
needsUpdate = true
|
|
78
80
|
return
|
|
79
81
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
onStakingStatusChanged: () => {},
|
|
90
|
-
onSubscribeAddresses: () => {},
|
|
91
|
-
onTokenBalanceChanged: (tokenId, balance) => {
|
|
92
|
-
if (balanceMap.get(tokenId) === balance) return
|
|
93
|
-
|
|
94
|
-
balanceMap = new Map(balanceMap)
|
|
95
|
-
balanceMap.set(tokenId, balance)
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
onSeenTxCheckpoint: () => {},
|
|
85
|
+
onStakingStatusChanged: () => {},
|
|
86
|
+
onSubscribeAddresses: () => {},
|
|
87
|
+
onSyncStatusChanged(status) {
|
|
88
|
+
if (syncStatus.totalRatio === 1) return
|
|
89
|
+
if (status.totalRatio === 1) {
|
|
90
|
+
syncStatus = status
|
|
96
91
|
needsUpdate = true
|
|
97
|
-
}
|
|
98
|
-
onTransactions: () => {},
|
|
99
|
-
onTransactionsChanged: () => {},
|
|
100
|
-
onTxidsChanged: () => {},
|
|
101
|
-
onUnactivatedTokenIdsChanged: () => {},
|
|
102
|
-
onWcNewContractCall: () => {},
|
|
103
|
-
onBlockHeightChanged: () => {},
|
|
104
|
-
onBalanceChanged: () => {}
|
|
92
|
+
}
|
|
105
93
|
},
|
|
94
|
+
onTokenBalanceChanged: (tokenId, balance) => {
|
|
95
|
+
if (balanceMap.get(tokenId) === balance) return
|
|
96
|
+
|
|
97
|
+
balanceMap = new Map(balanceMap)
|
|
98
|
+
balanceMap.set(tokenId, balance)
|
|
99
|
+
needsUpdate = true
|
|
100
|
+
},
|
|
101
|
+
onTransactions: () => {},
|
|
102
|
+
onTransactionsChanged: () => {},
|
|
103
|
+
onTxidsChanged: () => {},
|
|
104
|
+
onUnactivatedTokenIdsChanged: () => {},
|
|
105
|
+
onWcNewContractCall: () => {},
|
|
106
|
+
onBlockHeightChanged: () => {},
|
|
107
|
+
onBalanceChanged: () => {}
|
|
108
|
+
}
|
|
109
|
+
const engine = await plugin.makeCurrencyEngine(walletInfo, {
|
|
110
|
+
callbacks,
|
|
106
111
|
customTokens: { ...config.customTokens },
|
|
107
112
|
enabledTokenIds: [...Object.keys(config.allTokens)],
|
|
108
113
|
lightMode: true,
|
|
@@ -151,7 +156,10 @@ export const makeMemoryWalletInner = async (
|
|
|
151
156
|
return detectedTokenIds
|
|
152
157
|
},
|
|
153
158
|
get syncRatio() {
|
|
154
|
-
return
|
|
159
|
+
return syncStatus.totalRatio
|
|
160
|
+
},
|
|
161
|
+
get syncStatus() {
|
|
162
|
+
return syncStatus
|
|
155
163
|
},
|
|
156
164
|
async changeEnabledTokenIds(tokenIds) {
|
|
157
165
|
if (engine.changeEnabledTokenIds != null) {
|
package/lib/core/actions.js
CHANGED
|
@@ -35,11 +35,15 @@ import {
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
38
41
|
|
|
39
42
|
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
import { makeMetaTokens } from '../../account/custom-tokens'
|
|
46
|
+
import { splitWalletInfo } from '../../login/splitting'
|
|
43
47
|
import { toApiInput } from '../../root-pixie'
|
|
44
48
|
import { makeStorageWalletApi } from '../../storage/storage-api'
|
|
45
49
|
import { getCurrencyMultiplier } from '../currency-selectors'
|
|
@@ -201,7 +205,10 @@ export function makeCurrencyWalletApi(
|
|
|
201
205
|
return skipBlockHeight ? 0 : input.props.walletState.height
|
|
202
206
|
},
|
|
203
207
|
get syncRatio() {
|
|
204
|
-
return input.props.walletState.
|
|
208
|
+
return input.props.walletState.syncStatus.totalRatio
|
|
209
|
+
},
|
|
210
|
+
get syncStatus() {
|
|
211
|
+
return input.props.walletState.syncStatus
|
|
205
212
|
},
|
|
206
213
|
get unactivatedTokenIds() {
|
|
207
214
|
return input.props.walletState.unactivatedTokenIds
|
|
@@ -727,6 +734,18 @@ export function makeCurrencyWalletApi(
|
|
|
727
734
|
emit(out, 'transactionsRemoved', undefined)
|
|
728
735
|
},
|
|
729
736
|
|
|
737
|
+
async split(
|
|
738
|
+
splitWallets
|
|
739
|
+
) {
|
|
740
|
+
return await splitWalletInfo(
|
|
741
|
+
ai,
|
|
742
|
+
accountId,
|
|
743
|
+
walletInfo,
|
|
744
|
+
splitWallets,
|
|
745
|
+
false
|
|
746
|
+
)
|
|
747
|
+
},
|
|
748
|
+
|
|
730
749
|
// URI handling:
|
|
731
750
|
async encodeUri(options) {
|
|
732
751
|
return await tools.encodeUri(
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
|
|
19
20
|
import { compare } from '../../../util/compare'
|
|
20
21
|
import { enableTestMode, pushUpdate } from '../../../util/updateQueue'
|
|
21
22
|
import {
|
|
@@ -118,11 +119,11 @@ export function makeCurrencyWalletCallbacks(
|
|
|
118
119
|
onAddressesChecked(ratio) {
|
|
119
120
|
pushUpdate({
|
|
120
121
|
id: walletId,
|
|
121
|
-
action: '
|
|
122
|
+
action: 'onSyncStatusChanged',
|
|
122
123
|
updateFunc: () => {
|
|
123
124
|
input.props.dispatch({
|
|
124
|
-
type: '
|
|
125
|
-
payload: { ratio, walletId }
|
|
125
|
+
type: 'CURRENCY_ENGINE_CHANGED_SYNC_STATUS',
|
|
126
|
+
payload: { status: { totalRatio: ratio }, walletId }
|
|
126
127
|
})
|
|
127
128
|
}
|
|
128
129
|
})
|
|
@@ -317,6 +318,19 @@ export function makeCurrencyWalletCallbacks(
|
|
|
317
318
|
})
|
|
318
319
|
},
|
|
319
320
|
|
|
321
|
+
onSyncStatusChanged(syncStatus) {
|
|
322
|
+
pushUpdate({
|
|
323
|
+
id: walletId,
|
|
324
|
+
action: 'onSyncStatusChanged',
|
|
325
|
+
updateFunc: () => {
|
|
326
|
+
input.props.dispatch({
|
|
327
|
+
type: 'CURRENCY_ENGINE_CHANGED_SYNC_STATUS',
|
|
328
|
+
payload: { status: syncStatus, walletId }
|
|
329
|
+
})
|
|
330
|
+
}
|
|
331
|
+
})
|
|
332
|
+
},
|
|
333
|
+
|
|
320
334
|
onTransactions(txEvents) {
|
|
321
335
|
const { accountId, currencyInfo, pluginId } = input.props.walletState
|
|
322
336
|
const allTokens =
|
|
@@ -14,6 +14,7 @@ import { buildReducer, filterReducer, memoizeReducer } from 'redux-keto'
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
import { compare } from '../../../util/compare'
|
|
18
19
|
|
|
19
20
|
import { findCurrencyPluginId } from '../../plugins/plugins-selectors'
|
|
@@ -120,6 +121,10 @@ import { uniqueStrings } from './enabled-tokens'
|
|
|
120
121
|
// Used for detectedTokenIds & enabledTokenIds:
|
|
121
122
|
export const initialTokenIds = []
|
|
122
123
|
|
|
124
|
+
export const initialSyncStatus = {
|
|
125
|
+
totalRatio: 0
|
|
126
|
+
}
|
|
127
|
+
|
|
123
128
|
const currencyWalletInner = buildReducer
|
|
124
129
|
|
|
125
130
|
|
|
@@ -314,13 +319,13 @@ const currencyWalletInner = buildReducer
|
|
|
314
319
|
return state
|
|
315
320
|
},
|
|
316
321
|
|
|
317
|
-
|
|
322
|
+
syncStatus(state = initialSyncStatus, action) {
|
|
318
323
|
switch (action.type) {
|
|
319
|
-
case '
|
|
320
|
-
return action.payload.
|
|
324
|
+
case 'CURRENCY_ENGINE_CHANGED_SYNC_STATUS': {
|
|
325
|
+
return action.payload.status
|
|
321
326
|
}
|
|
322
327
|
case 'CURRENCY_ENGINE_CLEARED': {
|
|
323
|
-
return
|
|
328
|
+
return initialSyncStatus
|
|
324
329
|
}
|
|
325
330
|
}
|
|
326
331
|
return state
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { asMaybe } from 'cleaners'
|
|
1
|
+
function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }import { asMaybe } from 'cleaners'
|
|
2
2
|
import { base64 } from 'rfc4648'
|
|
3
3
|
|
|
4
4
|
|
|
@@ -7,7 +7,11 @@ import { base64 } from 'rfc4648'
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
import { hmacSha256 } from '../../util/crypto/hashes'
|
|
14
|
+
import { makeEdgeResult } from '../../util/edgeResult'
|
|
11
15
|
import { utf8 } from '../../util/encoding'
|
|
12
16
|
import { changeWalletStates } from '../account/account-files'
|
|
13
17
|
import { waitForCurrencyWallet } from '../currency/currency-selectors'
|
|
@@ -102,80 +106,135 @@ export function makeSplitWalletInfo(
|
|
|
102
106
|
export async function splitWalletInfo(
|
|
103
107
|
ai,
|
|
104
108
|
accountId,
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
walletInfo,
|
|
110
|
+
splitWallets,
|
|
111
|
+
rejectDupes
|
|
107
112
|
) {
|
|
108
113
|
const accountState = ai.props.state.accounts[accountId]
|
|
109
114
|
const { allWalletInfosFull, sessionKey } = accountState
|
|
110
115
|
|
|
111
|
-
//
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
'Cannot split segwit-format Bitcoin wallets to Bitcoin Cash'
|
|
125
|
-
)
|
|
116
|
+
// Validate the wallet types:
|
|
117
|
+
const plugins = ai.props.state.plugins.currency
|
|
118
|
+
const splitInfos = new Map()
|
|
119
|
+
for (const item of splitWallets) {
|
|
120
|
+
const { walletType } = item
|
|
121
|
+
const pluginId = maybeFindCurrencyPluginId(plugins, item.walletType)
|
|
122
|
+
if (pluginId == null) {
|
|
123
|
+
throw new Error(`Cannot find plugin for wallet type "${walletType}"`)
|
|
124
|
+
}
|
|
125
|
+
if (splitInfos.has(walletType)) {
|
|
126
|
+
throw new Error(`Duplicate wallet type "${walletType}"`)
|
|
127
|
+
}
|
|
128
|
+
splitInfos.set(walletType, makeSplitWalletInfo(walletInfo, walletType))
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
//
|
|
131
|
+
// Do we need BitcoinABC/SV replay protection?
|
|
129
132
|
const needsProtection =
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
walletInfo.type === 'wallet:bitcoincash' &&
|
|
134
|
+
// We can re-protect a wallet by doing a repeated split,
|
|
135
|
+
// so don't check if the wallet already exists:
|
|
136
|
+
splitInfos.has('wallet:bitcoinsv')
|
|
132
137
|
if (needsProtection) {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
138
|
+
const existingWallet =
|
|
139
|
+
_optionalChain([ai, 'access', _ => _.props, 'access', _2 => _2.output, 'optionalAccess', _3 => _3.currency, 'optionalAccess', _4 => _4.wallets, 'access', _5 => _5[walletInfo.id], 'optionalAccess', _6 => _6.walletApi])
|
|
140
|
+
if (existingWallet == null) {
|
|
141
|
+
throw new Error(`Cannot find wallet ${walletInfo.id}`)
|
|
142
|
+
}
|
|
143
|
+
await protectBchWallet(existingWallet)
|
|
136
144
|
}
|
|
137
145
|
|
|
138
|
-
//
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
// Sort the wallet infos into two categories:
|
|
147
|
+
const toRestore = []
|
|
148
|
+
const toCreate = []
|
|
149
|
+
for (const newWalletInfo of splitInfos.values()) {
|
|
150
|
+
const existingWalletInfo = allWalletInfosFull.find(
|
|
151
|
+
info => info.id === newWalletInfo.id
|
|
152
|
+
)
|
|
153
|
+
if (existingWalletInfo == null) {
|
|
154
|
+
toCreate.push(newWalletInfo)
|
|
155
|
+
} else {
|
|
156
|
+
if (existingWalletInfo.archived || existingWalletInfo.deleted) {
|
|
157
|
+
toRestore.push(existingWalletInfo)
|
|
158
|
+
} else if (rejectDupes) {
|
|
159
|
+
if (
|
|
160
|
+
// It's OK to re-split if we are adding protection:
|
|
161
|
+
walletInfo.type !== 'wallet:bitcoincash' ||
|
|
162
|
+
newWalletInfo.type !== 'wallet:bitcoinsv'
|
|
163
|
+
) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`This wallet has already been split (${newWalletInfo.type})`
|
|
166
|
+
)
|
|
167
|
+
}
|
|
151
168
|
}
|
|
152
|
-
await changeWalletStates(ai, accountId, walletInfos)
|
|
153
|
-
return newWalletInfo.id
|
|
154
169
|
}
|
|
155
|
-
|
|
156
|
-
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Restore anything that has simply been deleted:
|
|
173
|
+
if (toRestore.length > 0) {
|
|
174
|
+
const newStates = {}
|
|
175
|
+
let hasChanges = false
|
|
176
|
+
for (const existingWalletInfo of toRestore) {
|
|
177
|
+
if (existingWalletInfo.archived || existingWalletInfo.deleted) {
|
|
178
|
+
hasChanges = true
|
|
179
|
+
newStates[existingWalletInfo.id] = {
|
|
180
|
+
archived: false,
|
|
181
|
+
deleted: false,
|
|
182
|
+
migratedFromWalletId: existingWalletInfo.migratedFromWalletId
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (hasChanges) await changeWalletStates(ai, accountId, newStates)
|
|
157
187
|
}
|
|
158
188
|
|
|
159
189
|
// Add the keys to the login:
|
|
160
|
-
|
|
161
|
-
|
|
190
|
+
if (toCreate.length > 0) {
|
|
191
|
+
const kit = makeKeysKit(ai, sessionKey, toCreate, true)
|
|
192
|
+
await applyKit(ai, sessionKey, kit)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Wait for the new wallets to load:
|
|
196
|
+
const out = await Promise.all(
|
|
197
|
+
splitWallets.map(async splitInfo => {
|
|
198
|
+
const walletInfo = splitInfos.get(splitInfo.walletType)
|
|
199
|
+
if (walletInfo == null) {
|
|
200
|
+
throw new Error(`Missing wallet info for ${splitInfo.walletType}`)
|
|
201
|
+
}
|
|
202
|
+
return await makeEdgeResult(
|
|
203
|
+
finishWalletSplitting(
|
|
204
|
+
ai,
|
|
205
|
+
walletInfo.id,
|
|
206
|
+
toCreate.find(info => info.type === splitInfo.walletType) != null
|
|
207
|
+
? splitInfo
|
|
208
|
+
: undefined
|
|
209
|
+
)
|
|
210
|
+
)
|
|
211
|
+
})
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
return out
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function finishWalletSplitting(
|
|
218
|
+
ai,
|
|
219
|
+
walletId,
|
|
220
|
+
item
|
|
221
|
+
) {
|
|
222
|
+
const wallet = await waitForCurrencyWallet(ai, walletId)
|
|
162
223
|
|
|
163
224
|
// Try to copy metadata on a best-effort basis.
|
|
164
225
|
// In the future we should clone the repo instead:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
} catch (error) {
|
|
175
|
-
ai.props.onError(error)
|
|
226
|
+
if (_optionalChain([item, 'optionalAccess', _7 => _7.name]) != null) {
|
|
227
|
+
await wallet
|
|
228
|
+
.renameWallet(item.name)
|
|
229
|
+
.catch((error) => ai.props.onError(error))
|
|
230
|
+
}
|
|
231
|
+
if (_optionalChain([item, 'optionalAccess', _8 => _8.fiatCurrencyCode]) != null) {
|
|
232
|
+
await wallet
|
|
233
|
+
.setFiatCurrencyCode(item.fiatCurrencyCode)
|
|
234
|
+
.catch((error) => ai.props.onError(error))
|
|
176
235
|
}
|
|
177
236
|
|
|
178
|
-
return
|
|
237
|
+
return wallet
|
|
179
238
|
}
|
|
180
239
|
|
|
181
240
|
async function protectBchWallet(wallet) {
|