mainnet-js 0.4.35 → 0.4.38

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 (43) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/main/message/signed.js +4 -4
  3. package/dist/main/message/signed.js.map +1 -1
  4. package/dist/main/network/ElectrumNetworkProvider.js +8 -3
  5. package/dist/main/network/ElectrumNetworkProvider.js.map +1 -1
  6. package/dist/main/network/constant.d.ts +2 -0
  7. package/dist/main/network/constant.js +21 -6
  8. package/dist/main/network/constant.js.map +1 -1
  9. package/dist/main/network/default.js +6 -1
  10. package/dist/main/network/default.js.map +1 -1
  11. package/dist/main/transaction/Wif.d.ts +2 -2
  12. package/dist/main/transaction/Wif.js +16 -10
  13. package/dist/main/transaction/Wif.js.map +1 -1
  14. package/dist/main/wallet/Wif.js +8 -1
  15. package/dist/main/wallet/Wif.js.map +1 -1
  16. package/dist/mainnet-0.4.38.js +2 -0
  17. package/dist/{mainnet-0.4.35.js.LICENSE.txt → mainnet-0.4.38.js.LICENSE.txt} +0 -0
  18. package/dist/module/message/signed.js +4 -4
  19. package/dist/module/message/signed.js.map +1 -1
  20. package/dist/module/network/ElectrumNetworkProvider.js +8 -3
  21. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  22. package/dist/module/network/constant.d.ts +2 -0
  23. package/dist/module/network/constant.js +21 -6
  24. package/dist/module/network/constant.js.map +1 -1
  25. package/dist/module/network/default.js +6 -1
  26. package/dist/module/network/default.js.map +1 -1
  27. package/dist/module/transaction/Wif.d.ts +2 -2
  28. package/dist/module/transaction/Wif.js +16 -10
  29. package/dist/module/transaction/Wif.js.map +1 -1
  30. package/dist/module/wallet/Wif.js +8 -1
  31. package/dist/module/wallet/Wif.js.map +1 -1
  32. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +3 -3
  35. package/src/Wallet.test.ts +44 -0
  36. package/src/message/signed.ts +6 -4
  37. package/src/network/ElectrumNetworkProvider.ts +8 -2
  38. package/src/network/constant.ts +21 -6
  39. package/src/network/default.ts +7 -1
  40. package/src/transaction/Wif.ts +18 -11
  41. package/src/wallet/Wif.test.ts +1 -1
  42. package/src/wallet/Wif.ts +9 -1
  43. package/dist/mainnet-0.4.35.js +0 -2
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "url": "https://github.com/mainnet-cash/mainnet-js/issues"
9
9
  },
10
10
  "name": "mainnet-js",
11
- "version": "0.4.35",
11
+ "version": "0.4.38",
12
12
  "homepage": "https://mainnet.cash",
13
13
  "main": "dist/main/index.js",
14
14
  "module": "dist/module/index.js",
@@ -38,7 +38,7 @@
38
38
  "reload": "npx reload --dir=../../jest/playwright "
39
39
  },
40
40
  "dependencies": {
41
- "@bitauth/libauth": "^1.18.0",
41
+ "@bitauth/libauth": "^1.19.1",
42
42
  "async-mutex": "^0.3.1",
43
43
  "axios": "^0.21.1",
44
44
  "bchaddrjs-slp": "^0.2.12",
@@ -49,7 +49,7 @@
49
49
  "buffer": "^6.0.3",
50
50
  "buffer-lite": "^1.0.0",
51
51
  "cashaddrjs": "^0.4.4",
52
- "electrum-cash": "^2.0.8",
52
+ "electrum-cash": "^2.0.10",
53
53
  "events": "^3.2.0",
54
54
  "eventsource": "^1.0.7",
55
55
  "fake-indexeddb": "^3.1.2",
@@ -225,6 +225,50 @@ describe(`Test Wallet library`, () => {
225
225
  }
226
226
  });
227
227
 
