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.
Files changed (44) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/{mainnet-2.3.13.js → mainnet-2.3.15.js} +10 -10
  3. package/dist/module/config.d.ts +2 -0
  4. package/dist/module/config.d.ts.map +1 -1
  5. package/dist/module/config.js +4 -0
  6. package/dist/module/config.js.map +1 -1
  7. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  8. package/dist/module/network/ElectrumNetworkProvider.js +17 -3
  9. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  10. package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
  11. package/dist/module/rate/ExchangeRate.js +7 -1
  12. package/dist/module/rate/ExchangeRate.js.map +1 -1
  13. package/dist/module/util/amountInSatoshi.d.ts.map +1 -1
  14. package/dist/module/util/amountInSatoshi.js +3 -5
  15. package/dist/module/util/amountInSatoshi.js.map +1 -1
  16. package/dist/module/util/balanceObjectFromSatoshi.d.ts +6 -7
  17. package/dist/module/util/balanceObjectFromSatoshi.d.ts.map +1 -1
  18. package/dist/module/util/balanceObjectFromSatoshi.js +12 -33
  19. package/dist/module/util/balanceObjectFromSatoshi.js.map +1 -1
  20. package/dist/module/util/index.js +1 -1
  21. package/dist/module/util/index.js.map +1 -1
  22. package/dist/module/util/satoshiToAmount.d.ts.map +1 -1
  23. package/dist/module/util/satoshiToAmount.js +5 -8
  24. package/dist/module/util/satoshiToAmount.js.map +1 -1
  25. package/dist/module/wallet/Wif.d.ts +1 -1
  26. package/dist/module/wallet/Wif.d.ts.map +1 -1
  27. package/dist/module/wallet/Wif.js +4 -4
  28. package/dist/module/wallet/Wif.js.map +1 -1
  29. package/dist/module/wallet/model.js +1 -2
  30. package/dist/module/wallet/model.js.map +1 -1
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +1 -1
  33. package/src/config.ts +4 -0
  34. package/src/network/ElectrumNetworkProvider.ts +19 -3
  35. package/src/rate/ExchangeRate.test.ts +9 -0
  36. package/src/rate/ExchangeRate.ts +12 -2
  37. package/src/util/amountInSatoshi.ts +4 -5
  38. package/src/util/balanceObjectFromSatoshi.test.ts +17 -0
  39. package/src/util/balanceObjectFromSatoshi.ts +18 -41
  40. package/src/util/convert.test.ts +5 -0
  41. package/src/util/satoshiToAmount.ts +7 -10
  42. package/src/wallet/Wif.test.ts +30 -0
  43. package/src/wallet/Wif.ts +4 -4
  44. 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
- if (ElectrumNetworkProvider.rawTransactionCache[key]) {
120
- return ElectrumNetworkProvider.rawTransactionCache[key];
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
- ElectrumNetworkProvider.rawTransactionCache[key] = transaction;
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
  });
@@ -124,9 +124,19 @@ export async function getRateFromExchange(symbol: string): Promise<number> {
124
124
  }
125
125
  }
126
126
  default:
127
- throw Error(
128
- "Support for giving an amount in '${symbol}' is not supported."
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
- throw Error("Unit of value not defined");
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 class BalanceResponse {
8
- bch?: number;
9
- sat?: number;
10
- usd?: number;
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
- usdPriceCache: boolean = true
16
+ priceCache: boolean = true
21
17
  ): Promise<BalanceResponse> {
22
- let response = new BalanceResponse();
23
- let returnUnits: UnitEnum[] = ["bch", "sat", "usd"];
18
+ const response = {} as BalanceResponse;
24
19
 
25
- for (const u of returnUnits) {
26
- switch (u) {
27
- case UnitEnum.BCH:
28
- response.bch = value / bchParam.subUnits;
29
- break;
30
- case UnitEnum.SAT:
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
- usdPriceCache: boolean = true
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
- throw Error(
72
- `Balance response type ${JSON.stringify(unit)} not understood`
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
  }
@@ -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
- throw Error("Unit of value not defined");
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
  }
@@ -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 usd
639
+ // gets wallet balance in sats, bch and currency
640
640
  public async getBalance(
641
641
  rawUnit?: string,
642
- usdPriceCache = true
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
- usdPriceCache
649
+ priceCache
650
650
  );
651
651
  } else {
652
652
  return await balanceResponseFromSatoshi(
653
653
  await this.getBalanceFromProvider(),
654
- usdPriceCache
654
+ priceCache
655
655
  );
656
656
  }
657
657
  }
@@ -334,7 +334,7 @@ export class SendResponse {
334
334
  explorerUrl?: string;
335
335
  }) {
336
336
  this.txId = txId;
337
- this.balance = new BalanceResponse(balance);
337
+ this.balance = balance;
338
338
  this.explorerUrl = explorerUrl;
339
339
  }
340
340
  }