mainnet-js 3.1.7 → 4.0.0-next.10
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/dist/module/cache/IndexedDbCache.d.ts +1 -1
- package/dist/module/cache/IndexedDbCache.d.ts.map +1 -1
- package/dist/module/cache/MemoryCache.d.ts +1 -1
- package/dist/module/cache/MemoryCache.d.ts.map +1 -1
- package/dist/module/cache/WebStorageCache.d.ts +1 -1
- package/dist/module/cache/WebStorageCache.d.ts.map +1 -1
- package/dist/module/cache/walletCache.d.ts +16 -6
- package/dist/module/cache/walletCache.d.ts.map +1 -1
- package/dist/module/cache/walletCache.js +92 -34
- package/dist/module/cache/walletCache.js.map +1 -1
- package/dist/module/cli.js +1 -2
- package/dist/module/cli.js.map +1 -1
- package/dist/module/db/index.d.ts +1 -1
- package/dist/module/db/index.d.ts.map +1 -1
- package/dist/module/db/index.js +1 -1
- package/dist/module/db/index.js.map +1 -1
- package/dist/module/enum.d.ts +1 -1
- package/dist/module/enum.d.ts.map +1 -1
- package/dist/module/history/getHistory.d.ts +1 -1
- package/dist/module/history/getHistory.d.ts.map +1 -1
- package/dist/module/history/getHistory.js +3 -3
- package/dist/module/history/getHistory.js.map +1 -1
- package/dist/module/index.d.ts +25 -22
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +33 -26
- package/dist/module/index.js.map +1 -1
- package/dist/module/interface.d.ts +12 -2
- package/dist/module/interface.d.ts.map +1 -1
- package/dist/module/interface.js.map +1 -1
- package/dist/module/libauth.d.ts +1 -1
- package/dist/module/libauth.d.ts.map +1 -1
- package/dist/module/libauth.js +1 -1
- package/dist/module/libauth.js.map +1 -1
- package/dist/module/mine/mine.d.ts +2 -7
- package/dist/module/mine/mine.d.ts.map +1 -1
- package/dist/module/mine/mine.js +6 -27
- package/dist/module/mine/mine.js.map +1 -1
- package/dist/module/network/Connection.d.ts +1 -12
- package/dist/module/network/Connection.d.ts.map +1 -1
- package/dist/module/network/Connection.js +24 -33
- package/dist/module/network/Connection.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts +16 -17
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +91 -93
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/MockNetworkProvider.d.ts +28 -0
- package/dist/module/network/MockNetworkProvider.d.ts.map +1 -0
- package/dist/module/network/MockNetworkProvider.js +74 -0
- package/dist/module/network/MockNetworkProvider.js.map +1 -0
- package/dist/module/network/NetworkProvider.d.ts +9 -2
- package/dist/module/network/NetworkProvider.d.ts.map +1 -1
- package/dist/module/network/configuration.d.ts +2 -4
- package/dist/module/network/configuration.d.ts.map +1 -1
- package/dist/module/network/configuration.js +25 -50
- package/dist/module/network/configuration.js.map +1 -1
- package/dist/module/network/constant.d.ts +7 -7
- package/dist/module/network/constant.d.ts.map +1 -1
- package/dist/module/network/constant.js +21 -24
- package/dist/module/network/constant.js.map +1 -1
- package/dist/module/network/default.d.ts +5 -3
- package/dist/module/network/default.d.ts.map +1 -1
- package/dist/module/network/default.js +29 -51
- package/dist/module/network/default.js.map +1 -1
- package/dist/module/network/index.d.ts +4 -4
- package/dist/module/network/index.d.ts.map +1 -1
- package/dist/module/network/index.js +2 -2
- package/dist/module/network/index.js.map +1 -1
- package/dist/module/network/interface.d.ts +0 -6
- package/dist/module/network/interface.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.d.ts +1 -1
- package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.js +13 -7
- package/dist/module/rate/ExchangeRate.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +3 -3
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +4 -4
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/transaction/allocateFee.d.ts +1 -1
- package/dist/module/transaction/allocateFee.d.ts.map +1 -1
- package/dist/module/transaction/allocateFee.js +2 -2
- package/dist/module/transaction/allocateFee.js.map +1 -1
- package/dist/module/util/deriveCashaddr.js.map +1 -1
- package/dist/module/util/deriveNetwork.js +1 -1
- package/dist/module/util/deriveNetwork.js.map +1 -1
- package/dist/module/util/getAddrsByXpubKey.js +1 -1
- package/dist/module/util/getAddrsByXpubKey.js.map +1 -1
- package/dist/module/util/getXPubKey.js +1 -1
- package/dist/module/util/getXPubKey.js.map +1 -1
- package/dist/module/util/hd.d.ts +2 -0
- package/dist/module/util/hd.d.ts.map +1 -1
- package/dist/module/util/hd.js +41 -0
- package/dist/module/util/hd.js.map +1 -1
- package/dist/module/util/index.d.ts +7 -9
- package/dist/module/util/index.d.ts.map +1 -1
- package/dist/module/util/index.js +7 -9
- package/dist/module/util/index.js.map +1 -1
- package/dist/module/util/transaction.js +1 -1
- package/dist/module/util/transaction.js.map +1 -1
- package/dist/module/wallet/Base.d.ts +13 -9
- package/dist/module/wallet/Base.d.ts.map +1 -1
- package/dist/module/wallet/Base.js +54 -58
- package/dist/module/wallet/Base.js.map +1 -1
- package/dist/module/wallet/HDWallet.d.ts.map +1 -1
- package/dist/module/wallet/HDWallet.js +19 -38
- package/dist/module/wallet/HDWallet.js.map +1 -1
- package/dist/module/wallet/Util.d.ts +4 -22
- package/dist/module/wallet/Util.d.ts.map +1 -1
- package/dist/module/wallet/Util.js +75 -102
- package/dist/module/wallet/Util.js.map +1 -1
- package/dist/module/wallet/Watch.d.ts +24 -5
- package/dist/module/wallet/Watch.d.ts.map +1 -1
- package/dist/module/wallet/Watch.js +141 -17
- package/dist/module/wallet/Watch.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts +2 -6
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +3 -69
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/createWallet.d.ts +1 -1
- package/dist/module/wallet/createWallet.d.ts.map +1 -1
- package/dist/module/wallet/createWallet.js +2 -1
- package/dist/module/wallet/createWallet.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +3 -2
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +2 -1
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js +1 -1
- package/dist/module/wallet/model.js.map +1 -1
- package/package.json +17 -29
- package/dist/index.html +0 -9
- package/dist/mainnet-3.1.7.js +0 -2066
- package/dist/module/network/util.d.ts +0 -3
- package/dist/module/network/util.d.ts.map +0 -1
- package/dist/module/network/util.js +0 -27
- package/dist/module/network/util.js.map +0 -1
- package/dist/module/test/expect.d.ts +0 -12
- package/dist/module/test/expect.d.ts.map +0 -1
- package/dist/module/test/expect.js +0 -47
- package/dist/module/test/expect.js.map +0 -1
- package/dist/module/test/fetch.d.ts +0 -3
- package/dist/module/test/fetch.d.ts.map +0 -1
- package/dist/module/test/fetch.js +0 -32
- package/dist/module/test/fetch.js.map +0 -1
- package/dist/module/util/randomBytes.d.ts +0 -2
- package/dist/module/util/randomBytes.d.ts.map +0 -1
- package/dist/module/util/randomBytes.js +0 -13
- package/dist/module/util/randomBytes.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/cache/IndexedDbCache.test.ts +0 -15
- package/src/cache/IndexedDbCache.ts +0 -172
- package/src/cache/MemoryCache.test.ts +0 -15
- package/src/cache/MemoryCache.ts +0 -32
- package/src/cache/WebStorageCache.test.ts +0 -15
- package/src/cache/WebStorageCache.ts +0 -38
- package/src/cache/index.ts +0 -2
- package/src/cache/interface.ts +0 -9
- package/src/cache/walletCache.ts +0 -254
- package/src/chain.ts +0 -3
- package/src/cli.ts +0 -32
- package/src/config.ts +0 -23
- package/src/constant.ts +0 -27
- package/src/db/ExchangeRateProvider.ts +0 -28
- package/src/db/StorageProvider.ts +0 -64
- package/src/db/index.ts +0 -2
- package/src/db/interface.ts +0 -11
- package/src/enum.ts +0 -34
- package/src/history/getHistory.test.ts +0 -290
- package/src/history/getHistory.ts +0 -411
- package/src/history/interface.ts +0 -24
- package/src/index.ts +0 -48
- package/src/interface.ts +0 -72
- package/src/libauth.ts +0 -11
- package/src/message/index.ts +0 -2
- package/src/message/interface.ts +0 -40
- package/src/message/signed.test.ts +0 -309
- package/src/message/signed.ts +0 -201
- package/src/mine/index.ts +0 -1
- package/src/mine/mine.test.ts +0 -10
- package/src/mine/mine.ts +0 -42
- package/src/network/Connection.test.ts +0 -51
- package/src/network/Connection.ts +0 -73
- package/src/network/ElectrumNetworkProvider.ts +0 -657
- package/src/network/NetworkProvider.ts +0 -180
- package/src/network/Rpc.test.ts +0 -130
- package/src/network/configuration.test.ts +0 -59
- package/src/network/configuration.ts +0 -72
- package/src/network/constant.ts +0 -43
- package/src/network/default.ts +0 -120
- package/src/network/electrum.test.ts +0 -28
- package/src/network/getRelayFeeCache.test.ts +0 -15
- package/src/network/getRelayFeeCache.ts +0 -23
- package/src/network/index.ts +0 -14
- package/src/network/interface.ts +0 -80
- package/src/network/util.test.ts +0 -24
- package/src/network/util.ts +0 -30
- package/src/rate/ExchangeRate.test.headless.js +0 -35
- package/src/rate/ExchangeRate.test.ts +0 -51
- package/src/rate/ExchangeRate.ts +0 -142
- package/src/test/expect.ts +0 -59
- package/src/test/fetch.ts +0 -39
- package/src/test/json.test.ts +0 -13
- package/src/transaction/Wif.ts +0 -680
- package/src/transaction/allocateFee.test.ts +0 -298
- package/src/transaction/allocateFee.ts +0 -149
- package/src/util/amountInSatoshi.test.ts +0 -27
- package/src/util/amountInSatoshi.ts +0 -33
- package/src/util/asSendRequestObject.ts +0 -81
- package/src/util/base64.test.ts +0 -39
- package/src/util/base64.ts +0 -12
- package/src/util/browserNotSupported.ts +0 -7
- package/src/util/checkForEmptySeed.ts +0 -9
- package/src/util/checkUtxos.ts +0 -29
- package/src/util/checkWifNetwork.ts +0 -24
- package/src/util/convert.test.ts +0 -46
- package/src/util/convert.ts +0 -50
- package/src/util/delay.ts +0 -3
- package/src/util/deriveCashaddr.test.ts +0 -164
- package/src/util/deriveCashaddr.ts +0 -143
- package/src/util/deriveLockscript.ts +0 -16
- package/src/util/deriveNetwork.ts +0 -19
- package/src/util/derivePublicKeyHash.test.ts +0 -55
- package/src/util/derivePublicKeyHash.ts +0 -64
- package/src/util/floor.test.ts +0 -21
- package/src/util/floor.ts +0 -4
- package/src/util/getAddrsByXpubKey.test.ts +0 -115
- package/src/util/getAddrsByXpubKey.ts +0 -86
- package/src/util/getRuntimePlatform.test.headless.js +0 -40
- package/src/util/getRuntimePlatform.test.ts +0 -5
- package/src/util/getRuntimePlatform.ts +0 -31
- package/src/util/getUsdRate.ts +0 -5
- package/src/util/getXPubKey.ts +0 -39
- package/src/util/hash160.test.ts +0 -18
- package/src/util/hash160.ts +0 -12
- package/src/util/hd.ts +0 -16
- package/src/util/header.test.ts +0 -34
- package/src/util/header.ts +0 -26
- package/src/util/index.ts +0 -33
- package/src/util/randomBytes.ts +0 -13
- package/src/util/randomInt.test.ts +0 -15
- package/src/util/randomInt.ts +0 -4
- package/src/util/sanitizeAddress.ts +0 -10
- package/src/util/sanitizeUnit.ts +0 -11
- package/src/util/satoshiToAmount.test.ts +0 -6
- package/src/util/satoshiToAmount.ts +0 -33
- package/src/util/sumSendRequestAmounts.ts +0 -34
- package/src/util/sumUtxoValue.ts +0 -27
- package/src/util/transaction.ts +0 -10
- package/src/wallet/Base.ts +0 -1563
- package/src/wallet/Cashtokens.test.headless.js +0 -730
- package/src/wallet/Cashtokens.test.ts +0 -1411
- package/src/wallet/HDWallet.test.ts +0 -1086
- package/src/wallet/HDWallet.ts +0 -992
- package/src/wallet/Util.test.ts +0 -134
- package/src/wallet/Util.ts +0 -191
- package/src/wallet/WalletCache.test.ts +0 -45
- package/src/wallet/Watch.ts +0 -441
- package/src/wallet/Wif.bip39.test.ts +0 -48
- package/src/wallet/Wif.test.ts +0 -1189
- package/src/wallet/Wif.ts +0 -687
- package/src/wallet/Wif.watchOnly.test.ts +0 -58
- package/src/wallet/createWallet.ts +0 -238
- package/src/wallet/enum.ts +0 -18
- package/src/wallet/interface.ts +0 -102
- package/src/wallet/model.test.ts +0 -24
- package/src/wallet/model.ts +0 -352
- package/tsconfig.browser.json +0 -11
- package/tsconfig.json +0 -33
- package/webpack.config.cjs +0 -132
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
import { RegTestWallet, Wallet } from "../wallet/Wif";
|
|
2
|
-
import { WalletTypeEnum } from "../wallet/enum";
|
|
3
|
-
import { createWallet } from "../wallet/createWallet";
|
|
4
|
-
import { mine } from "../mine";
|
|
5
|
-
import { encodeCashAddress } from "@bitauth/libauth";
|
|
6
|
-
import { toBch } from "../util";
|
|
7
|
-
|
|
8
|
-
test("Should get miner history", async () => {
|
|
9
|
-
const alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF!);
|
|
10
|
-
const history = await alice.getHistory();
|
|
11
|
-
expect(history.length).toBeGreaterThan(0);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
// // This class transforms outputs from electrum to a standard array of history.
|
|
15
|
-
test("Should get an address history", async () => {
|
|
16
|
-
// Build Alice's wallet from Wallet Import Format string
|
|
17
|
-
if (!process.env.PRIVATE_WIF) {
|
|
18
|
-
throw Error("Attempted to pass an empty WIF");
|
|
19
|
-
} else {
|
|
20
|
-
let alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF); // insert WIF from #1
|
|
21
|
-
const bob = await createWallet({
|
|
22
|
-
type: WalletTypeEnum.Wif,
|
|
23
|
-
network: "regtest",
|
|
24
|
-
});
|
|
25
|
-
const charlie = await createWallet({
|
|
26
|
-
type: WalletTypeEnum.Wif,
|
|
27
|
-
network: "regtest",
|
|
28
|
-
});
|
|
29
|
-
let sendResponse = await alice.send([
|
|
30
|
-
{
|
|
31
|
-
cashaddr: bob.cashaddr!,
|
|
32
|
-
value: 31000n,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
cashaddr: charlie.cashaddr!,
|
|
36
|
-
value: 41000n,
|
|
37
|
-
},
|
|
38
|
-
]);
|
|
39
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
40
|
-
await bob.send([
|
|
41
|
-
{
|
|
42
|
-
cashaddr: charlie.cashaddr!,
|
|
43
|
-
value: 2100n,
|
|
44
|
-
},
|
|
45
|
-
]);
|
|
46
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
47
|
-
await bob.send([
|
|
48
|
-
{
|
|
49
|
-
cashaddr: alice.cashaddr!,
|
|
50
|
-
value: 2100n,
|
|
51
|
-
},
|
|
52
|
-
]);
|
|
53
|
-
expect(sendResponse!.txId!.length).toBe(64);
|
|
54
|
-
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
55
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
56
|
-
|
|
57
|
-
// Build Bob's wallet from a public address, check his balance.
|
|
58
|
-
const bobHistory = await bob.getHistory();
|
|
59
|
-
expect(bobHistory[0].valueChange).toBe(-2320);
|
|
60
|
-
expect(
|
|
61
|
-
bobHistory[0].outputs.some(
|
|
62
|
-
(output) => output.address === alice.getDepositAddress()
|
|
63
|
-
)
|
|
64
|
-
).toBe(true);
|
|
65
|
-
expect(
|
|
66
|
-
bobHistory[0].inputs.some(
|
|
67
|
-
(input) => input.address === bob.getDepositAddress()
|
|
68
|
-
)
|
|
69
|
-
).toBe(true);
|
|
70
|
-
expect(bobHistory[1].valueChange).toBe(-2320);
|
|
71
|
-
expect(
|
|
72
|
-
bobHistory[1].inputs.some(
|
|
73
|
-
(input) => input.address === bob.getDepositAddress()
|
|
74
|
-
)
|
|
75
|
-
).toBe(true);
|
|
76
|
-
expect(
|
|
77
|
-
bobHistory[1].outputs.some(
|
|
78
|
-
(output) => output.address === charlie.getDepositAddress()
|
|
79
|
-
)
|
|
80
|
-
).toBe(true);
|
|
81
|
-
expect(bobHistory[2].valueChange).toBe(31000);
|
|
82
|
-
expect(bobHistory[2].balance).toBe(31000);
|
|
83
|
-
expect(bobHistory[2].fee).not.toBe(0);
|
|
84
|
-
expect(
|
|
85
|
-
bobHistory[2].inputs.some(
|
|
86
|
-
(input) => input.address === alice.getDepositAddress()
|
|
87
|
-
)
|
|
88
|
-
).toBe(true);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
// This class transforms outputs from electrum to a standard array of history.
|
|
93
|
-
test("Should get a history with multi-party sends", async () => {
|
|
94
|
-
// Build Alice's wallet from Wallet Import Format string
|
|
95
|
-
if (!process.env.PRIVATE_WIF) {
|
|
96
|
-
throw Error("Attempted to pass an empty WIF");
|
|
97
|
-
} else {
|
|
98
|
-
let alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF); // insert WIF from #1
|
|
99
|
-
const bob = await createWallet({
|
|
100
|
-
type: WalletTypeEnum.Wif,
|
|
101
|
-
network: "regtest",
|
|
102
|
-
});
|
|
103
|
-
const charlie = await createWallet({
|
|
104
|
-
type: WalletTypeEnum.Wif,
|
|
105
|
-
network: "regtest",
|
|
106
|
-
});
|
|
107
|
-
let sendResponse = await alice.send([
|
|
108
|
-
{
|
|
109
|
-
cashaddr: bob.cashaddr!,
|
|
110
|
-
value: 31000n,
|
|
111
|
-
},
|
|
112
|
-
]);
|
|
113
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
114
|
-
await bob.send([
|
|
115
|
-
{
|
|
116
|
-
cashaddr: charlie.cashaddr!,
|
|
117
|
-
value: 2100n,
|
|
118
|
-
},
|
|
119
|
-
]);
|
|
120
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
121
|
-
await bob.send([
|
|
122
|
-
{
|
|
123
|
-
cashaddr: alice.cashaddr!,
|
|
124
|
-
value: 2100n,
|
|
125
|
-
},
|
|
126
|
-
]);
|
|
127
|
-
expect(sendResponse!.txId!.length).toBe(64);
|
|
128
|
-
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
129
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
130
|
-
|
|
131
|
-
// Build Bob's wallet from a public address, check his balance.
|
|
132
|
-
const bobHistory = await bob.getHistory();
|
|
133
|
-
|
|
134
|
-
expect(bobHistory[1].fee).toBeGreaterThan(120);
|
|
135
|
-
expect(bobHistory[1].fee).toBe(220);
|
|
136
|
-
expect(bobHistory[0].valueChange).toBe(-2320);
|
|
137
|
-
expect(
|
|
138
|
-
bobHistory[0].outputs.some(
|
|
139
|
-
(output) => output.address === alice.getDepositAddress()
|
|
140
|
-
)
|
|
141
|
-
).toBe(true);
|
|
142
|
-
expect(
|
|
143
|
-
bobHistory[0].inputs.some(
|
|
144
|
-
(input) => input.address === bob.getDepositAddress()
|
|
145
|
-
)
|
|
146
|
-
).toBe(true);
|
|
147
|
-
expect(bobHistory[1].valueChange).toBe(-2320);
|
|
148
|
-
expect(
|
|
149
|
-
bobHistory[1].outputs.some(
|
|
150
|
-
(output) => output.address === charlie.getDepositAddress()
|
|
151
|
-
)
|
|
152
|
-
).toBe(true);
|
|
153
|
-
expect(
|
|
154
|
-
bobHistory[1].inputs.some(
|
|
155
|
-
(input) => input.address === bob.getDepositAddress()
|
|
156
|
-
)
|
|
157
|
-
).toBe(true);
|
|
158
|
-
|
|
159
|
-
expect(bobHistory[2].valueChange).toBe(31000);
|
|
160
|
-
expect(bobHistory[2].fee).not.toBe(0);
|
|
161
|
-
expect(
|
|
162
|
-
bobHistory[2].inputs.some(
|
|
163
|
-
(input) => input.address === alice.getDepositAddress()
|
|
164
|
-
)
|
|
165
|
-
).toBe(true);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// This class transforms outputs from electrum to a standard array of history.
|
|
170
|
-
test("Should cut results with a longer history to given count", async () => {
|
|
171
|
-
// Build Alice's wallet from Wallet Import Format string
|
|
172
|
-
if (!process.env.PRIVATE_WIF) {
|
|
173
|
-
throw Error("Attempted to pass an empty WIF");
|
|
174
|
-
} else {
|
|
175
|
-
let alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF); // insert WIF from #1
|
|
176
|
-
const bob = await createWallet({
|
|
177
|
-
type: WalletTypeEnum.Wif,
|
|
178
|
-
network: "regtest",
|
|
179
|
-
});
|
|
180
|
-
const charlie = await createWallet({
|
|
181
|
-
type: WalletTypeEnum.Wif,
|
|
182
|
-
network: "regtest",
|
|
183
|
-
});
|
|
184
|
-
let sendResponse = await alice.send([
|
|
185
|
-
{
|
|
186
|
-
cashaddr: bob.cashaddr!,
|
|
187
|
-
value: 31000n,
|
|
188
|
-
},
|
|
189
|
-
]);
|
|
190
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
191
|
-
await bob.send([
|
|
192
|
-
{
|
|
193
|
-
cashaddr: charlie.cashaddr!,
|
|
194
|
-
value: 2100n,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
cashaddr: alice.cashaddr!,
|
|
198
|
-
value: 2100n,
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
cashaddr: alice.cashaddr!,
|
|
202
|
-
value: 2100n,
|
|
203
|
-
},
|
|
204
|
-
]);
|
|
205
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
206
|
-
expect(sendResponse!.txId!.length).toBe(64);
|
|
207
|
-
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
208
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
209
|
-
|
|
210
|
-
// Build Bob's wallet from a public address, check his balance.
|
|
211
|
-
const bobHistory = await bob.getHistory({
|
|
212
|
-
unit: "sat",
|
|
213
|
-
start: 0,
|
|
214
|
-
count: 2,
|
|
215
|
-
});
|
|
216
|
-
expect(bobHistory.length).toBe(2);
|
|
217
|
-
|
|
218
|
-
expect(bobHistory[0].valueChange).toBe(-6588);
|
|
219
|
-
expect(
|
|
220
|
-
bobHistory[0].outputs.some(
|
|
221
|
-
(output) => output.address === alice.getDepositAddress()
|
|
222
|
-
)
|
|
223
|
-
).toBe(true);
|
|
224
|
-
expect(bobHistory[1].valueChange).toBe(31000);
|
|
225
|
-
expect(
|
|
226
|
-
bobHistory[1].outputs.some(
|
|
227
|
-
(output) => output.address === alice.getDepositAddress()
|
|
228
|
-
)
|
|
229
|
-
).toBe(true);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// This class transforms outputs from electrum to a standard array of history.
|
|
234
|
-
test("Should handle input and fee from many utxos", async () => {
|
|
235
|
-
// Build Alice's wallet from Wallet Import Format string
|
|
236
|
-
if (!process.env.PRIVATE_WIF) {
|
|
237
|
-
throw Error("Attempted to pass an empty WIF");
|
|
238
|
-
} else {
|
|
239
|
-
let alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF); // insert WIF from #1
|
|
240
|
-
const bob = await createWallet({
|
|
241
|
-
type: WalletTypeEnum.Wif,
|
|
242
|
-
network: "regtest",
|
|
243
|
-
});
|
|
244
|
-
const charlie = await createWallet({
|
|
245
|
-
type: WalletTypeEnum.Wif,
|
|
246
|
-
network: "regtest",
|
|
247
|
-
});
|
|
248
|
-
let sendResponse = await alice.send([
|
|
249
|
-
{
|
|
250
|
-
cashaddr: bob.cashaddr!,
|
|
251
|
-
value: 600n,
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
cashaddr: bob.cashaddr!,
|
|
255
|
-
value: 600n,
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
cashaddr: bob.cashaddr!,
|
|
259
|
-
value: 600n,
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
cashaddr: bob.cashaddr!,
|
|
263
|
-
value: 600n,
|
|
264
|
-
},
|
|
265
|
-
]);
|
|
266
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
267
|
-
await bob.sendMax(charlie.cashaddr!);
|
|
268
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
269
|
-
expect(sendResponse!.txId!.length).toBe(64);
|
|
270
|
-
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
271
|
-
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
272
|
-
|
|
273
|
-
// Build Bob's wallet from a public address, check his balance.
|
|
274
|
-
const bobHistory = await bob.getHistory({
|
|
275
|
-
unit: "sat",
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
expect(bobHistory[0].valueChange).toBeLessThan(-1700);
|
|
279
|
-
expect(
|
|
280
|
-
bobHistory[0].outputs.some(
|
|
281
|
-
(output) => output.address === charlie.getDepositAddress()
|
|
282
|
-
)
|
|
283
|
-
).toBe(true);
|
|
284
|
-
expect(
|
|
285
|
-
bobHistory[1].inputs.some(
|
|
286
|
-
(input) => input.address === alice.getDepositAddress()
|
|
287
|
-
)
|
|
288
|
-
).toBe(true);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
binToHex,
|
|
3
|
-
decodeTransaction,
|
|
4
|
-
hexToBin,
|
|
5
|
-
lockingBytecodeToCashAddress,
|
|
6
|
-
CashAddressNetworkPrefix,
|
|
7
|
-
decodeCashAddress,
|
|
8
|
-
TransactionCommon,
|
|
9
|
-
assertSuccess,
|
|
10
|
-
Opcodes,
|
|
11
|
-
} from "@bitauth/libauth";
|
|
12
|
-
import { UnitEnum } from "../enum.js";
|
|
13
|
-
import NetworkProvider from "../network/NetworkProvider.js";
|
|
14
|
-
import { TxI } from "../interface.js";
|
|
15
|
-
import { TransactionHistoryItem, InOutput } from "./interface.js";
|
|
16
|
-
import { ExchangeRate } from "../rate/ExchangeRate.js";
|
|
17
|
-
import { sanitizeUnit } from "../util/sanitizeUnit.js";
|
|
18
|
-
import { bchParam } from "../chain.js";
|
|
19
|
-
|
|
20
|
-
type Transaction = TransactionCommon & {
|
|
21
|
-
size: number;
|
|
22
|
-
blockHeight: number;
|
|
23
|
-
timestamp?: number;
|
|
24
|
-
hash: string;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const getHistory = async ({
|
|
28
|
-
addresses,
|
|
29
|
-
provider,
|
|
30
|
-
unit = "sat",
|
|
31
|
-
fromHeight = 0,
|
|
32
|
-
toHeight = -1,
|
|
33
|
-
start = 0,
|
|
34
|
-
count = -1,
|
|
35
|
-
rawHistory,
|
|
36
|
-
}: {
|
|
37
|
-
addresses: string[];
|
|
38
|
-
provider: NetworkProvider;
|
|
39
|
-
unit?: UnitEnum;
|
|
40
|
-
fromHeight?: number;
|
|
41
|
-
toHeight?: number;
|
|
42
|
-
start?: number;
|
|
43
|
-
count?: number;
|
|
44
|
-
rawHistory?: TxI[];
|
|
45
|
-
}): Promise<TransactionHistoryItem[]> => {
|
|
46
|
-
if (!addresses.length) {
|
|
47
|
-
return [];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (count === -1) {
|
|
51
|
-
count = 1e10;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
let history: TxI[];
|
|
55
|
-
if (rawHistory) {
|
|
56
|
-
history = rawHistory.slice(start, start + count);
|
|
57
|
-
} else {
|
|
58
|
-
const allHistory = (
|
|
59
|
-
await Promise.all(
|
|
60
|
-
addresses.map(async (address) =>
|
|
61
|
-
provider.getHistory(address, fromHeight, toHeight)
|
|
62
|
-
)
|
|
63
|
-
)
|
|
64
|
-
).flat();
|
|
65
|
-
|
|
66
|
-
// Dedup using Set instead of O(N²) findIndex
|
|
67
|
-
const seen = new Set<string>();
|
|
68
|
-
const deduped: TxI[] = [];
|
|
69
|
-
for (const item of allHistory) {
|
|
70
|
-
if (!seen.has(item.tx_hash)) {
|
|
71
|
-
seen.add(item.tx_hash);
|
|
72
|
-
deduped.push(item);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
history = deduped
|
|
77
|
-
.sort((a, b) =>
|
|
78
|
-
a.height <= 0 || b.height <= 0
|
|
79
|
-
? a.height - b.height
|
|
80
|
-
: b.height - a.height
|
|
81
|
-
)
|
|
82
|
-
.slice(start, start + count);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Collect unique heights for header fetch
|
|
86
|
-
const uniqueHeightsSet = new Set<number>();
|
|
87
|
-
for (const tx of history) {
|
|
88
|
-
if (tx.height > 0) uniqueHeightsSet.add(tx.height);
|
|
89
|
-
}
|
|
90
|
-
const uniqueHeights = [...uniqueHeightsSet];
|
|
91
|
-
|
|
92
|
-
// Batch fetch headers and history transactions in parallel
|
|
93
|
-
const historyHashes = history.map((tx) => tx.tx_hash);
|
|
94
|
-
const [headerMap, txHexMap] = await Promise.all([
|
|
95
|
-
uniqueHeights.length > 0 ? provider.getHeaders(uniqueHeights) : new Map(),
|
|
96
|
-
provider.getRawTransactions(historyHashes),
|
|
97
|
-
] as const);
|
|
98
|
-
|
|
99
|
-
const timestampMap: Record<number, number> = {};
|
|
100
|
-
for (const [height, header] of headerMap) {
|
|
101
|
-
timestampMap[height] = header.timestamp;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Precompute binToHex for each input's outpoint hash once
|
|
105
|
-
const inputOutpointHashes = new WeakMap<Uint8Array, string>();
|
|
106
|
-
const getOutpointHash = (bytes: Uint8Array): string => {
|
|
107
|
-
let hash = inputOutpointHashes.get(bytes);
|
|
108
|
-
if (hash === undefined) {
|
|
109
|
-
hash = binToHex(bytes);
|
|
110
|
-
inputOutpointHashes.set(bytes, hash);
|
|
111
|
-
}
|
|
112
|
-
return hash;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const historicTransactions = history.map((tx) => {
|
|
116
|
-
const txHex = txHexMap.get(tx.tx_hash)!;
|
|
117
|
-
const transactionCommon = decodeTransaction(hexToBin(txHex));
|
|
118
|
-
if (typeof transactionCommon === "string") {
|
|
119
|
-
throw transactionCommon;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const transaction = transactionCommon as Transaction;
|
|
123
|
-
transaction.blockHeight = tx.height;
|
|
124
|
-
transaction.timestamp = timestampMap[tx.height];
|
|
125
|
-
transaction.hash = tx.tx_hash;
|
|
126
|
-
transaction.size = txHex.length / 2;
|
|
127
|
-
|
|
128
|
-
return transaction;
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Collect unique prevout hashes using Set, excluding already-fetched txs
|
|
132
|
-
const ZERO_HASH =
|
|
133
|
-
"0000000000000000000000000000000000000000000000000000000000000000";
|
|
134
|
-
const prevoutHashSet = new Set<string>();
|
|
135
|
-
for (const tx of historicTransactions) {
|
|
136
|
-
for (const input of tx.inputs) {
|
|
137
|
-
const hash = getOutpointHash(input.outpointTransactionHash);
|
|
138
|
-
if (hash !== ZERO_HASH && !txHexMap.has(hash)) {
|
|
139
|
-
prevoutHashSet.add(hash);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Batch fetch prevout transactions
|
|
145
|
-
const prevoutHashes = [...prevoutHashSet];
|
|
146
|
-
const prevoutHexMap = await provider.getRawTransactions(prevoutHashes);
|
|
147
|
-
|
|
148
|
-
// Build prevout transaction map (decode all prevout txs)
|
|
149
|
-
const prevoutTransactionMap: Record<string, TransactionCommon> = {};
|
|
150
|
-
const allPrevoutSources = new Map([...txHexMap, ...prevoutHexMap]);
|
|
151
|
-
for (const tx of historicTransactions) {
|
|
152
|
-
for (const input of tx.inputs) {
|
|
153
|
-
const hash = getOutpointHash(input.outpointTransactionHash);
|
|
154
|
-
if (hash === ZERO_HASH || prevoutTransactionMap[hash]) continue;
|
|
155
|
-
|
|
156
|
-
const hex = allPrevoutSources.get(hash);
|
|
157
|
-
if (!hex) continue;
|
|
158
|
-
|
|
159
|
-
const decoded = decodeTransaction(hexToBin(hex));
|
|
160
|
-
if (typeof decoded === "string") {
|
|
161
|
-
throw decoded;
|
|
162
|
-
}
|
|
163
|
-
prevoutTransactionMap[hash] = decoded;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const decoded = assertSuccess(decodeCashAddress(addresses[0]));
|
|
168
|
-
const prefix = decoded.prefix as CashAddressNetworkPrefix;
|
|
169
|
-
|
|
170
|
-
const addressCache: Record<any, string> = {};
|
|
171
|
-
const addressSet = new Set(addresses);
|
|
172
|
-
|
|
173
|
-
// map decoded transaction data to TransactionHistoryItem
|
|
174
|
-
const historyItems = historicTransactions.map((tx) => {
|
|
175
|
-
const result = {} as TransactionHistoryItem;
|
|
176
|
-
|
|
177
|
-
let inputTotalValue = 0n;
|
|
178
|
-
let outputTotalValue = 0n;
|
|
179
|
-
|
|
180
|
-
const isCoinbase =
|
|
181
|
-
tx.inputs.length === 1 &&
|
|
182
|
-
tx.inputs[0].outpointTransactionHash.every((b) => b === 0);
|
|
183
|
-
|
|
184
|
-
result.inputs = tx.inputs.map((input): InOutput => {
|
|
185
|
-
if (isCoinbase) {
|
|
186
|
-
const halvings = Math.floor(tx.blockHeight / 210000);
|
|
187
|
-
const subsidy = Math.floor(5000000000 / 2 ** halvings);
|
|
188
|
-
inputTotalValue += BigInt(subsidy);
|
|
189
|
-
|
|
190
|
-
return {
|
|
191
|
-
address: "coinbase",
|
|
192
|
-
value: subsidy,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const prevoutTx =
|
|
197
|
-
prevoutTransactionMap[getOutpointHash(input.outpointTransactionHash)];
|
|
198
|
-
if (!prevoutTx) {
|
|
199
|
-
throw new Error("Could not find prevout transaction");
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const prevoutOutput = prevoutTx.outputs[input.outpointIndex];
|
|
203
|
-
if (!prevoutOutput) {
|
|
204
|
-
throw new Error("Could not find prevout output");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const cached = addressCache[prevoutOutput.lockingBytecode as any];
|
|
208
|
-
let address: string;
|
|
209
|
-
if (!cached) {
|
|
210
|
-
address = assertSuccess(
|
|
211
|
-
lockingBytecodeToCashAddress({
|
|
212
|
-
bytecode: prevoutOutput.lockingBytecode,
|
|
213
|
-
prefix: prefix,
|
|
214
|
-
})
|
|
215
|
-
).address;
|
|
216
|
-
addressCache[prevoutOutput.lockingBytecode as any] = address;
|
|
217
|
-
} else {
|
|
218
|
-
address = cached;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
inputTotalValue += prevoutOutput.valueSatoshis;
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
address: address,
|
|
225
|
-
value: Number(prevoutOutput.valueSatoshis),
|
|
226
|
-
token: prevoutOutput.token
|
|
227
|
-
? {
|
|
228
|
-
category: binToHex(prevoutOutput.token.category),
|
|
229
|
-
amount: prevoutOutput.token.amount,
|
|
230
|
-
nft: prevoutOutput.token.nft
|
|
231
|
-
? {
|
|
232
|
-
capability: prevoutOutput.token.nft.capability,
|
|
233
|
-
commitment: binToHex(prevoutOutput.token.nft.commitment),
|
|
234
|
-
}
|
|
235
|
-
: undefined,
|
|
236
|
-
}
|
|
237
|
-
: undefined,
|
|
238
|
-
};
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
result.outputs = tx.outputs.map((output): InOutput => {
|
|
242
|
-
const cached = addressCache[output.lockingBytecode as any];
|
|
243
|
-
let address: string;
|
|
244
|
-
if (!cached) {
|
|
245
|
-
if (output.lockingBytecode[0] === Opcodes.OP_RETURN) {
|
|
246
|
-
address = `OP_RETURN: ${binToHex(output.lockingBytecode)}`;
|
|
247
|
-
} else {
|
|
248
|
-
address = assertSuccess(
|
|
249
|
-
lockingBytecodeToCashAddress({
|
|
250
|
-
bytecode: output.lockingBytecode,
|
|
251
|
-
prefix: prefix,
|
|
252
|
-
})
|
|
253
|
-
).address;
|
|
254
|
-
addressCache[output.lockingBytecode as any] = address;
|
|
255
|
-
}
|
|
256
|
-
} else {
|
|
257
|
-
address = cached;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
outputTotalValue += output.valueSatoshis;
|
|
261
|
-
|
|
262
|
-
return {
|
|
263
|
-
address: address,
|
|
264
|
-
value: Number(output.valueSatoshis),
|
|
265
|
-
token: output.token
|
|
266
|
-
? {
|
|
267
|
-
category: binToHex(output.token.category),
|
|
268
|
-
amount: output.token.amount,
|
|
269
|
-
nft: output.token.nft
|
|
270
|
-
? {
|
|
271
|
-
capability: output.token.nft.capability,
|
|
272
|
-
commitment: binToHex(output.token.nft.commitment),
|
|
273
|
-
}
|
|
274
|
-
: undefined,
|
|
275
|
-
}
|
|
276
|
-
: undefined,
|
|
277
|
-
};
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
result.blockHeight = tx.blockHeight;
|
|
281
|
-
result.timestamp = tx.timestamp;
|
|
282
|
-
result.hash = tx.hash;
|
|
283
|
-
result.size = tx.size;
|
|
284
|
-
result.fee = Number(inputTotalValue - outputTotalValue);
|
|
285
|
-
|
|
286
|
-
if (isCoinbase && result.fee) {
|
|
287
|
-
// will indicate the fees collected by the miner
|
|
288
|
-
result.fee = -result.fee;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return result;
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
// compute value changes using Set for O(1) address lookup
|
|
295
|
-
historyItems.forEach((tx) => {
|
|
296
|
-
let satoshiBalance = 0;
|
|
297
|
-
const ftTokenBalances: Record<string, bigint> = {};
|
|
298
|
-
const nftTokenBalances: Record<string, bigint> = {};
|
|
299
|
-
|
|
300
|
-
tx.inputs.forEach((input) => {
|
|
301
|
-
if (addressSet.has(input.address)) {
|
|
302
|
-
satoshiBalance -= input.value;
|
|
303
|
-
|
|
304
|
-
if (input.token?.amount) {
|
|
305
|
-
ftTokenBalances[input.token.category] =
|
|
306
|
-
(ftTokenBalances[input.token.category] || BigInt(0)) -
|
|
307
|
-
input.token.amount;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (input.token?.nft?.capability) {
|
|
311
|
-
nftTokenBalances[input.token.category] =
|
|
312
|
-
(nftTokenBalances[input.token.category] || BigInt(0)) - 1n;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
tx.outputs.forEach((output) => {
|
|
317
|
-
if (addressSet.has(output.address)) {
|
|
318
|
-
satoshiBalance += Number(output.value);
|
|
319
|
-
|
|
320
|
-
if (output.token?.amount) {
|
|
321
|
-
ftTokenBalances[output.token.category] =
|
|
322
|
-
(ftTokenBalances[output.token.category] || BigInt(0)) +
|
|
323
|
-
output.token.amount;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (output.token?.nft?.capability) {
|
|
327
|
-
nftTokenBalances[output.token.category] =
|
|
328
|
-
(nftTokenBalances[output.token.category] || BigInt(0)) + 1n;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
tx.valueChange = satoshiBalance;
|
|
334
|
-
tx.tokenAmountChanges = Object.entries(ftTokenBalances).map(
|
|
335
|
-
([category, amount]) => ({
|
|
336
|
-
category,
|
|
337
|
-
amount,
|
|
338
|
-
nftAmount: BigInt(0),
|
|
339
|
-
})
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
for (const [category, nftAmount] of Object.entries(nftTokenBalances)) {
|
|
343
|
-
const tokenChange = tx.tokenAmountChanges.find(
|
|
344
|
-
(tokenChange) => tokenChange.category === category
|
|
345
|
-
);
|
|
346
|
-
if (tokenChange) {
|
|
347
|
-
tokenChange.nftAmount = nftAmount;
|
|
348
|
-
} else {
|
|
349
|
-
tx.tokenAmountChanges.push({
|
|
350
|
-
category: category,
|
|
351
|
-
amount: BigInt(0),
|
|
352
|
-
nftAmount,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
// order transactions in a way such that receives are always ordered before sends, per block
|
|
359
|
-
historyItems.sort(
|
|
360
|
-
(a, b) =>
|
|
361
|
-
(a.blockHeight <= 0 || b.blockHeight <= 0
|
|
362
|
-
? a.blockHeight - b.blockHeight
|
|
363
|
-
: b.blockHeight - a.blockHeight) || a.valueChange - b.valueChange
|
|
364
|
-
);
|
|
365
|
-
|
|
366
|
-
// backfill the balances
|
|
367
|
-
let prevBalance = (
|
|
368
|
-
await Promise.all(addresses.map((address) => provider.getBalance(address)))
|
|
369
|
-
).reduce((a, b) => Number(a) + Number(b), 0);
|
|
370
|
-
|
|
371
|
-
let prevValueChange = 0;
|
|
372
|
-
historyItems.forEach((tx) => {
|
|
373
|
-
tx.balance = prevBalance - prevValueChange;
|
|
374
|
-
prevBalance = tx.balance;
|
|
375
|
-
prevValueChange = tx.valueChange;
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
// convert units if needed — fetch exchange rate once
|
|
379
|
-
if (!(unit as string).includes("sat")) {
|
|
380
|
-
const sanitizedUnit = sanitizeUnit(unit);
|
|
381
|
-
let rate: number = 0;
|
|
382
|
-
if (sanitizedUnit !== UnitEnum.BCH && sanitizedUnit !== UnitEnum.SAT) {
|
|
383
|
-
rate = await ExchangeRate.get(unit);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
const subUnits = Number(bchParam.subUnits);
|
|
387
|
-
const convertSatToUnit = (satValue: number): number => {
|
|
388
|
-
if (sanitizedUnit === UnitEnum.BCH) {
|
|
389
|
-
return satValue / subUnits;
|
|
390
|
-
}
|
|
391
|
-
// currency conversion matching satoshiToAmount behavior
|
|
392
|
-
const currencyValue = Number((satValue * (rate / subUnits)).toFixed(2));
|
|
393
|
-
return currencyValue;
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
for (const tx of historyItems) {
|
|
397
|
-
for (const input of tx.inputs) {
|
|
398
|
-
input.value = convertSatToUnit(input.value);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
for (const output of tx.outputs) {
|
|
402
|
-
output.value = convertSatToUnit(output.value);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
tx.valueChange = convertSatToUnit(tx.valueChange);
|
|
406
|
-
tx.balance = convertSatToUnit(tx.balance);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
return historyItems;
|
|
411
|
-
};
|