@alexbosworth/blockchain 3.0.0 → 3.2.0
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/CHANGELOG.md +14 -0
- package/README.md +132 -0
- package/addresses/bech32_type.js +52 -0
- package/addresses/decode_bech32.js +79 -0
- package/addresses/decode_bech32_address.js +86 -0
- package/addresses/index.js +2 -1
- package/addresses/modify_bech32_accumulator.js +24 -0
- package/hashes/id_for_transaction_components.js +2 -0
- package/index.js +16 -0
- package/package.json +1 -1
- package/script/index.js +14 -1
- package/script/p2pkh_output_script.js +37 -0
- package/script/p2sh_output_script.js +35 -0
- package/script/p2tr_output_script.js +32 -0
- package/script/p2wpkh_output_script.js +32 -0
- package/script/p2wsh_output_script.js +32 -0
- package/script/script_elements_as_output.js +41 -0
- package/script/script_elements_as_script.js +3 -22
- package/test/addresses/test_bech32_type.js +29 -0
- package/test/addresses/test_decode_bech32.js +49 -0
- package/test/addresses/test_decode_bech32_address.js +188 -0
- package/test/script/test_p2pkh_output_script.js +41 -0
- package/test/script/test_p2sh_output_script.js +41 -0
- package/test/script/test_p2tr_output_script.js +43 -0
- package/test/script/test_p2wpkh_output_script.js +41 -0
- package/test/script/test_p2wsh_output_script.js +43 -0
- package/test/transactions/test_id_for_transaction.js +72 -0
- package/test/transactions/test_unsigned_tx_from_psbt.js +72 -0
- package/transactions/id_for_transaction.js +39 -0
- package/transactions/index.js +4 -0
- package/transactions/parse_transaction.js +9 -11
- package/transactions/unsigned_tx_from_psbt.js +47 -0
- /package/test/addresses/{decode_base58_address.js → test_decode_base58_address.js} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const {numberAsCompactInt} = require('./../numbers');
|
|
2
|
+
|
|
3
|
+
const {concat} = Buffer;
|
|
4
|
+
const encode = number => numberAsCompactInt({number}).encoded;
|
|
5
|
+
const flatten = arr => arr.reduce((sum, n) => Buffer.concat([sum, n]));
|
|
6
|
+
const {from} = Buffer;
|
|
7
|
+
const {isArray} = Array;
|
|
8
|
+
const {isBuffer} = Buffer;
|
|
9
|
+
|
|
10
|
+
/** Map array of script buffer elements to an output script
|
|
11
|
+
|
|
12
|
+
{
|
|
13
|
+
elements: [<Data Buffer>, <Script OP_CODE Number>]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@throws
|
|
17
|
+
<Error>
|
|
18
|
+
|
|
19
|
+
@returns
|
|
20
|
+
{
|
|
21
|
+
output: <Script Output Buffer Object>
|
|
22
|
+
}
|
|
23
|
+
*/
|
|
24
|
+
module.exports = ({elements}) => {
|
|
25
|
+
if (!isArray(elements)) {
|
|
26
|
+
throw new Error('ExpectedArrayOfScriptElementsToEncodeScript');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Convert numbers to buffers and hex data to pushdata
|
|
30
|
+
const fullScript = elements.map(element => {
|
|
31
|
+
// Exit early when element is a data push
|
|
32
|
+
if (isBuffer(element)) {
|
|
33
|
+
return concat([encode(element.length), element]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Non data elements are direct bytes
|
|
37
|
+
return from([element]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return {output: flatten(fullScript)};
|
|
41
|
+
};
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const scriptElementsAsOutput = require('./script_elements_as_output');
|
|
2
2
|
|
|
3
3
|
const bufferAsHex = buffer => buffer.toString('hex');
|
|
4
|
-
const {concat} = Buffer;
|
|
5
|
-
const encode = number => numberAsCompactInt({number}).encoded;
|
|
6
|
-
const flatten = arr => arr.reduce((sum, n) => Buffer.concat([sum, n]));
|
|
7
|
-
const {from} = Buffer;
|
|
8
|
-
const {isArray} = Array;
|
|
9
|
-
const {isBuffer} = Buffer;
|
|
10
4
|
|
|
11
5
|
/** Map array of script buffer elements to a fully formed script
|
|
12
6
|
|
|
@@ -23,20 +17,7 @@ const {isBuffer} = Buffer;
|
|
|
23
17
|
}
|
|
24
18
|
*/
|
|
25
19
|
module.exports = ({elements}) => {
|
|
26
|
-
|
|
27
|
-
throw new Error('ExpectedArrayOfScriptElementsToEncodeScript');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Convert numbers to buffers and hex data to pushdata
|
|
31
|
-
const fullScript = elements.map(element => {
|
|
32
|
-
// Exit early when element is a data push
|
|
33
|
-
if (isBuffer(element)) {
|
|
34
|
-
return concat([encode(element.length), element]);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Non data elements are direct bytes
|
|
38
|
-
return from([element]);
|
|
39
|
-
});
|
|
20
|
+
const {output} = scriptElementsAsOutput({elements});
|
|
40
21
|
|
|
41
|
-
return {script: bufferAsHex(
|
|
22
|
+
return {script: bufferAsHex(output)};
|
|
42
23
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const {deepEqual} = require('node:assert').strict;
|
|
2
|
+
const test = require('node:test');
|
|
3
|
+
const {throws} = require('node:assert').strict;
|
|
4
|
+
|
|
5
|
+
const bech32Type = require('./../../addresses/bech32_type');
|
|
6
|
+
|
|
7
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {prefix: 'bc', words: [0, 0, 0, 0, 0, 0]},
|
|
12
|
+
description: 'The checksum must derive to a known value',
|
|
13
|
+
error: 'UnexpectedChecksumValueForBech32DataAndPrefix',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
18
|
+
return test(description, (t, end) => {
|
|
19
|
+
if (!!error) {
|
|
20
|
+
throws(() => bech32Type(args), new Error(error), 'Err');
|
|
21
|
+
} else {
|
|
22
|
+
const res = bech32Type(args);
|
|
23
|
+
|
|
24
|
+
deepEqual(res, expected, 'Got expected result');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return end();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const {deepEqual} = require('node:assert').strict;
|
|
2
|
+
const test = require('node:test');
|
|
3
|
+
const {throws} = require('node:assert').strict;
|
|
4
|
+
|
|
5
|
+
const decodeBech32 = require('./../../addresses/decode_bech32');
|
|
6
|
+
|
|
7
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {encoded: null},
|
|
12
|
+
description: 'A bech32 string is expected',
|
|
13
|
+
error: 'ExpectedEncodedStringToDecodeBech32String',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
args: {encoded: 'b'.repeat(91)},
|
|
17
|
+
description: 'A short bech32 string is expected',
|
|
18
|
+
error: 'ExpectedShorterBech32EncodedStringToDecode',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
args: {encoded: 'b'.repeat(7)},
|
|
22
|
+
description: 'A long bech32 string is expected',
|
|
23
|
+
error: 'ExpectedLongerBech32EncodedStringToDecode',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
args: {encoded: '1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P'},
|
|
27
|
+
description: 'A farther divider is expected',
|
|
28
|
+
error: 'ExpectedLaterDividerPositionForBech32String',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
args: {encoded: 'BCKJBC1QR5'},
|
|
32
|
+
description: 'A shorter divider is expected',
|
|
33
|
+
error: 'ExpectedChecksumDataForBech32String',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
38
|
+
return test(description, (t, end) => {
|
|
39
|
+
if (!!error) {
|
|
40
|
+
throws(() => decodeBech32(args), new Error(error), 'Err');
|
|
41
|
+
} else {
|
|
42
|
+
const res = decodeBech32(args);
|
|
43
|
+
|
|
44
|
+
deepEqual(res, expected, 'Got expected result');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return end();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
const {deepEqual} = require('node:assert').strict;
|
|
2
|
+
const test = require('node:test');
|
|
3
|
+
const {throws} = require('node:assert').strict;
|
|
4
|
+
|
|
5
|
+
const {decodeBech32Address} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const hexAsBuffer = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {
|
|
12
|
+
address: 'tc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq5zuyut',
|
|
13
|
+
},
|
|
14
|
+
description: 'Invalid human-readable part',
|
|
15
|
+
error: 'ExpectedKnownBech32AddressPrefixToDecodeBech32',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
args: {
|
|
19
|
+
address: 'bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqh2y7hd',
|
|
20
|
+
},
|
|
21
|
+
description: 'Invalid checksum (Bech32 instead of Bech32m)',
|
|
22
|
+
error: 'ExpectedUseOfLaterVersionBech32PostInitialSegwit',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
args: {
|
|
26
|
+
address: 'tb1z0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqglt7rf',
|
|
27
|
+
},
|
|
28
|
+
description: 'Invalid tb checksum (Bech32 instead of Bech32m)',
|
|
29
|
+
error: 'ExpectedUseOfLaterVersionBech32PostInitialSegwit',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
args: {
|
|
33
|
+
address: 'BC1S0XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ54WELL',
|
|
34
|
+
},
|
|
35
|
+
description: 'Invalid BC checksum (Bech32 instead of Bech32m)',
|
|
36
|
+
error: 'ExpectedUseOfLaterVersionBech32PostInitialSegwit',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
args: {address: 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kemeawh'},
|
|
40
|
+
description: 'Invalid checksum (Bech32m instead of Bech32)',
|
|
41
|
+
error: 'ExpectedInitialSegwitTypeForInitialSegwitVersion',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
args: {
|
|
45
|
+
address: 'tb1q0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq24jc47',
|
|
46
|
+
},
|
|
47
|
+
description: 'Invalid tb checksum (Bech32m instead of Bech32)',
|
|
48
|
+
error: 'ExpectedInitialSegwitTypeForInitialSegwitVersion',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
args: {
|
|
52
|
+
address: 'bc1p38j9r5y49hruaue7wxjce0updqjuyyx0kh56v8s25huc6995vvpql3jow4',
|
|
53
|
+
},
|
|
54
|
+
description: 'Invalid character in checksum',
|
|
55
|
+
error: 'ExpectedAllKnownCharactersForBech32EncodedString',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
args: {
|
|
59
|
+
address: 'BC130XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ7ZWS8R',
|
|
60
|
+
},
|
|
61
|
+
description: 'Invalid witness version',
|
|
62
|
+
error: 'UnexpectedHighSegwitWitnessVersion',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
args: {address: 'bc1pw5dgrnzv'},
|
|
66
|
+
description: 'Invalid program length (1 byte)',
|
|
67
|
+
error: 'UnexpectedSizeOfBech32AddressProgram',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
args: {
|
|
71
|
+
address: 'bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav253zgeav',
|
|
72
|
+
},
|
|
73
|
+
description: 'Invalid program length (41 bytes)',
|
|
74
|
+
error: 'UnexpectedSizeOfBech32AddressProgram',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
args: {address: 'BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P'},
|
|
78
|
+
description: 'Invalid program length for witness version 0 (per BIP141)',
|
|
79
|
+
error: 'UnexpectedBech32AddressProgramSizeForV0Address',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
args: {
|
|
83
|
+
address: 'tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq47Zagq',
|
|
84
|
+
},
|
|
85
|
+
description: 'Mixed case',
|
|
86
|
+
error: 'ExpectedSingleCasingStyleForBech32EncodedString',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
args: {
|
|
90
|
+
address: 'bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v07qwwzcrf',
|
|
91
|
+
},
|
|
92
|
+
description: 'zero padding of more than 4 bits',
|
|
93
|
+
error: 'ExpectedNoPaddingOnBech32Address',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
args: {
|
|
97
|
+
address: 'tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vpggkg4j',
|
|
98
|
+
},
|
|
99
|
+
description: 'Non-zero padding in 8-to-5 conversion',
|
|
100
|
+
error: 'UnexpectedNonZeroPadding',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
args: {address: 'bc1gmk9yu'},
|
|
104
|
+
description: 'Empty data section',
|
|
105
|
+
error: 'ExpectedNonEmptyWitnessCommitmentDataInBech32Address',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
args: {address: 'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4'},
|
|
109
|
+
description: 'Details are returned for a btc1q address',
|
|
110
|
+
expected: {
|
|
111
|
+
prefix: 'bc',
|
|
112
|
+
program: hexAsBuffer('751e76e8199196d454941c45d1b3a323f1433bd6'),
|
|
113
|
+
version: 0,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
args: {
|
|
118
|
+
address: 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7',
|
|
119
|
+
},
|
|
120
|
+
description: 'Details are returned for a tb1q address',
|
|
121
|
+
expected: {
|
|
122
|
+
prefix: 'tb',
|
|
123
|
+
program: hexAsBuffer('1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262'),
|
|
124
|
+
version: 0,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
args: {
|
|
129
|
+
address: 'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y',
|
|
130
|
+
},
|
|
131
|
+
description: 'Details are returned for a bc1p address',
|
|
132
|
+
expected: {
|
|
133
|
+
prefix: 'bc',
|
|
134
|
+
program: hexAsBuffer('751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6'),
|
|
135
|
+
version: 1,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
args: {address: 'BC1SW50QGDZ25J'},
|
|
140
|
+
description: 'Details are returned for a short bc1 address',
|
|
141
|
+
expected: {prefix: 'bc', program: hexAsBuffer('751e'), version: 16},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
args: {address: 'bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs'},
|
|
145
|
+
description: 'Details are returned for a midsize bc1 address',
|
|
146
|
+
expected: {
|
|
147
|
+
prefix: 'bc',
|
|
148
|
+
program: hexAsBuffer('751e76e8199196d454941c45d1b3a323'),
|
|
149
|
+
version: 2,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
args: {
|
|
154
|
+
address: 'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy',
|
|
155
|
+
},
|
|
156
|
+
description: 'Details are returned for a zero starting tb address',
|
|
157
|
+
expected: {
|
|
158
|
+
prefix: 'tb',
|
|
159
|
+
program: hexAsBuffer('000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433'),
|
|
160
|
+
version: 0,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
args: {
|
|
165
|
+
address: 'bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0',
|
|
166
|
+
},
|
|
167
|
+
description: 'Details are returned for a bc1 v1 address',
|
|
168
|
+
expected: {
|
|
169
|
+
prefix: 'bc',
|
|
170
|
+
program: hexAsBuffer('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'),
|
|
171
|
+
version: 1,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
177
|
+
return test(description, (t, end) => {
|
|
178
|
+
if (!!error) {
|
|
179
|
+
throws(() => decodeBech32Address(args), new Error(error), 'Err');
|
|
180
|
+
} else {
|
|
181
|
+
const res = decodeBech32Address(args);
|
|
182
|
+
|
|
183
|
+
deepEqual(res, expected, 'Got expected result');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return end();
|
|
187
|
+
});
|
|
188
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const {deepStrictEqual} = require('node:assert').strict;
|
|
2
|
+
const {throws} = require('node:assert').strict;
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
|
|
5
|
+
const {p2pkhOutputScript} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const bufferFromHex = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {},
|
|
12
|
+
description: 'A hash is required',
|
|
13
|
+
error: 'ExpectedPublicKeyHashToDeriveOutputScript',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
args: {hash: bufferFromHex('12ab8dc588ca9d5787dde7eb29569da63c3a23')},
|
|
17
|
+
description: 'A correctly sized hash is required',
|
|
18
|
+
error: 'UnexpectedHashLengthForPublicKeyHashOutputScript',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
args: {hash: bufferFromHex('12ab8dc588ca9d5787dde7eb29569da63c3a238c')},
|
|
22
|
+
description: 'An output script is derived for a hash',
|
|
23
|
+
expected: {
|
|
24
|
+
script: bufferFromHex('76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac'),
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
30
|
+
return test(description, (t, end) => {
|
|
31
|
+
if (!!error) {
|
|
32
|
+
throws(() => p2pkhOutputScript(args), new Error(error), 'Got err');
|
|
33
|
+
} else {
|
|
34
|
+
const res = p2pkhOutputScript(args);
|
|
35
|
+
|
|
36
|
+
deepStrictEqual(res, expected, 'Got expected result');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return end();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const {deepStrictEqual} = require('node:assert').strict;
|
|
2
|
+
const {throws} = require('node:assert').strict;
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
|
|
5
|
+
const {p2shOutputScript} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const bufferFromHex = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {},
|
|
12
|
+
description: 'A hash is required',
|
|
13
|
+
error: 'ExpectedScriptHashToDerivePayToScriptOutputScript',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
args: {hash: bufferFromHex('433ec2ac1ffa1b7b7d027f564529c57197f9ae')},
|
|
17
|
+
description: 'A correctly sized hash is required',
|
|
18
|
+
error: 'UnexpectedHashLengthForPayToScriptHashOutputScript',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
args: {hash: bufferFromHex('433ec2ac1ffa1b7b7d027f564529c57197f9ae88')},
|
|
22
|
+
description: 'An output script is derived for a hash',
|
|
23
|
+
expected: {
|
|
24
|
+
script: bufferFromHex('a914433ec2ac1ffa1b7b7d027f564529c57197f9ae8887'),
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
30
|
+
return test(description, (t, end) => {
|
|
31
|
+
if (!!error) {
|
|
32
|
+
throws(() => p2shOutputScript(args), new Error(error), 'Got err');
|
|
33
|
+
} else {
|
|
34
|
+
const res = p2shOutputScript(args);
|
|
35
|
+
|
|
36
|
+
deepStrictEqual(res, expected, 'Got expected result');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return end();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const {deepStrictEqual} = require('node:assert').strict;
|
|
2
|
+
const {throws} = require('node:assert').strict;
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
|
|
5
|
+
const {p2trOutputScript} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const bufferFromHex = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {},
|
|
12
|
+
description: 'A hash is required',
|
|
13
|
+
error: 'ExpectedTaprootHashToDeriveOutputScript',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
args: {hash: bufferFromHex('8d7a0a3461e3891723e5fdf8129caa0075060c')},
|
|
17
|
+
description: 'A correctly sized hash is required',
|
|
18
|
+
error: 'ExpectedKnownLengthTaprootHashForOutputScript',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
args: {
|
|
22
|
+
hash: bufferFromHex('667bdd93c7c029767fd516d2ea292624b938fefefa175ac9f1220cf508963ff3'),
|
|
23
|
+
},
|
|
24
|
+
description: 'An output script is derived for a hash',
|
|
25
|
+
expected: {
|
|
26
|
+
script: bufferFromHex('5120667bdd93c7c029767fd516d2ea292624b938fefefa175ac9f1220cf508963ff3'),
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
32
|
+
return test(description, (t, end) => {
|
|
33
|
+
if (!!error) {
|
|
34
|
+
throws(() => p2trOutputScript(args), new Error(error), 'Got err');
|
|
35
|
+
} else {
|
|
36
|
+
const res = p2trOutputScript(args);
|
|
37
|
+
|
|
38
|
+
deepStrictEqual(res, expected, 'Got expected result');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return end();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const {deepStrictEqual} = require('node:assert').strict;
|
|
2
|
+
const {throws} = require('node:assert').strict;
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
|
|
5
|
+
const {p2wpkhOutputScript} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const bufferFromHex = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {},
|
|
12
|
+
description: 'A hash is required',
|
|
13
|
+
error: 'ExpectedWitnessPublicKeyHashToDeriveOutputScript',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
args: {hash: bufferFromHex('8d7a0a3461e3891723e5fdf8129caa0075060c')},
|
|
17
|
+
description: 'A correctly sized hash is required',
|
|
18
|
+
error: 'ExpectedKnownLengthWitnessPublicKeyHashForOutputScript',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
args: {hash: bufferFromHex('8d7a0a3461e3891723e5fdf8129caa0075060cff')},
|
|
22
|
+
description: 'An output script is derived for a hash',
|
|
23
|
+
expected: {
|
|
24
|
+
script: bufferFromHex('00148d7a0a3461e3891723e5fdf8129caa0075060cff'),
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
30
|
+
return test(description, (t, end) => {
|
|
31
|
+
if (!!error) {
|
|
32
|
+
throws(() => p2wpkhOutputScript(args), new Error(error), 'Got err');
|
|
33
|
+
} else {
|
|
34
|
+
const res = p2wpkhOutputScript(args);
|
|
35
|
+
|
|
36
|
+
deepStrictEqual(res, expected, 'Got expected result');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return end();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const {deepStrictEqual} = require('node:assert').strict;
|
|
2
|
+
const {throws} = require('node:assert').strict;
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
|
|
5
|
+
const {p2wshOutputScript} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const bufferFromHex = hex => Buffer.from(hex, 'hex');
|
|
8
|
+
|
|
9
|
+
const tests = [
|
|
10
|
+
{
|
|
11
|
+
args: {},
|
|
12
|
+
description: 'A hash is required',
|
|
13
|
+
error: 'ExpectedWitnessScriptHashToDeriveOutputScript',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
args: {hash: bufferFromHex('8d7a0a3461e3891723e5fdf8129caa0075060c')},
|
|
17
|
+
description: 'A correctly sized hash is required',
|
|
18
|
+
error: 'ExpectedKnownLengthWitnessScriptHashForOutputScript',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
args: {
|
|
22
|
+
hash: bufferFromHex('cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70'),
|
|
23
|
+
},
|
|
24
|
+
description: 'An output script is derived for a hash',
|
|
25
|
+
expected: {
|
|
26
|
+
script: bufferFromHex('0020cdbf909e935c855d3e8d1b61aeb9c5e3c03ae8021b286839b1a72f2e48fdba70'),
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
32
|
+
return test(description, (t, end) => {
|
|
33
|
+
if (!!error) {
|
|
34
|
+
throws(() => p2wshOutputScript(args), new Error(error), 'Got err');
|
|
35
|
+
} else {
|
|
36
|
+
const res = p2wshOutputScript(args);
|
|
37
|
+
|
|
38
|
+
deepStrictEqual(res, expected, 'Got expected result');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return end();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const {deepStrictEqual} = require('node:assert').strict;
|
|
2
|
+
const {throws} = require('node:assert').strict;
|
|
3
|
+
const test = require('node:test');
|
|
4
|
+
|
|
5
|
+
const {idForTransaction} = require('./../../');
|
|
6
|
+
|
|
7
|
+
const tests = [
|
|
8
|
+
{
|
|
9
|
+
args: {transaction: ''},
|
|
10
|
+
description: 'A transaction hex is required',
|
|
11
|
+
error: 'ExpectedHexEncodedTransactionToGetComponentsOf',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
args: {
|
|
15
|
+
transaction: '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000',
|
|
16
|
+
},
|
|
17
|
+
description: 'A coinbase transaction',
|
|
18
|
+
expected: {
|
|
19
|
+
id: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
args: {
|
|
24
|
+
transaction: '01000000019ac03d5ae6a875d970128ef9086cef276a1919684a6988023cc7254691d97e6d010000006b4830450221009d41dc793ba24e65f571473d40b299b6459087cea1509f0d381740b1ac863cb6022039c425906fcaf51b2b84d8092569fb3213de43abaff2180e2a799d4fcb4dd0aa012102d5ede09a8ae667d0f855ef90325e27f6ce35bbe60a1e6e87af7f5b3c652140fdffffffff080100000000000000010101000000000000000202010100000000000000014c0100000000000000034c02010100000000000000014d0100000000000000044dffff010100000000000000014e0100000000000000064effffffff0100000000',
|
|
25
|
+
},
|
|
26
|
+
description: 'invalid script',
|
|
27
|
+
expected: {
|
|
28
|
+
id: 'ebc9fa1196a59e192352d76c0f6e73167046b9d37b8302b6bb6968dfd279b767',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
args: {
|
|
33
|
+
transaction: '02000000000103ae8caf3aad8861142597a29d6377f524a55f4542d5294c8292ce123a956d3e520000000000ffffffff9cbb1c5531a677b90c489d75a198a14f02d49e554ab9cdaa17bd956b127724570200000000ffffffff9cbb1c5531a677b90c489d75a198a14f02d49e554ab9cdaa17bd956b127724570100000000ffffffff0640420f0000000000160014eaa9b76637b1ad340b6efadf773a73b53637d5b6de91f62901000000225120f4c82416bcb08422c195af995e1d248d1378d8b48dafa9f45bc213b83101d49240420f00000000001600148729d17b2aa507ab19051a028384bc6e0ce25e455e368900000000002251200249ccc5af06fa5642f12d42d2a34bfbb08688d54a9b99d07b98619b35df03b440420f0000000000160014d2d59a8a59f997cbc8888411010faf1658e0e3465e368900000000002251207febd720c78518b52aa1a2443823cc8f55e373910f616e112d5d7bd622fe1ab2024830450221008ac71eff4d7e298941be012fc14f0ac9bf62ae6ffeac13522bb27b5b4108d3aa0220192a69ad6fdb86b1e09c7fdcaaafeb58d25060e44199c734dc0d7d385b5d800d0121029943eaccd3987fa495a6b4f47f2fafeb0521e4e12f39498d9465a564ef75329602483045022100f9cde9adb00c0a6c62dae8604ca750039201288c0dafff952461da3caf05e3ae0220679c01f2518413951de3b62531b1cf36bb92562e3bd4197f0fa6e6e3e231272e0121027326b48c9f2729597e328ab6d05f5af75866e1ffa203fadf78387a3b202ff80d0247304402202550beec478845af2df929abf85708f9fcceaae31377f2e01d803e2acf7b426f022036c312b1e38ca333fe70aa37d3093387ac7486f08438eb8eed323699594468cb012102275a197f7ccfece19cf0532b068b6e38ceceda146e791875ecbdc55500bb7efe00000000',
|
|
34
|
+
},
|
|
35
|
+
description: 'Transaction with witnesses and P2TR and P2WPKH outputs',
|
|
36
|
+
expected: {
|
|
37
|
+
id: 'ab940e8efd07f7f85f907e36f8e6509ab795de91bbd3e0fa69781549464506a4',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
args: {
|
|
42
|
+
transaction: '0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000',
|
|
43
|
+
},
|
|
44
|
+
description: 'A non-segwit transaction is read',
|
|
45
|
+
expected: {
|
|
46
|
+
id: 'cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
args: {
|
|
51
|
+
transaction: '0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000',
|
|
52
|
+
},
|
|
53
|
+
description: 'A P2PK transaction is read',
|
|
54
|
+
expected: {
|
|
55
|
+
id: 'f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
tests.forEach(({args, description, error, expected}) => {
|
|
61
|
+
return test(description, (t, end) => {
|
|
62
|
+
if (!!error) {
|
|
63
|
+
throws(() => idForTransaction(args), new Error(error), 'Got err');
|
|
64
|
+
} else {
|
|
65
|
+
const res = idForTransaction(args);
|
|
66
|
+
|
|
67
|
+
deepStrictEqual(res, expected, 'Got expected result');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return end();
|
|
71
|
+
});
|
|
72
|
+
});
|