beignet 0.0.48 → 0.0.49

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.
@@ -0,0 +1,216 @@
1
+ import BitcoinJsonRpc from 'bitcoin-json-rpc';
2
+ import { expect } from 'chai';
3
+ import net from 'net';
4
+ import tls from 'tls';
5
+
6
+ import {
7
+ EAddressType,
8
+ EAvailableNetworks,
9
+ EProtocol,
10
+ generateMnemonic,
11
+ sleep,
12
+ Wallet
13
+ } from '../';
14
+ import {
15
+ bitcoinURL,
16
+ electrumHost,
17
+ electrumPort,
18
+ initWaitForElectrumToSync,
19
+ MessageListener,
20
+ TWaitForElectrum
21
+ } from './utils';
22
+
23
+ const testTimeout = 60000;
24
+ let wallet: Wallet;
25
+ let waitForElectrum: TWaitForElectrum;
26
+ const rpc = new BitcoinJsonRpc(bitcoinURL);
27
+ const ml = new MessageListener();
28
+
29
+ describe('Receive', async function () {
30
+ this.timeout(testTimeout);
31
+
32
+ beforeEach(async function () {
33
+ this.timeout(testTimeout);
34
+ ml.clear();
35
+
36
+ // Ensure sufficient balance in regtest
37
+ let balance = await rpc.getBalance();
38
+ const address = await rpc.getNewAddress();
39
+ await rpc.generateToAddress(1, address);
40
+
41
+ while (balance < 10) {
42
+ await rpc.generateToAddress(10, address);
43
+ balance = await rpc.getBalance();
44
+ }
45
+
46
+ waitForElectrum = await initWaitForElectrumToSync(
47
+ { host: electrumHost, port: electrumPort },
48
+ bitcoinURL
49
+ );
50
+
51
+ await waitForElectrum();
52
+
53
+ const mnemonic = generateMnemonic();
54
+
55
+ const res = await Wallet.create({
56
+ mnemonic,
57
+ network: EAvailableNetworks.regtest,
58
+ addressType: EAddressType.p2wpkh,
59
+ electrumOptions: {
60
+ servers: [
61
+ {
62
+ host: '127.0.0.1',
63
+ ssl: 60002,
64
+ tcp: 60001,
65
+ protocol: EProtocol.tcp
66
+ }
67
+ ],
68
+ net,
69
+ tls
70
+ },
71
+ // reduce gap limit to speed up tests
72
+ gapLimitOptions: {
73
+ lookAhead: 2,
74
+ lookBehind: 2,
75
+ lookAheadChange: 2,
76
+ lookBehindChange: 2
77
+ },
78
+ addressTypesToMonitor: [EAddressType.p2wpkh],
79
+ onMessage: ml.onMessage
80
+ });
81
+ if (res.isErr()) throw res.error;
82
+ wallet = res.value;
83
+ await wallet.refreshWallet({});
84
+ });
85
+
86
+ afterEach(async function () {
87
+ await wallet?.electrum?.disconnect();
88
+ });
89
+
90
+ it('Should generate new receiving address', async () => {
91
+ const r = await wallet.getNextAvailableAddress();
92
+ if (r.isErr()) throw r.error;
93
+ const address = r.value.addressIndex.address;
94
+ expect(address).to.be.a('string');
95
+ expect(address).to.match(/^bcrt1/); // Regtest bech32 prefix
96
+ });
97
+
98
+ it('Should receive funds and update balance', async () => {
99
+ expect(wallet.data.balance).to.equal(0);
100
+
101
+ const r = await wallet.getNextAvailableAddress();
102
+ if (r.isErr()) throw r.error;
103
+ const address = r.value.addressIndex.address;
104
+ expect(address).to.be.a('string');
105
+ expect(address).to.match(/^bcrt1/); // Regtest bech32 prefix
106
+
107
+ const amount = 0.1;
108
+ const amountSats = amount * 10e7;
109
+ await rpc.sendToAddress(address, amount.toString());
110
+
111
+ await rpc.generateToAddress(1, await rpc.getNewAddress());
112
+ await waitForElectrum();
113
+
114
+ await wallet.refreshWallet({});
115
+ expect(wallet.getBalance()).to.equal(amountSats);
116
+ expect(wallet.balance).to.equal(amountSats);
117
+ expect(wallet.utxos.length).to.equal(1);
118
+ });
119
+
120
+ it('Should track multiple receiving addresses', async () => {
121
+ const r1 = await wallet.getNextAvailableAddress();
122
+ if (r1.isErr()) throw r1.error;
123
+ const address1 = r1.value.addressIndex.address;
124
+ const r2 = await wallet.getNextAvailableAddress();
125
+ if (r2.isErr()) throw r2.error;
126
+ const address2 = r2.value.addressIndex.address;
127
+
128
+ // Without any transactions addresses should match
129
+ expect(address1).to.equal(address2);
130
+
131
+ // Send funds, get new address
132
+ await rpc.sendToAddress(address1, '0.1');
133
+ await rpc.generateToAddress(1, await rpc.getNewAddress());
134
+ await waitForElectrum();
135
+ const r3 = await wallet.getNextAvailableAddress();
136
+ if (r3.isErr()) throw r3.error;
137
+ const address3 = r3.value.addressIndex.address;
138
+
139
+ // After a transaction, addresses should differ
140
+ expect(address1).to.not.equal(address3);
141
+
142
+ // Second transaction
143
+ const receivePromise = ml.waitFor('transactionReceived');
144
+ await rpc.sendToAddress(address3, '0.2');
145
+ await receivePromise;
146
+
147
+ // unfortinately it is possible that Electrum server still does not
148
+ // have second transaction parsed so we need to wait a bit
149
+ while (wallet.data.utxos.length === 1) {
150
+ await sleep(100);
151
+ await wallet.refreshWallet();
152
+ }
153
+
154
+ // Check balances
155
+ expect(wallet.balance).to.equal(0.3 * 10e7); // 0.3 BTC in sats
156
+
157
+ // Test getAddressBalance
158
+ const balance1 = await wallet.getAddressBalance(address1);
159
+ if (balance1.isErr()) throw balance1.error;
160
+ expect(balance1.value.confirmed).to.equal(0.1 * 10e7);
161
+ const balance3 = await wallet.getAddressBalance(address3);
162
+ if (balance3.isErr()) throw balance3.error;
163
+ expect(balance3.value.unconfirmed).to.equal(0.2 * 10e7);
164
+
165
+ // Test getAddressesBalance
166
+ const combinedBalance = await wallet.getAddressesBalance([
167
+ address1,
168
+ address3
169
+ ]);
170
+ if (combinedBalance.isErr()) throw combinedBalance.error;
171
+ expect(combinedBalance.value).to.equal(0.3 * 10e7);
172
+ });
173
+
174
+ it('Should handle unconfirmed transactions', async () => {
175
+ const r = await wallet.getNextAvailableAddress();
176
+ if (r.isErr()) throw r.error;
177
+ const address = r.value.addressIndex.address;
178
+
179
+ await rpc.sendToAddress(address, '0.1');
180
+ await waitForElectrum();
181
+
182
+ // Refresh wallet and check unconfirmed transactions
183
+ await wallet.refreshWallet({});
184
+ expect(Object.keys(wallet.data.unconfirmedTransactions)).to.have.length(1);
185
+ expect(Object.keys(wallet.data.transactions)).to.have.length(1);
186
+
187
+ // Generate blocks to confirm transaction
188
+ await rpc.generateToAddress(10, await rpc.getNewAddress());
189
+ await waitForElectrum();
190
+
191
+ // Refresh and check confirmed status
192
+ await wallet.refreshWallet({});
193
+ expect(Object.keys(wallet.data.unconfirmedTransactions)).to.have.length(0);
194
+ expect(Object.keys(wallet.data.transactions)).to.have.length(1);
195
+ });
196
+
197
+ it('Should receive transaction and emit correct messages', async () => {
198
+ const r = await wallet.getNextAvailableAddress();
199
+ if (r.isErr()) throw r.error;
200
+ const address = r.value.addressIndex.address;
201
+
202
+ // test transactionReceived message
203
+ const receivePromise = ml.waitFor('transactionReceived');
204
+ const amount = 0.1;
205
+ await rpc.sendToAddress(address, amount.toString());
206
+ const txReceivedMessage = await receivePromise;
207
+ expect(txReceivedMessage.transaction.value).to.equal(0.1);
208
+
209
+ // test transactionConfirmed message
210
+ const confirmedPromise = ml.waitFor('transactionConfirmed');
211
+ await rpc.generateToAddress(1, await rpc.getNewAddress());
212
+ await waitForElectrum();
213
+ const txConfirmedMessage = await confirmedPromise;
214
+ expect(txConfirmedMessage.transaction.height).to.be.greaterThan(0);
215
+ });
216
+ });
@@ -1,55 +1,58 @@
1
- import * as chai from 'chai';
2
1
  import { validateMnemonic } from 'bip39';