228
+ test("Should send a transaction with change to different change address", async () => {
229
+ // Build Alice's wallet from Wallet Import Format string, send some sats
230
+ if (!process.env.PRIVATE_WIF) {
231
+ throw Error("Attempted to pass an empty WIF");
232
+ } else {
233
+ let funder = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF); // insert WIF from #1
234
+
235
+ const alice = await createWallet({
236
+ type: WalletTypeEnum.Wif,
237
+ network: "regtest",
238
+ });
239
+ const bob = await createWallet({
240
+ type: WalletTypeEnum.Wif,
241
+ network: "regtest",
242
+ });
243
+ const charlie = await createWallet({
244
+ type: WalletTypeEnum.Wif,
245
+ network: "regtest",
246
+ });
247
+ await funder.send([
248
+ {
249
+ cashaddr: alice.cashaddr!,
250
+ value: 3000,
251
+ unit: "satoshis",
252
+ },
253
+ ]);
254
+
255
+ let sendResponse = await alice.send(
256
+ [
257
+ {
258
+ cashaddr: bob.cashaddr!,
259
+ value: 1000,
260
+ unit: "satoshis",
261
+ },
262
+ ],
263
+ {
264
+ changeAddress: charlie.cashaddr!,
265
+ }
266
+ );
267
+ expect(await bob.getBalance("sat")).toBe(1000);
268
+ expect(await charlie.getBalance("sat")).toBe(1780);
269
+ }
270
+ });
271
+
228
272
  test("Should send maximum amount from specific utxos", async () => {
229
273
  // Build Alice's wallet from Wallet Import Format string, send some sats
230
274
  if (!process.env.PRIVATE_WIF) {
@@ -144,12 +144,14 @@ export class SignedMessage implements SignedMessageI {
144
144
  }
145
145
  }
146
146
  } else if (publicKey) {
147
- if (secp256k1.verifySignatureSchnorr(sig, publicKey, messageHash)) {
148
- signatureType = "schnorr";
149
- valid = true;
150
- } else if (secp256k1.verifySignatureDER(sig, publicKey, messageHash)) {
147
+ if (secp256k1.verifySignatureDER(sig, publicKey, messageHash)) {
151
148
  signatureType = "der";
152
149
  valid = true;
150
+ } else if (
151
+ secp256k1.verifySignatureSchnorr(sig, publicKey, messageHash)
152
+ ) {
153
+ signatureType = "schnorr";
154
+ valid = true;
153
155
  } else if (
154
156
  secp256k1.verifySignatureCompact(sig, publicKey, messageHash)
155
157
  ) {
@@ -360,9 +360,15 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
360
360
  ): Promise<RequestResponse> {
361
361
  await this.ready();
362
362
 
363
- const result = await this.electrum.request(name, ...parameters);
363
+ let result = await this.electrum.request(name, ...parameters);
364
364
 
365
- if (result instanceof Error) throw result;
365
+ // If the first request fails, retry
366
+ if (result instanceof Error) {
367
+ result = await this.electrum.request(name, ...parameters);
368
+
369
+ // If the second attempt fails, throw.
370
+ if (result instanceof Error) throw result;
371
+ }
366
372
 
367
373
  return result;
368
374
  }
@@ -8,11 +8,24 @@ export const networkTickerMap = {
8
8
  regtest: "rBCH",
9
9
  };
10
10
 
11
- export const mainnetServers = ["wss://fulcrum.fountainhead.cash"];
11
+ export const mainnetServers = [
12
+ "wss://bch.imaginary.cash:50004",
13
+ //"wss://blackie.c3-soft.com:50004",
14
+ "wss://electrum.imaginary.cash:50004",
15
+ "wss://fulcrum.fountainhead.cash",
16
+ ];
12
17
 
13
- export const testnetServers = ["wss://tbch.loping.net:60004"];
18
+ export const testnetServers = [
19
+ "wss://tbch.loping.net:60004",
20
+ "wss://blackie.c3-soft.com:60004",
21
+ "wss://testnet.bitcoincash.network:60004",
22
+ //,"wss://unavailable.invalid:50004"
23
+ ];
14
24
 
15
- export const regtestServers = ["ws://127.0.0.1:60003"];
25
+ export const regtestServers = [
26
+ "ws://127.0.0.1:60003",
27
+ //,"wss://unavailable.invalid:50004"
28
+ ];
16
29
 
17
30
  export const defaultServers = {
18
31
  mainnet: mainnetServers,
@@ -22,13 +35,15 @@ export const defaultServers = {
22
35
 
23
36
  export const clusterParams = {
24
37
  mainnet: {
25
- distribution: 2,
26
- order: ClusterOrder.PRIORITY,
38
+ confidence: 1,
39
+ distribution: 1,
40
+ order: ClusterOrder.RANDOM,
27
41
  timeout: 45000,
28
42
  },
29
43
  testnet: {
44
+ confidence: 1,
30
45
  distribution: 1,
31
- order: ClusterOrder.PRIORITY,
46
+ order: ClusterOrder.RANDOM,
32
47
  timeout: 50000,
33
48
  },
34
49
  regtest: {
@@ -100,7 +100,13 @@ function getCluster(servers: string[], params) {
100
100
 
101
101
  for (const s of servers) {
102
102
  let url = parseElectrumUrl(s);
103
- electrum.addServer(url.host, url.port, url.scheme, false);
103
+ try {
104
+ electrum.addServer(url.host, url.port, url.scheme, false);
105
+ } catch (error) {
106
+ console.log(
107
+ `Error connecting ${url.host}:${url.port} over ${url.scheme}`
108
+ );
109
+ }
104
110
  }
105
111
  return electrum;
106
112
  }
@@ -30,7 +30,8 @@ export async function buildP2pkhNonHdTransaction(
30
30
  fee: number = 0,
31
31
  discardChange = false,
32
32
  slpOutputs: any[] = [],
33
- feePaidBy: FeePaidByEnum = FeePaidByEnum.change
33
+ feePaidBy: FeePaidByEnum = FeePaidByEnum.change,
34
+ changeAddress: string = ""
34
35
  ) {
35
36
  if (!signingKey) {
36
37
  throw new Error("Missing signing key when building transaction");
@@ -48,14 +49,6 @@ export async function buildP2pkhNonHdTransaction(
48
49
 
49
50
  const sendAmount = await sumSendRequestAmounts(outputs);
50
51
 
51
- // Get the change locking bytecode
52
- let changeLockingBytecode = compiler.generateBytecode("lock", {
53
- keys: { privateKeys: { key: signingKey } },
54
- });
55
- if (!changeLockingBytecode.success) {
56
- throw new Error(changeLockingBytecode.toString());
57
- }
58
-
59
52
  try {
60
53
  const changeAmount = BigInt(inputAmount) - BigInt(sendAmount) - BigInt(fee);
61
54
 
@@ -65,6 +58,18 @@ export async function buildP2pkhNonHdTransaction(
65
58
 
66
59
  if (discardChange !== true) {
67
60
  if (changeAmount > DUST_UTXO_THRESHOLD) {
61
+ let changeLockingBytecode;
62
+ if (changeAddress) {
63
+ changeLockingBytecode = cashAddressToLockingBytecode(changeAddress);
64
+ } else {
65
+ // Get the change locking bytecode
66
+ changeLockingBytecode = compiler.generateBytecode("lock", {
67
+ keys: { privateKeys: { key: signingKey } },
68
+ });
69
+ }
70
+ if (typeof changeLockingBytecode === "string") {
71
+ throw new Error(changeLockingBytecode);
72
+ }
68
73
  lockedOutputs.push({
69
74
  lockingBytecode: changeLockingBytecode.bytecode,
70
75
  satoshis: bigIntToBinUint64LEClamped(BigInt(changeAmount)),
@@ -282,7 +287,8 @@ export async function buildEncodedTransaction(
282
287
  fee: number = 0,
283
288
  discardChange = false,
284
289
  slpOutputs: any[] = [],
285
- feePaidBy: FeePaidByEnum = FeePaidByEnum.change
290
+ feePaidBy: FeePaidByEnum = FeePaidByEnum.change,
291
+ changeAddress: string = ""
286
292
  ) {
287
293
  let txn = await buildP2pkhNonHdTransaction(
288
294
  fundingUtxos,
@@ -291,7 +297,8 @@ export async function buildEncodedTransaction(
291
297
  fee,
292
298
  discardChange,
293
299
  slpOutputs,
294
- feePaidBy
300
+ feePaidBy,
301
+ changeAddress
295
302
  );
296
303
  // submit transaction
297
304
  if (txn.success) {
@@ -471,7 +471,7 @@ describe(`Watch only Wallets`, () => {
471
471
  }
472
472
  });
473
473
 
474
- test("Should send to a testnet coins to a random address", async () => {
474
+ test("Should send to testnet coins to a random address", async () => {
475
475
  if (!process.env.ALICE_TESTNET_WALLET_ID) {
476
476
  throw Error("Attempted to pass an empty address");
477
477
  } else {
package/src/wallet/Wif.ts CHANGED
@@ -970,6 +970,13 @@ export class Wallet extends BaseWallet {
970
970
  feePaidBy = FeePaidByEnum.change;
971
971
  }
972
972
 
973
+ let changeAddress;
974
+ if (options && options.changeAddress) {
975
+ changeAddress = options.changeAddress;
976
+ } else {
977
+ changeAddress = "";
978
+ }
979
+
973
980
  // get inputs from options or query all inputs
974
981
  let utxos: UtxoI[];
975
982
  if (options && options.utxoIds) {
@@ -1026,7 +1033,8 @@ export class Wallet extends BaseWallet {
1026
1033
  fee,
1027
1034
  discardChange,
1028
1035
  [],
1029
- feePaidBy
1036
+ feePaidBy,
1037
+ changeAddress
1030
1038
  );
1031
1039
 
1032
1040
  return encodedTransaction;