-
-
Notifications
You must be signed in to change notification settings - Fork 283
/
Copy pathaddressManager.ts
103 lines (81 loc) · 3.27 KB
/
addressManager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { isNotUndefined, arrayDistinct, objectPartition } from '@trezor/utils';
import type { Network } from '@trezor/utxo-lib';
import type { AccountAddresses, SubscriptionAccountInfo } from '@trezor/blockchain-link-types/src';
import { addressToScripthash } from './transform';
type AddressMap = { [address: string]: string };
type AccountMap = { [descriptor: string]: AccountAddresses };
const addressesFromAccounts = (array: (AccountAddresses | undefined)[]) =>
array
.filter(isNotUndefined)
.flatMap(({ change, used, unused }) =>
change.concat(used, unused).map(({ address }) => address),
);
export const createAddressManager = (getNetwork: () => Network | undefined) => {
let subscribedAddrs: AddressMap = {};
let subscribedAccs: AccountMap = {};
const addAddresses = (addresses: string[]) => {
const toAdd = addresses.filter(arrayDistinct).filter(addr => !subscribedAddrs[addr]);
const network = getNetwork();
subscribedAddrs = toAdd.reduce<AddressMap>(
(dic, addr) => ({
...dic,
[addr]: addressToScripthash(addr, network),
}),
subscribedAddrs,
);
return toAdd.map(addr => subscribedAddrs[addr]);
};
const removeAddresses = (addresses?: string[]) => {
const [toRemove, toPreserve] = addresses
? objectPartition(subscribedAddrs, addresses)
: [subscribedAddrs, {}];
subscribedAddrs = toPreserve;
return Object.values(toRemove);
};
const addAccounts = (accounts: SubscriptionAccountInfo[]) => {
const toAdd = accounts.filter(acc => !subscribedAccs[acc.descriptor]);
subscribedAccs = toAdd.reduce<AccountMap>(
(dic, acc) => ({
...dic,
[acc.descriptor]: acc.addresses || { change: [], used: [], unused: [] },
}),
subscribedAccs,
);
const addresses = addressesFromAccounts(toAdd.map(acc => acc.addresses));
return addAddresses(addresses);
};
const removeAccounts = (accounts?: SubscriptionAccountInfo[]) => {
const [toRemove, toPreserve] = accounts
? objectPartition(
subscribedAccs,
accounts.map(({ descriptor }) => descriptor),
)
: [subscribedAccs, {}];
subscribedAccs = toPreserve;
const addresses = addressesFromAccounts(Object.values(toRemove));
return removeAddresses(addresses);
};
const getCount = () => Object.keys(subscribedAddrs).length;
const getInfo = (scripthash: string) => {
const [address, _sh] =
Object.entries(subscribedAddrs).find(([_addr, sh]) => sh === scripthash) || [];
if (!address) return { descriptor: scripthash };
const [account, addresses] =
Object.entries(subscribedAccs).find(
([_acc, { change, unused, used }]) =>
!!change.concat(used, unused).find(ad => ad.address === address),
) || [];
return {
descriptor: account || address,
addresses,
};
};
return {
addAddresses,
removeAddresses,
addAccounts,
removeAccounts,
getCount,
getInfo,
};
};