2
+ import { expect } from 'chai';
3
3
  import net from 'net';
4
4
  import tls from 'tls';
5
+ import sinon from 'sinon';
5
6
 
6
7
  import { Wallet } from '../';
8
+ import { deleteDirectory, getData, servers, setData } from '../example/helpers';
7
9
  import {
8
10
  EAddressType,
9
11
  EAvailableNetworks,
12
+ generateMnemonic,
10
13
  IGetUtxosResponse,
11
- Result,
12
- generateMnemonic
14
+ Result
13
15
  } from '../src';
14
16
  import { TEST_MNEMONIC } from './constants';
15
- import { deleteDirectory, getData, servers, setData } from '../example/helpers';
16
17
  import { EXPECTED_SHARED_RESULTS } from './expected-results';
17
18
 
18
- const expect = chai.expect;
19
-
20
19
  const testTimeout = 60000;
21
20
 
22
21
  let wallet: Wallet;
23
22
  const WALLET_NAME = 'storagetestwallet0';
24
23
 
25
- before(async function () {
26
- this.timeout(testTimeout);
27
- await deleteDirectory('example/walletData'); // Start test with clean slate.
28
- const res = await Wallet.create({
29
- mnemonic: TEST_MNEMONIC,
30
- network: EAvailableNetworks.testnet,
31
- name: WALLET_NAME,
32
- addressType: EAddressType.p2wpkh,
33
- storage: {
34
- getData,
35
- setData
36
- },
37
- electrumOptions: {
38
- servers: servers[EAvailableNetworks.testnet],
39
- net,
40
- tls
41
- }
42
- });
43
- if (res.isErr()) {
44
- console.log('error: ', res.error.message);
45
- //throw new Error(res.error.message);
46
- return;
47
- }
48
- wallet = res.value;
49
- });
24
+ const storage = { getData, setData };
25
+ const storageSpy = sinon.spy(storage, 'setData');
26
+ const messageSpy = sinon.spy();
50
27
 
