mainnet-js 2.2.4 → 2.2.6
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/README.md +3 -0
- package/dist/index.html +1 -1
- package/dist/{mainnet-2.2.4.js → mainnet-2.2.6.js} +2 -2
- package/dist/module/message/interface.d.ts +1 -0
- package/dist/module/message/interface.d.ts.map +1 -1
- package/dist/module/message/signed.d.ts.map +1 -1
- package/dist/module/message/signed.js +12 -7
- package/dist/module/message/signed.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +17 -5
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/message/interface.ts +1 -0
- package/src/message/signed.test.ts +86 -0
- package/src/message/signed.ts +12 -7
- package/src/wallet/Wif.ts +31 -4
- package/src/wallet/Wif.watchOnly.test.ts +58 -0
|
@@ -45,6 +45,18 @@ describe("Test message Signing and Verification", () => {
|
|
|
45
45
|
"gE9BDBFAOqW+yoOzABjnM+LQRWHd4dvUVrsTR+sIWsU="
|
|
46
46
|
);
|
|
47
47
|
expect(result.details!.publicKeyHashMatch).toBe(true);
|
|
48
|
+
expect(result.details!.publicKeyMatch).toBe(false);
|
|
49
|
+
expect(result.details!.signatureValid).toBe(true);
|
|
50
|
+
expect(result.details!.signatureType).toBe("recoverable");
|
|
51
|
+
|
|
52
|
+
let msg2 = "Lessons for China from Japan’s lost decade";
|
|
53
|
+
result = await SignedMessage.verify(msg2, sig.signature, w1.cashaddr!);
|
|
54
|
+
expect(result.valid).toBe(false);
|
|
55
|
+
expect(result.details!.messageHash).toBe(
|
|
56
|
+
"070kQIcYPSHApGdOGH0O81N1AkMbNKwCTM3IX2Svd3I="
|
|
57
|
+
);
|
|
58
|
+
expect(result.details!.publicKeyHashMatch).toBe(false);
|
|
59
|
+
expect(result.details!.publicKeyMatch).toBe(false);
|
|
48
60
|
expect(result.details!.signatureValid).toBe(true);
|
|
49
61
|
expect(result.details!.signatureType).toBe("recoverable");
|
|
50
62
|
});
|
|
@@ -64,6 +76,9 @@ describe("Test message Signing and Verification", () => {
|
|
|
64
76
|
let sig = await SignedMessage.sign(msg, w.privateKey!);
|
|
65
77
|
let result = await SignedMessage.verify(msg, sig.signature, w.cashaddr!);
|
|
66
78
|
expect(result.valid).toBe(true);
|
|
79
|
+
|
|
80
|
+
result = await SignedMessage.verify("test2", sig.signature, w.cashaddr!);
|
|
81
|
+
expect(result.valid).toBe(false);
|
|
67
82
|
});
|
|
68
83
|
|
|
69
84
|
test("Test signing and verifying regtest signature using Alice's wallet", async () => {
|
|
@@ -75,6 +90,9 @@ describe("Test message Signing and Verification", () => {
|
|
|
75
90
|
|
|
76
91
|
let result = await SignedMessage.verify(msg, sig.signature, w.cashaddr!);
|
|
77
92
|
expect(result.valid).toBe(true);
|
|
93
|
+
|
|
94
|
+
result = await SignedMessage.verify("test2", sig.signature, w.cashaddr!);
|
|
95
|
+
expect(result.valid).toBe(false);
|
|
78
96
|
});
|
|
79
97
|
|
|
80
98
|
test("Test signing and verifying regtest signature using Alice's wallet", async () => {
|
|
@@ -85,6 +103,9 @@ describe("Test message Signing and Verification", () => {
|
|
|
85
103
|
let sig = await SignedMessage.sign(msg, w.privateKey!);
|
|
86
104
|
let result = await SignedMessage.verify(msg, sig.signature, w.cashaddr!);
|
|
87
105
|
expect(result.valid).toBe(true);
|
|
106
|
+
|
|
107
|
+
result = await SignedMessage.verify("测试二", sig.signature, w.cashaddr!);
|
|
108
|
+
expect(result.valid).toBe(false);
|
|
88
109
|
});
|
|
89
110
|
|
|
90
111
|
test("Test signing and verifying a schnorr signature", async () => {
|
|
@@ -101,6 +122,16 @@ describe("Test message Signing and Verification", () => {
|
|
|
101
122
|
);
|
|
102
123
|
expect(result.valid).toBe(true);
|
|
103
124
|
expect(result.details!.signatureType).toBe("schnorr");
|
|
125
|
+
|
|
126
|
+
let msg2 =
|
|
127
|
+
"Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
|
|
128
|
+
let invalid = await SignedMessage.verify(
|
|
129
|
+
msg2,
|
|
130
|
+
sig.raw!.schnorr,
|
|
131
|
+
undefined,
|
|
132
|
+
w.publicKey!
|
|
133
|
+
);
|
|
134
|
+
expect(invalid.valid).toBe(false);
|
|
104
135
|
});
|
|
105
136
|
|
|
106
137
|
test("Test signing and verifying a der signature", async () => {
|
|
@@ -133,6 +164,16 @@ describe("Test message Signing and Verification", () => {
|
|
|
133
164
|
);
|
|
134
165
|
expect(result.valid).toBe(true);
|
|
135
166
|
expect(result.details!.signatureType).toBe("ecdsa");
|
|
167
|
+
|
|
168
|
+
let msg2 =
|
|
169
|
+
"Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
|
|
170
|
+
let invalid = await SignedMessage.verify(
|
|
171
|
+
msg2,
|
|
172
|
+
sig.raw!.ecdsa,
|
|
173
|
+
undefined,
|
|
174
|
+
w.publicKey!
|
|
175
|
+
);
|
|
176
|
+
expect(invalid.valid).toBe(false);
|
|
136
177
|
});
|
|
137
178
|
|
|
138
179
|
test("Test signing and verifying a long message", async () => {
|
|
@@ -160,10 +201,20 @@ describe("Test message Signing and Verification", () => {
|
|
|
160
201
|
w1.cashaddr!
|
|
161
202
|
);
|
|
162
203
|
expect(result.valid).toBe(true);
|
|
204
|
+
|
|
205
|
+
let msg2 =
|
|
206
|
+
"Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
|
|
207
|
+
let invalid = await Wallet.signedMessage.verify(
|
|
208
|
+
msg2,
|
|
209
|
+
sig.signature,
|
|
210
|
+
w1.cashaddr!
|
|
211
|
+
);
|
|
212
|
+
expect(invalid.valid).toBe(false);
|
|
163
213
|
});
|
|
164
214
|
|
|
165
215
|
test("Test electron cash example from a wallet instance", async () => {
|
|
166
216
|
let msg1 = "Chancellor on brink of second bailout for banks";
|
|
217
|
+
|
|
167
218
|
let w1 = await Wallet.fromId(
|
|
168
219
|
`wif:mainnet:L1TnU2zbNaAqMoVh65Cyvmcjzbrj41Gs9iTLcWbpJCMynXuap6UN`
|
|
169
220
|
);
|
|
@@ -173,5 +224,40 @@ describe("Test message Signing and Verification", () => {
|
|
|
173
224
|
let sig = await w1.sign(msg1);
|
|
174
225
|
let result = await w1.verify(msg1, sig.signature);
|
|
175
226
|
expect(result.valid).toBe(true);
|
|
227
|
+
|
|
228
|
+
let msg2 =
|
|
229
|
+
"Biggest Selloff in 25 Years Hits Japan Bonds as BOJ Loosens Grip";
|
|
230
|
+
let invalid = await w1.verify(msg2, sig.signature);
|
|
231
|
+
expect(invalid.valid).toBe(false);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("Test electron cash example from a wallet instance", async () => {
|
|
235
|
+
let beak = "Eeny meeny, hide & seek―catch a cephalopod by the beak";
|
|
236
|
+
let beakSig =
|
|
237
|
+
"H2a0aK6ZhF5rii4yzKkE+15yLTaQPa4KzoGXwYNHm5I+OYxRdcpTiUVZm3h6+ocy2JYxb0UUrQn7UWh8IcxzEtk=";
|
|
238
|
+
|
|
239
|
+
let falseMessage = "Employer provided healthcare is a benefit.";
|
|
240
|
+
|
|
241
|
+
let w1 = await Wallet.fromId(
|
|
242
|
+
`watch:mainnet:qqad5sy4jml3f6vcp246dulsex04xp48wq23d35rqe`
|
|
243
|
+
);
|
|
244
|
+
expect(w1.cashaddr!).toBe(
|
|
245
|
+
"bitcoincash:qqad5sy4jml3f6vcp246dulsex04xp48wq23d35rqe"
|
|
246
|
+
);
|
|
247
|
+
let result = await w1.verify(beak, beakSig);
|
|
248
|
+
expect(result.valid).toBe(true);
|
|
249
|
+
expect(result.details?.publicKeyHashMatch).toBe(true);
|
|
250
|
+
expect(result.details?.publicKeyMatch).toBe(false);
|
|
251
|
+
expect(result.details?.signatureValid).toBe(true);
|
|
252
|
+
expect(result.details?.signatureType).toBe("recoverable");
|
|
253
|
+
|
|
254
|
+
let badResult = await w1.verify(falseMessage, beakSig);
|
|
255
|
+
expect(badResult.valid).toBe(false);
|
|
256
|
+
|
|
257
|
+
// While the recoverable sig is valid, it doesn't match the message.
|
|
258
|
+
expect(badResult.details?.signatureValid).toBe(true);
|
|
259
|
+
expect(badResult.details?.publicKeyHashMatch).toBe(false);
|
|
260
|
+
expect(badResult.details?.publicKeyMatch).toBe(false);
|
|
261
|
+
expect(result.details?.signatureType).toBe("recoverable");
|
|
176
262
|
});
|
|
177
263
|
});
|
package/src/message/signed.ts
CHANGED
|
@@ -125,7 +125,8 @@ export class SignedMessage implements SignedMessageI {
|
|
|
125
125
|
let messageHash = await hash_message(message);
|
|
126
126
|
let sig = base64ToBin(signature);
|
|
127
127
|
|
|
128
|
-
let
|
|
128
|
+
let signatureValid = false;
|
|
129
|
+
let keyMatch = false;
|
|
129
130
|
let pkhMatch = false;
|
|
130
131
|
let pkh, signatureType;
|
|
131
132
|
|
|
@@ -143,7 +144,7 @@ export class SignedMessage implements SignedMessageI {
|
|
|
143
144
|
|
|
144
145
|
pkh = await hash160(recoveredPk);
|
|
145
146
|
signatureType = "recoverable";
|
|
146
|
-
|
|
147
|
+
signatureValid = secp256k1.verifySignatureCompact(
|
|
147
148
|
rawSig,
|
|
148
149
|
recoveredPk,
|
|
149
150
|
messageHash
|
|
@@ -163,29 +164,33 @@ export class SignedMessage implements SignedMessageI {
|
|
|
163
164
|
} else if (publicKey) {
|
|
164
165
|
if (secp256k1.verifySignatureDER(sig, publicKey, messageHash)) {
|
|
165
166
|
signatureType = "der";
|
|
166
|
-
|
|
167
|
+
signatureValid = true;
|
|
168
|
+
keyMatch = true;
|
|
167
169
|
} else if (
|
|
168
170
|
secp256k1.verifySignatureSchnorr(sig, publicKey, messageHash)
|
|
169
171
|
) {
|
|
170
172
|
signatureType = "schnorr";
|
|
171
|
-
|
|
173
|
+
signatureValid = true;
|
|
174
|
+
keyMatch = true;
|
|
172
175
|
} else if (
|
|
173
176
|
secp256k1.verifySignatureCompact(sig, publicKey, messageHash)
|
|
174
177
|
) {
|
|
175
178
|
signatureType = "ecdsa";
|
|
176
|
-
|
|
179
|
+
signatureValid = true;
|
|
180
|
+
keyMatch = true;
|
|
177
181
|
} else {
|
|
178
182
|
signatureType = "na";
|
|
179
183
|
}
|
|
180
184
|
}
|
|
181
185
|
|
|
182
186
|
return {
|
|
183
|
-
valid:
|
|
187
|
+
valid: signatureValid && (keyMatch || pkhMatch),
|
|
184
188
|
details: {
|
|
185
|
-
signatureValid:
|
|
189
|
+
signatureValid: signatureValid,
|
|
186
190
|
signatureType: signatureType,
|
|
187
191
|
messageHash: binToBase64(messageHash),
|
|
188
192
|
publicKeyHashMatch: pkhMatch,
|
|
193
|
+
publicKeyMatch: keyMatch,
|
|
189
194
|
},
|
|
190
195
|
};
|
|
191
196
|
}
|
package/src/wallet/Wif.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
//#region Imports
|
|
2
2
|
// Stable
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
decodeCashAddress,
|
|
5
|
+
decodeCashAddressVersionByte,
|
|
6
|
+
encodeHdPublicKey,
|
|
7
|
+
HdKeyNetwork,
|
|
8
|
+
secp256k1,
|
|
9
|
+
} from "@bitauth/libauth";
|
|
4
10
|
|
|
5
11
|
// Unstable?
|
|
6
12
|
import {
|
|
7
13
|
binToHex,
|
|
8
14
|
CashAddressNetworkPrefix,
|
|
15
|
+
CashAddressType,
|
|
9
16
|
deriveHdPublicNode,
|
|
10
17
|
decodePrivateKeyWif,
|
|
18
|
+
encodeCashAddress,
|
|
11
19
|
encodePrivateKeyWif,
|
|
12
20
|
deriveHdPrivateNodeFromSeed,
|
|
13
21
|
deriveHdPath,
|
|
@@ -497,10 +505,29 @@ export class Wallet extends BaseWallet {
|
|
|
497
505
|
}
|
|
498
506
|
}
|
|
499
507
|
|
|
500
|
-
|
|
508
|
+
const prefixedAddress = `${addressPrefix}:${addressBase}`;
|
|
509
|
+
|
|
510
|
+
// check if a token aware address was provided
|
|
511
|
+
let addressData = decodeCashAddress(prefixedAddress);
|
|
512
|
+
if (typeof addressData === "string") throw addressData;
|
|
513
|
+
|
|
514
|
+
this.publicKeyHash = addressData.payload;
|
|
515
|
+
|
|
516
|
+
let nonTokenAwareType = addressData.type;
|
|
517
|
+
if (nonTokenAwareType == CashAddressType.p2pkhWithTokens)
|
|
518
|
+
nonTokenAwareType = CashAddressType.p2pkh;
|
|
519
|
+
if (nonTokenAwareType == CashAddressType.p2shWithTokens)
|
|
520
|
+
nonTokenAwareType = CashAddressType.p2sh;
|
|
521
|
+
if (nonTokenAwareType == CashAddressType.p2pkh)
|
|
522
|
+
this.publicKeyHash = addressData.payload;
|
|
523
|
+
|
|
524
|
+
this.cashaddr = encodeCashAddress(
|
|
525
|
+
addressData.prefix as CashAddressNetworkPrefix,
|
|
526
|
+
nonTokenAwareType,
|
|
527
|
+
addressData.payload
|
|
528
|
+
);
|
|
501
529
|
this.address = this.cashaddr;
|
|
502
|
-
this.
|
|
503
|
-
this.tokenaddr = deriveTokenaddr(this.publicKeyHash, this.networkPrefix);
|
|
530
|
+
this.tokenaddr = deriveTokenaddr(addressData.payload, this.networkPrefix);
|
|
504
531
|
|
|
505
532
|
return this;
|
|
506
533
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { RegTestWallet, TestNetWallet, Wallet } from "./Wif";
|
|
2
|
+
import { initProviders, disconnectProviders } from "../network/Connection";
|
|
3
|
+
|
|
4
|
+
beforeAll(async () => {
|
|
5
|
+
await initProviders();
|
|
6
|
+
});
|
|
7
|
+
afterAll(async () => {
|
|
8
|
+
await disconnectProviders();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
describe(`Test creation of wallet from walletId`, () => {
|
|
12
|
+
test("Get a regtest wallet from string id", async () => {
|
|
13
|
+
const ADDRESS = "bchreg:qpttdv3qg2usm4nm7talhxhl05mlhms3ys43u76rn0";
|
|
14
|
+
const ADDRESS_TOKEN = "bchreg:zpttdv3qg2usm4nm7talhxhl05mlhms3ysjm0q59vu";
|
|
15
|
+
|
|
16
|
+
let w = await RegTestWallet.fromId(
|
|
17
|
+
"wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
expect(w.cashaddr!.startsWith("bchreg:")).toBeTruthy();
|
|
21
|
+
expect(w.address!).toBe(ADDRESS);
|
|
22
|
+
expect(w.cashaddr!).toBe(ADDRESS);
|
|
23
|
+
expect(w.tokenaddr!).toBe(ADDRESS_TOKEN);
|
|
24
|
+
let w2 = await RegTestWallet.watchOnly(w.cashaddr!);
|
|
25
|
+
|
|
26
|
+
expect(w2.address!).toBe(ADDRESS);
|
|
27
|
+
expect(w2.cashaddr!).toBe(ADDRESS);
|
|
28
|
+
expect(w2.tokenaddr!).toBe(ADDRESS_TOKEN);
|
|
29
|
+
|
|
30
|
+
let w3 = await RegTestWallet.watchOnly(ADDRESS_TOKEN);
|
|
31
|
+
expect(w3.address!).toBe(ADDRESS);
|
|
32
|
+
expect(w3.cashaddr!).toBe(ADDRESS);
|
|
33
|
+
expect(w3.tokenaddr!).toBe(ADDRESS_TOKEN);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("Get create a p2sh32 watch address", async () => {
|
|
37
|
+
const ADDRESS =
|
|
38
|
+
"bitcoincash:pvykylj7uk385669fjse37r2eknx35ngaalx805q2hul62lmx2fq2v5dx6g8w";
|
|
39
|
+
|
|
40
|
+
let w = await Wallet.watchOnly(
|
|
41
|
+
"bitcoincash:pvykylj7uk385669fjse37r2eknx35ngaalx805q2hul62lmx2fq2v5dx6g8w"
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(w.cashaddr!.startsWith("bitcoincash:")).toBeTruthy();
|
|
45
|
+
expect(w.address!).toBe(ADDRESS);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("Get create a p2sh watch address", async () => {
|
|
49
|
+
const ADDRESS = "bitcoincash:pzvts0uztwg32yvrx7xz9lp572dgnt20sy0dj993vx";
|
|
50
|
+
|
|
51
|
+
let w = await Wallet.watchOnly(
|
|
52
|
+
"bitcoincash:pzvts0uztwg32yvrx7xz9lp572dgnt20sy0dj993vx"
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(w.cashaddr!.startsWith("bitcoincash:")).toBeTruthy();
|
|
56
|
+
expect(w.address!).toBe(ADDRESS);
|
|
57
|
+
});
|
|
58
|
+
});
|