mainnet-js 2.3.13 → 2.3.15
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/index.html +1 -1
- package/dist/{mainnet-2.3.13.js → mainnet-2.3.15.js} +10 -10
- package/dist/module/config.d.ts +2 -0
- package/dist/module/config.d.ts.map +1 -1
- package/dist/module/config.js +4 -0
- package/dist/module/config.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +17 -3
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.js +7 -1
- package/dist/module/rate/ExchangeRate.js.map +1 -1
- package/dist/module/util/amountInSatoshi.d.ts.map +1 -1
- package/dist/module/util/amountInSatoshi.js +3 -5
- package/dist/module/util/amountInSatoshi.js.map +1 -1
- package/dist/module/util/balanceObjectFromSatoshi.d.ts +6 -7
- package/dist/module/util/balanceObjectFromSatoshi.d.ts.map +1 -1
- package/dist/module/util/balanceObjectFromSatoshi.js +12 -33
- package/dist/module/util/balanceObjectFromSatoshi.js.map +1 -1
- package/dist/module/util/index.js +1 -1
- package/dist/module/util/index.js.map +1 -1
- package/dist/module/util/satoshiToAmount.d.ts.map +1 -1
- package/dist/module/util/satoshiToAmount.js +5 -8
- package/dist/module/util/satoshiToAmount.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts +1 -1
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +4 -4
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/model.js +1 -2
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/config.ts +4 -0
- package/src/network/ElectrumNetworkProvider.ts +19 -3
- package/src/rate/ExchangeRate.test.ts +9 -0
- package/src/rate/ExchangeRate.ts +12 -2
- package/src/util/amountInSatoshi.ts +4 -5
- package/src/util/balanceObjectFromSatoshi.test.ts +17 -0
- package/src/util/balanceObjectFromSatoshi.ts +18 -41
- package/src/util/convert.test.ts +5 -0
- package/src/util/satoshiToAmount.ts +7 -10
- package/src/wallet/Wif.test.ts +30 -0
- package/src/wallet/Wif.ts +4 -4
- package/src/wallet/model.ts +1 -1
|
@@ -12,6 +12,7 @@ import { ElectrumRawTransaction, ElectrumUtxo } from "./interface.js";
|
|
|
12
12
|
|
|
13
13
|
import { CancelWatchFn } from "../wallet/interface.js";
|
|
14
14
|
import { getTransactionHash } from "../util/transaction.js";
|
|
15
|
+
import { Config } from "../config.js";
|
|
15
16
|
|
|
16
17
|
export default class ElectrumNetworkProvider implements NetworkProvider {
|
|
17
18
|
public electrum: ElectrumCluster | ElectrumClient;
|
|
@@ -116,8 +117,14 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
|
|
|
116
117
|
loadInputValues: boolean = false
|
|
117
118
|
): Promise<string> {
|
|
118
119
|
const key = `${this.network}-${txHash}-${verbose}-${loadInputValues}`;
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
|
|
121
|
+
if (Config.UseLocalStorageCache) {
|
|
122
|
+
const cached = localStorage.getItem(key);
|
|
123
|
+
if (cached) {
|
|
124
|
+
return verbose ? JSON.parse(cached) : cached;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
ElectrumNetworkProvider.rawTransactionCache[key];
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
try {
|
|
@@ -127,7 +134,16 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
|
|
|
127
134
|
verbose
|
|
128
135
|
)) as ElectrumRawTransaction;
|
|
129
136
|
|
|
130
|
-
|
|
137
|
+
if (Config.UseLocalStorageCache) {
|
|
138
|
+
localStorage.setItem(
|
|
139
|
+
key,
|
|
140
|
+
verbose
|
|
141
|
+
? JSON.stringify(transaction)
|
|
142
|
+
: (transaction as unknown as string)
|
|
143
|
+
);
|
|
144
|
+
} else {
|
|
145
|
+
ElectrumNetworkProvider.rawTransactionCache[key] = transaction;
|
|
146
|
+
}
|
|
131
147
|
|
|
132
148
|
if (verbose && loadInputValues) {
|
|
133
149
|
// get unique transaction hashes
|
|
@@ -64,4 +64,13 @@ describe("Exchange rate tests", () => {
|
|
|
64
64
|
expect(cbCounter).toBe(2);
|
|
65
65
|
await cancelWatchFn();
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
test("Test other currencies", async () => {
|
|
69
|
+
const eurRate = await ExchangeRate.get("eur");
|
|
70
|
+
expect(eurRate).toBeGreaterThan(0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("Test non-existing currency", async () => {
|
|
74
|
+
await expect(ExchangeRate.get("xyz")).rejects.toThrow();
|
|
75
|
+
});
|
|
67
76
|
});
|
package/src/rate/ExchangeRate.ts
CHANGED
|
@@ -124,9 +124,19 @@ export async function getRateFromExchange(symbol: string): Promise<number> {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
default:
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
const response = await fetch("https://bitpay.com/rates/BCH");
|
|
128
|
+
const data = (await response.json()) as {
|
|
129
|
+
data: { code: string; rate: number }[];
|
|
130
|
+
};
|
|
131
|
+
const rates = data.data.reduce(
|
|
132
|
+
(acc, rate) => ({ ...acc, [rate.code.toLocaleLowerCase()]: rate.rate }),
|
|
133
|
+
{}
|
|
129
134
|
);
|
|
135
|
+
if (symbol in rates) {
|
|
136
|
+
return rates[symbol];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
throw Error(`Currency '${symbol}' is not supported.`);
|
|
130
140
|
}
|
|
131
141
|
}
|
|
132
142
|
|
|
@@ -28,11 +28,10 @@ export async function amountInSatoshi(
|
|
|
28
28
|
return value;
|
|
29
29
|
case UnitEnum.SATOSHIS:
|
|
30
30
|
return value;
|
|
31
|
-
case UnitEnum.USD:
|
|
32
|
-
let USD_over_BCH = await ExchangeRate.get("usd");
|
|
33
|
-
let SAT_over_BCH = bchParam.subUnits;
|
|
34
|
-
return Math.round(Number(value * (SAT_over_BCH / USD_over_BCH)));
|
|
35
31
|
default:
|
|
36
|
-
|
|
32
|
+
const Currency_over_BCH = await ExchangeRate.get(rawUnit);
|
|
33
|
+
const SAT_over_BCH = bchParam.subUnits;
|
|
34
|
+
|
|
35
|
+
return Math.round(Number(value * (SAT_over_BCH / Currency_over_BCH)));
|
|
37
36
|
}
|
|
38
37
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Config } from "../config";
|
|
1
2
|
import { bchParam } from "../chain";
|
|
2
3
|
import { balanceResponseFromSatoshi } from "./balanceObjectFromSatoshi";
|
|
3
4
|
import { balanceFromSatoshi } from "./balanceObjectFromSatoshi";
|
|
@@ -8,6 +9,22 @@ test("Get balanceResponse from 1 bch in satoshi", async () => {
|
|
|
8
9
|
expect(bal.sat).toBe(bchParam.subUnits);
|
|
9
10
|
});
|
|
10
11
|
|
|
12
|
+
test("Get balanceResponse from 0", async () => {
|
|
13
|
+
let bal = await balanceResponseFromSatoshi(0);
|
|
14
|
+
expect(bal.bch).toBe(0);
|
|
15
|
+
expect(bal.sat).toBe(0);
|
|
16
|
+
expect(bal.usd).toBe(0);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("Get balanceResponse from 1 bch in eur", async () => {
|
|
20
|
+
Config.DefaultCurrency = "eur";
|
|
21
|
+
let bal = await balanceResponseFromSatoshi(100000000);
|
|
22
|
+
expect(bal.bch).toBe(1);
|
|
23
|
+
expect(bal.sat).toBe(bchParam.subUnits);
|
|
24
|
+
expect(bal.eur).toBeGreaterThan(0);
|
|
25
|
+
Config.DefaultCurrency = "usd";
|
|
26
|
+
});
|
|
27
|
+
|
|
11
28
|
test("Get balanceResponse from 1 satoshi", async () => {
|
|
12
29
|
let bal = await balanceResponseFromSatoshi(110000000);
|
|
13
30
|
expect(bal.bch).toBe(1.1);
|
|
@@ -3,52 +3,33 @@ import { UnitEnum } from "../enum.js";
|
|
|
3
3
|
import { floor } from "./floor.js";
|
|
4
4
|
import { ExchangeRate } from "../rate/ExchangeRate.js";
|
|
5
5
|
import { sanitizeUnit } from "./sanitizeUnit.js";
|
|
6
|
+
import { Config } from "../config.js";
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
-
bch
|
|
9
|
-
sat
|
|
10
|
-
|
|
11
|
-
constructor(bch?: number, sat?: number, usd?: number) {
|
|
12
|
-
this.bch = bch;
|
|
13
|
-
this.sat = sat;
|
|
14
|
-
this.usd = usd;
|
|
15
|
-
}
|
|
8
|
+
export interface BalanceResponse {
|
|
9
|
+
bch: number;
|
|
10
|
+
sat: number;
|
|
11
|
+
[currency: string]: number;
|
|
16
12
|
}
|
|
17
13
|
|
|
18
14
|
export async function balanceResponseFromSatoshi(
|
|
19
15
|
value: number,
|
|
20
|
-
|
|
16
|
+
priceCache: boolean = true
|
|
21
17
|
): Promise<BalanceResponse> {
|
|
22
|
-
|
|
23
|
-
let returnUnits: UnitEnum[] = ["bch", "sat", "usd"];
|
|
18
|
+
const response = {} as BalanceResponse;
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
response.sat = value;
|
|
32
|
-
break;
|
|
33
|
-
case UnitEnum.USD:
|
|
34
|
-
let usd =
|
|
35
|
-
(value / bchParam.subUnits) *
|
|
36
|
-
(await ExchangeRate.get("usd", usdPriceCache));
|
|
37
|
-
response.usd = floor(usd, 2);
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
throw Error(
|
|
41
|
-
`Balance response type ${JSON.stringify(u)} not understood`
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
20
|
+
response.bch = value / bchParam.subUnits;
|
|
21
|
+
response.sat = value;
|
|
22
|
+
const currencyValue =
|
|
23
|
+
(value / bchParam.subUnits) *
|
|
24
|
+
(await ExchangeRate.get(Config.DefaultCurrency, priceCache));
|
|
25
|
+
response[Config.DefaultCurrency] = floor(currencyValue, 2);
|
|
45
26
|
return response;
|
|
46
27
|
}
|
|
47
28
|
|
|
48
29
|
export async function balanceFromSatoshi(
|
|
49
30
|
value: number,
|
|
50
31
|
rawUnit: string,
|
|
51
|
-
|
|
32
|
+
priceCache: boolean = true
|
|
52
33
|
): Promise<number> {
|
|
53
34
|
const unit = sanitizeUnit(rawUnit);
|
|
54
35
|
switch (unit) {
|
|
@@ -62,14 +43,10 @@ export async function balanceFromSatoshi(
|
|
|
62
43
|
return value;
|
|
63
44
|
case UnitEnum.SATOSHIS:
|
|
64
45
|
return value;
|
|
65
|
-
case UnitEnum.USD:
|
|
66
|
-
let usd =
|
|
67
|
-
(value / bchParam.subUnits) *
|
|
68
|
-
(await ExchangeRate.get("usd", usdPriceCache));
|
|
69
|
-
return Number(usd.toFixed(2));
|
|
70
46
|
default:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
47
|
+
const currencyValue =
|
|
48
|
+
(value / bchParam.subUnits) *
|
|
49
|
+
(await ExchangeRate.get(Config.DefaultCurrency, priceCache));
|
|
50
|
+
return Number(currencyValue.toFixed(2));
|
|
74
51
|
}
|
|
75
52
|
}
|
package/src/util/convert.test.ts
CHANGED
|
@@ -39,3 +39,8 @@ test("Should convert all the BCH from sat to bch", async () => {
|
|
|
39
39
|
let bch = await convert(21000000 * 100000000, "sat", "BCH");
|
|
40
40
|
expect(bch).toBe(21000000);
|
|
41
41
|
});
|
|
42
|
+
|
|
43
|
+
test("Should convert BCH to EUR", async () => {
|
|
44
|
+
let eur = await convert(1, "BCH", "EUR");
|
|
45
|
+
expect(eur).toBeGreaterThan(0);
|
|
46
|
+
});
|
|
@@ -27,16 +27,13 @@ export async function satoshiToAmount(
|
|
|
27
27
|
return value;
|
|
28
28
|
case UnitEnum.SATOSHIS:
|
|
29
29
|
return value;
|
|
30
|
-
case UnitEnum.USD:
|
|
31
|
-
let USD_over_BCH = await ExchangeRate.get("usd");
|
|
32
|
-
let SAT_over_BCH = bchParam.subUnits;
|
|
33
|
-
// truncate dollar amounts to fixed precision (2),
|
|
34
|
-
// then return the fixed value string as a float.
|
|
35
|
-
let dollarValue = Number(value * (USD_over_BCH / SAT_over_BCH)).toFixed(
|
|
36
|
-
2
|
|
37
|
-
);
|
|
38
|
-
return Number.parseFloat(dollarValue);
|
|
39
30
|
default:
|
|
40
|
-
|
|
31
|
+
const Currency_over_BCH = await ExchangeRate.get(rawUnit);
|
|
32
|
+
// truncate currency amounts to fixed precision (2),
|
|
33
|
+
// then return the fixed value string as a float.
|
|
34
|
+
const currencyValue = Number(
|
|
35
|
+
value * (Currency_over_BCH / bchParam.subUnits)
|
|
36
|
+
).toFixed(2);
|
|
37
|
+
return Number.parseFloat(currencyValue);
|
|
41
38
|
}
|
|
42
39
|
}
|
package/src/wallet/Wif.test.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { mine } from "../mine";
|
|
19
19
|
import json from "../../polyfill/json";
|
|
20
20
|
import ElectrumNetworkProvider from "../network/ElectrumNetworkProvider";
|
|
21
|
+
import { Config } from "../config";
|
|
21
22
|
|
|
22
23
|
beforeAll(async () => {
|
|
23
24
|
await initProviders();
|
|
@@ -458,6 +459,23 @@ describe(`Watch only Wallets`, () => {
|
|
|
458
459
|
}
|
|
459
460
|
});
|
|
460
461
|
|
|
462
|
+
test("Should get the regtest wallet balance in eur", async () => {
|
|
463
|
+
// Build Alice's wallet from Wallet Import Format string, send some sats
|
|
464
|
+
if (!process.env.ADDRESS) {
|
|
465
|
+
throw Error("Attempted to pass an empty address");
|
|
466
|
+
} else {
|
|
467
|
+
Config.DefaultCurrency = "eur";
|
|
468
|
+
let alice = await RegTestWallet.watchOnly(process.env.ADDRESS); // insert WIF from #1
|
|
469
|
+
// Build Bob's wallet from a public address, check his balance.
|
|
470
|
+
expect(alice.getPublicKeyHash()!.length).toBe(20);
|
|
471
|
+
const aliceBalance = (await alice.getBalance()) as BalanceResponse;
|
|
472
|
+
expect(aliceBalance.bch).toBeGreaterThan(5000);
|
|
473
|
+
expect(await alice.getBalance("eur")).toBeGreaterThan(0);
|
|
474
|
+
expect(await (await RegTestWallet.newRandom()).getBalance("eur")).toBe(0);
|
|
475
|
+
Config.DefaultCurrency = "usd";
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
461
479
|
test("Should send to testnet coins to a random address", async () => {
|
|
462
480
|
if (!process.env.ALICE_TESTNET_WALLET_ID) {
|
|
463
481
|
throw Error("Attempted to pass an empty address");
|
|
@@ -525,6 +543,18 @@ describe(`Watch only Wallets`, () => {
|
|
|
525
543
|
|
|
526
544
|
expect(await bobWallet.getLastTransaction()).not.toBeNull();
|
|
527
545
|
});
|
|
546
|
+
|
|
547
|
+
test("Should fail localStorage cache", async () => {
|
|
548
|
+
const aliceWif = `wif:regtest:${process.env.PRIVATE_WIF!}`;
|
|
549
|
+
const aliceWallet = await RegTestWallet.fromId(aliceWif);
|
|
550
|
+
|
|
551
|
+
expect(await aliceWallet.getLastTransaction()).not.toBeNull();
|
|
552
|
+
Config.UseLocalStorageCache = true;
|
|
553
|
+
await expect(aliceWallet.getLastTransaction()).rejects.toThrow(
|
|
554
|
+
"localStorage is not defined"
|
|
555
|
+
);
|
|
556
|
+
Config.UseLocalStorageCache = false;
|
|
557
|
+
});
|
|
528
558
|
});
|
|
529
559
|
describe(`Wallet subscriptions`, () => {
|
|
530
560
|
test("Should wait for transaction", async () => {
|
package/src/wallet/Wif.ts
CHANGED
|
@@ -636,22 +636,22 @@ export class Wallet extends BaseWallet {
|
|
|
636
636
|
return await this.getAddressUtxos(this.cashaddr);
|
|
637
637
|
}
|
|
638
638
|
|
|
639
|
-
// gets wallet balance in sats, bch and
|
|
639
|
+
// gets wallet balance in sats, bch and currency
|
|
640
640
|
public async getBalance(
|
|
641
641
|
rawUnit?: string,
|
|
642
|
-
|
|
642
|
+
priceCache = true
|
|
643
643
|
): Promise<BalanceResponse | number> {
|
|
644
644
|
if (rawUnit) {
|
|
645
645
|
const unit = sanitizeUnit(rawUnit);
|
|
646
646
|
return await balanceFromSatoshi(
|
|
647
647
|
await this.getBalanceFromProvider(),
|
|
648
648
|
unit,
|
|
649
|
-
|
|
649
|
+
priceCache
|
|
650
650
|
);
|
|
651
651
|
} else {
|
|
652
652
|
return await balanceResponseFromSatoshi(
|
|
653
653
|
await this.getBalanceFromProvider(),
|
|
654
|
-
|
|
654
|
+
priceCache
|
|
655
655
|
);
|
|
656
656
|
}
|
|
657
657
|
}
|