51
28
  describe('Storage Test', async function (): Promise<void> {
52
29
  this.timeout(testTimeout);
30
+
31
+ before(async function () {
32
+ this.timeout(testTimeout);
33
+ await deleteDirectory('example/walletData'); // Start test with clean slate.
34
+ const res = await Wallet.create({
35
+ mnemonic: TEST_MNEMONIC,
36
+ network: EAvailableNetworks.testnet,
37
+ name: WALLET_NAME,
38
+ addressType: EAddressType.p2wpkh,
39
+ storage,
40
+ onMessage: messageSpy,
41
+ electrumOptions: {
42
+ servers: servers[EAvailableNetworks.testnet],
43
+ net,
44
+ tls
45
+ }
46
+ });
47
+ if (res.isErr()) throw res.error;
48
+ wallet = res.value;
49
+ await wallet.refreshWallet({});
50
+ });
51
+
52
+ after(async function () {
53
+ await wallet?.electrum?.disconnect();
54
+ });
55
+
53
56
  it('Should successfully create a wallet.', () => {
54
57
  expect(wallet).not.to.be.null;
55
58
  });
@@ -100,8 +103,7 @@ describe('Storage Test', async function (): Promise<void> {
100
103
 
101
104
  it('Should generate a bech32 receiving address at index 0 via its path', async () => {
102
105
  const address = await wallet.getAddressByPath({ path: "m/84'/1'/0'/0/0" });
103
- expect(address.isErr()).to.equal(false);
104
- if (address.isErr()) return;
106
+ if (address.isErr()) throw address.error;
105
107
  expect(address.value.address).to.equal(
106
108
  'tb1qmja98kkd540qtesjqdanfg0ywags845vehfg66'
107
109
  );
@@ -109,8 +111,7 @@ describe('Storage Test', async function (): Promise<void> {
109
111
 
110
112
  it('Should generate a segwit change address at index 1 via its path', async () => {
111
113
  const address = await wallet.getAddressByPath({ path: "m/49'/1'/0'/1/1" });
112
- expect(address.isErr()).to.equal(false);
113
- if (address.isErr()) return;
114
+ if (address.isErr()) throw address.error;
114
115
  expect(address.value.address).to.equal(
115
116
  '2NDRG1ZGhWMGGNW7Mp58BKcyBs4Hyat8Law'
116
117
  );
@@ -118,8 +119,7 @@ describe('Storage Test', async function (): Promise<void> {
118
119
 
119
120
  it('Should generate a testnet legacy receiving address at index 5 via its path', async () => {
120
121
  const address = await wallet.getAddressByPath({ path: "m/44'/1'/0'/0/5" });
121
- expect(address.isErr()).to.equal(false);
122
- if (address.isErr()) return;
122
+ if (address.isErr()) throw address.error;
123
123
  expect(address.value.address).to.equal(
124
124
  'mohdq3fadTtT4uSH4oNr4F1Dp3YM4pR3VF'
125
125
  );
@@ -127,8 +127,7 @@ describe('Storage Test', async function (): Promise<void> {
127
127
 
128
128
  it('getNextAvailableAddress: Should return the next available address/change index and the last used address/change index', async () => {
129
129
  const r = await wallet.getNextAvailableAddress();
130
- expect(r.isErr()).to.equal(false);
131
- if (r.isErr()) return;
130
+ if (r.isErr()) throw r.error;
132
131
  expect(r.value).to.deep.equal(
133
132
  EXPECTED_SHARED_RESULTS.getNextAvailableAddress
134
133
  );
@@ -136,8 +135,7 @@ describe('Storage Test', async function (): Promise<void> {
136
135
 
137
136
  it("Should return available UTXO's", async () => {
138
137
  const getUtxosRes: Result<IGetUtxosResponse> = await wallet.getUtxos({});
139
- expect(getUtxosRes.isErr()).to.equal(false);
140
- if (getUtxosRes.isErr()) return;
138
+ if (getUtxosRes.isErr()) throw getUtxosRes.error;
141
139
  expect(Array.isArray(getUtxosRes.value.utxos)).to.equal(true);
142
140
  expect(getUtxosRes.value.utxos.length).to.equal(3);
143
141
  expect(getUtxosRes.value.balance).to.equal(5855);
@@ -152,6 +150,21 @@ describe('Storage Test', async function (): Promise<void> {
152
150
  );
153
151
  });
154
152
 
153
+ it('Should successfully stop the wallet', async () => {
154
+ wallet.refreshWallet(); // start wallet refresh in the background
155
+ const r = await wallet.stop();
156
+ if (r.isErr()) throw r.error;
157
+ storageSpy.resetHistory();
158
+ messageSpy.resetHistory();
159
+ // try to force the wallet to update it's data
160
+ wallet.feeEstimates.timestamp = 0;
161
+ await wallet.updateFeeEstimates(true);
162
+ await wallet.refreshWallet();
163
+ // make sure that the wallet did not call setData or onMessage
164
+ expect(storageSpy.called).to.equal(false);
165
+ expect(messageSpy.called).to.equal(false);
166
+ });
167
+
155
168
  // it('Attempts to create a new wallet using the same name of an existing wallet in storage.', async () => {
156
169
  // const createRes = await Wallet.create({
157
170
  // mnemonic: generateMnemonic(),
@@ -1,4 +1,4 @@
1
- import * as chai from 'chai';
1
+ import { expect } from 'chai';
2
2
  import net from 'net';
3
3
  import tls from 'tls';
4
4
 
@@ -8,38 +8,37 @@ import {
8
8
  ISweepPrivateKeyRes,
9
9
  Wallet
10
10
  } from '../';
11
+ import { servers } from '../example/helpers';
11
12
  import { EAvailableNetworks, Result } from '../src';
12
13
  import { TRANSACTION_TEST_MNEMONIC } from './constants';
13
- import { servers } from '../example/helpers';
14
14
  import { EXPECTED_TRANSACTION_RESULTS } from './expected-results';
15
15
 
16
- const expect = chai.expect;
17
-
18
16
  const testTimeout = 60000;
19
17
 
20
18
  let wallet: Wallet;
21
19
 
22
- before(async function () {
20
+ describe('Transaction Test', async function (): Promise<void> {
23
21
  this.timeout(testTimeout);
24
- const res = await Wallet.create({
25
- mnemonic: TRANSACTION_TEST_MNEMONIC,
26
- network: EAvailableNetworks.testnet,
27
- electrumOptions: {
28
- servers: servers[EAvailableNetworks.testnet],
29
- net,
30
- tls
31
- }
22
+
23
+ before(async function () {
24
+ this.timeout(testTimeout);
25
+ const res = await Wallet.create({
26
+ mnemonic: TRANSACTION_TEST_MNEMONIC,
27
+ network: EAvailableNetworks.testnet,
28
+ electrumOptions: {
29
+ servers: servers[EAvailableNetworks.testnet],
30
+ net,
31
+ tls
32
+ }
33
+ });
34
+ if (res.isErr()) throw res.error;
35
+ wallet = res.value;
36
+ await wallet.refreshWallet({});
32
37
  });
33
- if (res.isErr()) {
34
- console.log('error: ', res.error.message);
35
- return;
36
- }
37
- wallet = res.value;
38
- await wallet.refreshWallet({});
39
- });
40
38
 
41
- describe('Transaction Test', async function (): Promise<void> {
42
- this.timeout(testTimeout);
39
+ after(async function () {
40
+ await wallet?.electrum?.disconnect();
41
+ });
43
42
 
44
43
  it('Should successfully create a wallet.', (): void => {
45
44
  expect(wallet).not.to.be.null;
@@ -53,9 +52,7 @@ describe('Transaction Test', async function (): Promise<void> {
53
52
 
54
53
  it('Should successfully return fee information.', (): void => {
55
54
  const feeInfo = wallet.getFeeInfo({ satsPerByte: 5 });
56
- expect(feeInfo.isErr()).to.equal(false);
57
- if (feeInfo.isErr()) return;
58
- expect(feeInfo).not.to.be.null;
55
+ if (feeInfo.isErr()) throw feeInfo.error;
59
56
  expect(feeInfo.value.satsPerByte).to.equal(5);
60
57
  expect(feeInfo.value.totalFee).to.equal(830);
61
58
  expect(feeInfo.value.transactionByteCount).to.equal(166);
@@ -72,15 +69,13 @@ describe('Transaction Test', async function (): Promise<void> {
72
69
  shuffleOutputs: false,
73
70
  rbf: true
74
71
  });
75
- expect(sendRes.isErr()).to.equal(false);
76
- if (sendRes.isErr()) return;
72
+ if (sendRes.isErr()) throw sendRes.error;
77
73
  expect(sendRes.value).to.equal(
78
74
  '020000000001014b44d379e48a8100d1c26f7220b8bbf7a4894ff015d5bc4064a28d08d25d808d0000000000000000000288130000000000001600143f1a7a1802e377d01602acf1cad403368ed3bb89ba21010000000000160014a6bd95db4dd6979189cad389daad006e236f4ba802483045022100dd709b656c271c7e2ab4c83e0245b9b8d9096a1c7a33eddc9a32113f436851d9022033f8e5cb016ae4c440badfa34e438ada7bea2cdd36e782c136e516350b502bca012102e86b90924963237c59e5389aab1cc5350c114549d1c5e7186a56ef33aea24ff900000000'
79
75
  );
80
76
 
81
77
  const decodeRes = decodeRawTransaction(sendRes.value, wallet.network);
82
- expect(decodeRes.isErr()).to.equal(false);
83
- if (decodeRes.isErr()) return;
78
+ if (decodeRes.isErr()) throw decodeRes.error;
84
79
  expect(decodeRes.value).to.deep.equal(
85
80
  EXPECTED_TRANSACTION_RESULTS.decodeRawTransaction
86
81
  );
@@ -104,15 +99,13 @@ describe('Transaction Test', async function (): Promise<void> {
104
99
  satsPerByte: 5,
105
100
  rbf: true
106
101
  });
107
- expect(sendManyRes.isErr()).to.equal(false);
108
- if (sendManyRes.isErr()) return;
102
+ if (sendManyRes.isErr()) throw sendManyRes.error;
109
103
  expect(sendManyRes.value).to.equal(
110
104
  '020000000001014b44d379e48a8100d1c26f7220b8bbf7a4894ff015d5bc4064a28d08d25d808d000000000000000000038813000000000000160014a6b760eaa96a9ba91bae9465dfc4eabe711e1d6770170000000000001600146bcf920595e09b5d8f7b8d03b3694ad3057572892c0a010000000000160014a6bd95db4dd6979189cad389daad006e236f4ba80247304402207e7b5de41cb9bf33e434c2136390bf40d6b6552b69234a62f6bf48b89f0d44ac022056121c9a9d79d9d84896c9896a6fddb358b48667021ff2832b5c5871d90b701a012102e86b90924963237c59e5389aab1cc5350c114549d1c5e7186a56ef33aea24ff900000000'
111
105
  );
112
106
 
113
107
  const decodeRes = decodeRawTransaction(sendManyRes.value, wallet.network);
114
- expect(decodeRes.isErr()).to.equal(false);
115
- if (decodeRes.isErr()) return;
108
+ if (decodeRes.isErr()) throw decodeRes.error;
116
109
  expect(decodeRes.value).to.deep.equal(
117
110
  EXPECTED_TRANSACTION_RESULTS.decodeRawSendManyTransaction
118
111
  );
@@ -126,7 +119,7 @@ describe('Transaction Test', async function (): Promise<void> {
126
119
  satsPerByte: 5,
127
120
  broadcast: false
128
121
  });
129
- if (sweepPrivateKey.isErr()) return;
122
+ if (sweepPrivateKey.isErr()) throw sweepPrivateKey.error;
130
123
  expect(sweepPrivateKey.value.id).to.equal(
131
124
  '7fbef762e16676715bc94693a495923273259aa1190a5bf97bf18ab676393af5'
132
125
  );
@@ -145,7 +138,7 @@ describe('Transaction Test', async function (): Promise<void> {
145
138
  broadcast: false,
146
139
  combineWithWalletUtxos: true
147
140
  });
148
- if (sweepPrivateKey.isErr()) return;
141
+ if (sweepPrivateKey.isErr()) throw sweepPrivateKey.error;
149
142
  expect(sweepPrivateKey.value.id).to.equal(
150
143
  'ea6677d40bbf44dbc2d19d3765fd440aa2344f928d724dc021884fc5984e91ff'
151
144
  );
@@ -166,14 +159,13 @@ describe('Transaction Test', async function (): Promise<void> {
166
159
  }
167
160
  ]
168
161
  });
169
- expect(setupResponse.isErr()).to.equal(false);
170
- if (setupResponse.isErr()) return;
162
+ if (setupResponse.isErr()) throw setupResponse.error;
163
+
171
164
  const privateKeyInfo: Result<IPrivateKeyInfo> =
172
165
  await wallet.getPrivateKeyInfo(
173
166
  'cUVwTLfHYrF7KGdTVU4AcP4yjtRTH3Y2BbTKHJbp2tsHDfpE8Zq5'
174
167
  );
175
- expect(privateKeyInfo.isErr()).to.equal(false);
176
- if (privateKeyInfo.isErr()) return;
168
+ if (privateKeyInfo.isErr()) throw privateKeyInfo.error;
177
169
  const utxos = privateKeyInfo.value.utxos;
178
170
  const keyPair = privateKeyInfo.value.keyPair;
179
171
  expect(Array.isArray(utxos)).to.equal(true);
@@ -185,13 +177,11 @@ describe('Transaction Test', async function (): Promise<void> {
185
177
  inputs: utxos,
186
178
  keyPair
187
179
  });
188
- expect(addExternRes.isErr()).to.equal(false);
189
- if (addExternRes.isErr()) return;
180
+ if (addExternRes.isErr()) throw addExternRes.error;
190
181
  const createTransaction = await wallet.transaction.createTransaction({
191
182
  shuffleOutputs: false
192
183
  });
193
- expect(createTransaction.isErr()).to.equal(false);
194
- if (createTransaction.isErr()) return;
184
+ if (createTransaction.isErr()) throw createTransaction.error;
195
185
  expect(createTransaction.value.id).to.equal(
196
186
  'c0b4a54d9b4f88a32c7d7349f03c71c84a16b99b5c82159474768e734afecd81'
197
187
  );
package/tests/utils.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  import net from 'net';
2
2
  import BitcoinJsonRpc from 'bitcoin-json-rpc';
3
3
  import ElectrumClient from 'bw-electrum-client';
4
- import { EProtocol, sleep } from '../src';
4
+ import {
5
+ EProtocol,
6
+ sleep,
7
+ TMessageDataMap,
8
+ TMessageKeys,
9
+ TOnMessage
10
+ } from '../src';
5
11
 
6
12
  export const bitcoinURL = 'http://polaruser:polarpass@127.0.0.1:43782';
7
13
  export const electrumHost = '127.0.0.1';
@@ -44,7 +50,7 @@ export const initWaitForElectrumToSync = async (
44
50
 
45
51
  const waitForElectrum = (): Promise<void> => {
46
52
  return new Promise(async (resolve, reject) => {
47
- let count;
53
+ let count: number;
48
54
  let running = true;
49
55
 
50
56
  const timer = setTimeout(async () => {
@@ -82,3 +88,55 @@ export const initWaitForElectrumToSync = async (
82
88
 
83
89
  return waitForElectrum;
84
90
  };
91
+
92
+ type TMessage = {
93
+ key: TMessageKeys;
94
+ data: TMessageDataMap[keyof TMessageDataMap];
95
+ timestamp: number;
96
+ };
97
+
98
+ export class MessageListener {
99
+ public messages: TMessage[] = [];
100
+ private resolvers: ((message: TMessage) => void)[] = [];
101
+
102
+ onMessage: TOnMessage = (key, data) => {
103
+ const message: TMessage = {
104
+ key,
105
+ data,
106
+ timestamp: Date.now()
107
+ };
108
+ this.messages.push(message);
109
+ this.resolvers.forEach((resolve) => resolve(message));
110
+ };
111
+
112
+ waitFor<K extends TMessageKeys>(
113
+ messageKey: K,
114
+ timeout = 20000
115
+ ): Promise<TMessageDataMap[K]> {
116
+ // Check if message already received
117
+ const existingMessage = this.messages.find((msg) => msg.key === messageKey);
118
+ if (existingMessage) {
119
+ return Promise.resolve(existingMessage.data as TMessageDataMap[K]);
120
+ }
121
+
122
+ // Wait for new message
123
+ return new Promise((resolve, reject) => {
124
+ const timer = setTimeout(() => {
125
+ reject(new Error('Timeout waiting for message'));
126
+ }, timeout);
127
+
128
+ const resolver = (msg: TMessage): void => {
129
+ if (msg.key === messageKey) {
130
+ clearTimeout(timer);
131
+ resolve(msg.data as TMessageDataMap[K]);
132
+ }
133
+ };
134
+ this.resolvers.push(resolver);
135
+ });
136
+ }
137
+
138
+ clear(): void {
139
+ this.messages = [];
140
+ this.resolvers = [];
141
+ }
142
+ }