@vbyte/btc-dev 1.1.8 → 2.0.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.
Files changed (174) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +260 -3
  3. package/dist/const.d.ts +3 -0
  4. package/dist/const.js +23 -22
  5. package/dist/index.d.ts +11 -11
  6. package/dist/index.js +10 -10
  7. package/dist/lib/address/api.d.ts +2 -2
  8. package/dist/lib/address/api.js +12 -12
  9. package/dist/lib/address/encode.d.ts +1 -1
  10. package/dist/lib/address/encode.js +24 -24
  11. package/dist/lib/address/index.d.ts +6 -6
  12. package/dist/lib/address/index.js +6 -6
  13. package/dist/lib/address/p2pkh.d.ts +2 -2
  14. package/dist/lib/address/p2pkh.js +14 -14
  15. package/dist/lib/address/p2sh.d.ts +2 -2
  16. package/dist/lib/address/p2sh.js +13 -13
  17. package/dist/lib/address/p2tr.d.ts +2 -2
  18. package/dist/lib/address/p2tr.js +13 -13
  19. package/dist/lib/address/p2wpkh.d.ts +2 -2
  20. package/dist/lib/address/p2wpkh.js +14 -14
  21. package/dist/lib/address/p2wsh.d.ts +2 -2
  22. package/dist/lib/address/p2wsh.js +13 -13
  23. package/dist/lib/address/script.d.ts +1 -1
  24. package/dist/lib/address/script.js +16 -16
  25. package/dist/lib/address/util.d.ts +1 -1
  26. package/dist/lib/address/util.js +22 -22
  27. package/dist/lib/meta/index.d.ts +4 -4
  28. package/dist/lib/meta/index.js +4 -4
  29. package/dist/lib/meta/locktime.d.ts +1 -1
  30. package/dist/lib/meta/locktime.js +12 -12
  31. package/dist/lib/meta/ref.js +9 -6
  32. package/dist/lib/meta/scribe.d.ts +2 -2
  33. package/dist/lib/meta/scribe.js +48 -53
  34. package/dist/lib/meta/sequence.d.ts +1 -1
  35. package/dist/lib/meta/sequence.js +16 -15
  36. package/dist/lib/script/decode.d.ts +2 -2
  37. package/dist/lib/script/decode.js +50 -15
  38. package/dist/lib/script/encode.d.ts +1 -1
  39. package/dist/lib/script/encode.js +20 -16
  40. package/dist/lib/script/index.d.ts +5 -13
  41. package/dist/lib/script/index.js +5 -14
  42. package/dist/lib/script/lock.d.ts +2 -2
  43. package/dist/lib/script/lock.js +15 -12
  44. package/dist/lib/script/util.js +4 -4
  45. package/dist/lib/script/words.js +129 -129
  46. package/dist/lib/sighash/index.d.ts +3 -3
  47. package/dist/lib/sighash/index.js +3 -3
  48. package/dist/lib/sighash/segwit.d.ts +2 -2
  49. package/dist/lib/sighash/segwit.js +15 -14
  50. package/dist/lib/sighash/taproot.d.ts +2 -2
  51. package/dist/lib/sighash/taproot.js +24 -23
  52. package/dist/lib/sighash/util.d.ts +2 -2
  53. package/dist/lib/sighash/util.js +7 -7
  54. package/dist/lib/signer/index.d.ts +2 -2
  55. package/dist/lib/signer/index.js +2 -2
  56. package/dist/lib/signer/sign.d.ts +1 -1
  57. package/dist/lib/signer/sign.js +42 -7
  58. package/dist/lib/signer/verify.d.ts +17 -3
  59. package/dist/lib/signer/verify.js +233 -3
  60. package/dist/lib/taproot/cblock.d.ts +1 -1
  61. package/dist/lib/taproot/cblock.js +14 -16
  62. package/dist/lib/taproot/encode.d.ts +1 -1
  63. package/dist/lib/taproot/encode.js +7 -7
  64. package/dist/lib/taproot/index.d.ts +4 -4
  65. package/dist/lib/taproot/index.js +4 -4
  66. package/dist/lib/taproot/parse.d.ts +1 -1
  67. package/dist/lib/taproot/parse.js +12 -14
  68. package/dist/lib/taproot/tree.d.ts +2 -2
  69. package/dist/lib/taproot/tree.js +11 -7
  70. package/dist/lib/tx/create.d.ts +1 -1
  71. package/dist/lib/tx/create.js +28 -12
  72. package/dist/lib/tx/decode.d.ts +2 -2
  73. package/dist/lib/tx/decode.js +50 -17
  74. package/dist/lib/tx/encode.d.ts +2 -2
  75. package/dist/lib/tx/encode.js +13 -16
  76. package/dist/lib/tx/index.d.ts +7 -7
  77. package/dist/lib/tx/index.js +7 -7
  78. package/dist/lib/tx/parse.d.ts +1 -1
  79. package/dist/lib/tx/parse.js +9 -9
  80. package/dist/lib/tx/size.d.ts +2 -2
  81. package/dist/lib/tx/size.js +9 -9
  82. package/dist/lib/tx/util.d.ts +2 -2
  83. package/dist/lib/tx/util.js +23 -20
  84. package/dist/lib/tx/validate.d.ts +1 -1
  85. package/dist/lib/tx/validate.js +3 -3
  86. package/dist/lib/witness/index.d.ts +2 -2
  87. package/dist/lib/witness/index.js +2 -2
  88. package/dist/lib/witness/parse.d.ts +2 -2
  89. package/dist/lib/witness/parse.js +24 -23
  90. package/dist/lib/witness/util.d.ts +2 -2
  91. package/dist/lib/witness/util.js +5 -5
  92. package/dist/main.cjs +2308 -1005
  93. package/dist/main.cjs.map +1 -1
  94. package/dist/module.mjs +2308 -1005
  95. package/dist/module.mjs.map +1 -1
  96. package/dist/package.json +20 -17
  97. package/dist/schema/base.d.ts +1 -1
  98. package/dist/schema/base.js +17 -13
  99. package/dist/schema/index.d.ts +2 -2
  100. package/dist/schema/index.js +2 -2
  101. package/dist/schema/taproot.d.ts +1 -1
  102. package/dist/schema/taproot.js +2 -2
  103. package/dist/schema/tx.d.ts +1 -1
  104. package/dist/schema/tx.js +4 -4
  105. package/dist/script.js +8 -8
  106. package/dist/script.js.map +1 -1
  107. package/dist/types/address.d.ts +4 -4
  108. package/dist/types/index.d.ts +8 -8
  109. package/dist/types/index.js +8 -8
  110. package/dist/types/meta.d.ts +4 -4
  111. package/dist/types/psbt.d.ts +2 -2
  112. package/dist/types/script.d.ts +2 -2
  113. package/dist/types/sighash.d.ts +2 -2
  114. package/dist/types/witness.d.ts +5 -5
  115. package/package.json +20 -17
  116. package/src/const.ts +0 -61
  117. package/src/index.ts +0 -13
  118. package/src/lib/address/api.ts +0 -50
  119. package/src/lib/address/encode.ts +0 -183
  120. package/src/lib/address/index.ts +0 -7
  121. package/src/lib/address/p2pkh.ts +0 -94
  122. package/src/lib/address/p2sh.ts +0 -96
  123. package/src/lib/address/p2tr.ts +0 -91
  124. package/src/lib/address/p2wpkh.ts +0 -94
  125. package/src/lib/address/p2wsh.ts +0 -92
  126. package/src/lib/address/script.ts +0 -63
  127. package/src/lib/address/util.ts +0 -87
  128. package/src/lib/meta/index.ts +0 -4
  129. package/src/lib/meta/locktime.ts +0 -57
  130. package/src/lib/meta/ref.ts +0 -107
  131. package/src/lib/meta/scribe.ts +0 -256
  132. package/src/lib/meta/sequence.ts +0 -146
  133. package/src/lib/script/decode.ts +0 -85
  134. package/src/lib/script/encode.ts +0 -129
  135. package/src/lib/script/index.ts +0 -20
  136. package/src/lib/script/lock.ts +0 -73
  137. package/src/lib/script/util.ts +0 -78
  138. package/src/lib/script/words.ts +0 -182
  139. package/src/lib/sighash/index.ts +0 -3
  140. package/src/lib/sighash/segwit.ts +0 -152
  141. package/src/lib/sighash/taproot.ts +0 -206
  142. package/src/lib/sighash/util.ts +0 -51
  143. package/src/lib/signer/index.ts +0 -2
  144. package/src/lib/signer/sign.ts +0 -39
  145. package/src/lib/signer/verify.ts +0 -88
  146. package/src/lib/taproot/cblock.ts +0 -96
  147. package/src/lib/taproot/encode.ts +0 -49
  148. package/src/lib/taproot/index.ts +0 -4
  149. package/src/lib/taproot/parse.ts +0 -65
  150. package/src/lib/taproot/tree.ts +0 -94
  151. package/src/lib/tx/create.ts +0 -90
  152. package/src/lib/tx/decode.ts +0 -123
  153. package/src/lib/tx/encode.ts +0 -155
  154. package/src/lib/tx/index.ts +0 -7
  155. package/src/lib/tx/parse.ts +0 -69
  156. package/src/lib/tx/size.ts +0 -68
  157. package/src/lib/tx/util.ts +0 -111
  158. package/src/lib/tx/validate.ts +0 -49
  159. package/src/lib/witness/index.ts +0 -2
  160. package/src/lib/witness/parse.ts +0 -127
  161. package/src/lib/witness/util.ts +0 -18
  162. package/src/schema/base.ts +0 -57
  163. package/src/schema/index.ts +0 -2
  164. package/src/schema/taproot.ts +0 -12
  165. package/src/schema/tx.ts +0 -48
  166. package/src/types/address.ts +0 -35
  167. package/src/types/index.ts +0 -8
  168. package/src/types/meta.ts +0 -48
  169. package/src/types/psbt.ts +0 -15
  170. package/src/types/script.ts +0 -18
  171. package/src/types/sighash.ts +0 -16
  172. package/src/types/taproot.ts +0 -41
  173. package/src/types/txdata.ts +0 -85
  174. package/src/types/witness.ts +0 -42
@@ -1,7 +1,7 @@
1
- import { Buff, Stream } from '@vbyte/buff';
2
- import { Assert } from '@vbyte/micro-lib';
3
- import { encode_script } from '../../lib/script/encode.js';
4
- import { decode_script } from '../../lib/script/decode.js';
1
+ import { Buff, Stream } from "@vbyte/buff";
2
+ import { Assert } from "@vbyte/micro-lib";
3
+ import { decode_script } from "../../lib/script/decode.js";
4
+ import { encode_script } from "../../lib/script/encode.js";
5
5
  const _0n = BigInt(0);
6
6
  const _1n = BigInt(1);
7
7
  const _26n = BigInt(26);
@@ -18,51 +18,51 @@ export function encode_inscription(data) {
18
18
  return Buff.join(data.map(create_envelope));
19
19
  }
20
20
  function create_envelope(data) {
21
- let asm = ['OP_0', 'OP_IF', '6f7264'];
22
- if (typeof data.delegate === 'string') {
21
+ const asm = ["OP_0", "OP_IF", "6f7264"];
22
+ if (typeof data.delegate === "string") {
23
23
  const id = encode_id(data.delegate);
24
- asm.push('OP_11', id);
24
+ asm.push("OP_11", id);
25
25
  }
26
- if (typeof data.ref === 'string') {
27
- asm.push('OP_WITHIN', data.ref);
26
+ if (typeof data.ref === "string") {
27
+ asm.push("OP_WITHIN", data.ref);
28
28
  }
29
- if (typeof data.parent === 'string') {
29
+ if (typeof data.parent === "string") {
30
30
  const id = encode_id(data.parent);
31
- asm.push('OP_3', id);
31
+ asm.push("OP_3", id);
32
32
  }
33
- if (typeof data.opcode === 'number') {
33
+ if (typeof data.opcode === "number") {
34
34
  const code = encode_pointer(data.opcode);
35
- asm.push('OP_NOP', code);
35
+ asm.push("OP_NOP", code);
36
36
  }
37
- if (typeof data.pointer === 'number') {
37
+ if (typeof data.pointer === "number") {
38
38
  const ptr = encode_pointer(data.pointer);
39
- asm.push('OP_2', ptr);
39
+ asm.push("OP_2", ptr);
40
40
  }
41
- if (typeof data.rune === 'string') {
41
+ if (typeof data.rune === "string") {
42
42
  const label = encode_rune_label(data.rune);
43
- asm.push('OP_13', label);
43
+ asm.push("OP_13", label);
44
44
  }
45
- if (typeof data.mimetype === 'string') {
45
+ if (typeof data.mimetype === "string") {
46
46
  const label = encode_label(data.mimetype);
47
- asm.push('OP_1', label);
47
+ asm.push("OP_1", label);
48
48
  }
49
- if (typeof data.content === 'string') {
49
+ if (typeof data.content === "string") {
50
50
  const chunks = encode_content(data.content);
51
- asm.push('OP_0', ...chunks);
51
+ asm.push("OP_0", ...chunks);
52
52
  }
53
- asm.push('OP_ENDIF');
53
+ asm.push("OP_ENDIF");
54
54
  return encode_script(asm);
55
55
  }
56
56
  function parse_envelopes(script) {
57
57
  const words = decode_script(script);
58
- const start_idx = words.findIndex(e => e === 'OP_0');
59
- Assert.ok(start_idx !== -1, 'inscription envelope not found');
58
+ const start_idx = words.indexOf("OP_0");
59
+ Assert.ok(start_idx !== -1, "inscription envelope not found");
60
60
  const envelopes = [];
61
61
  for (let idx = start_idx; idx < words.length; idx++) {
62
- Assert.ok(words[idx + 1] === 'OP_IF', 'OP_IF missing from envelope');
63
- Assert.ok(words[idx + 2] === '6f7264', 'magic bytes missing from envelope');
64
- const stop_idx = words.findIndex(e => e === 'OP_ENDIF');
65
- Assert.ok(stop_idx !== -1, 'inscription envelope missing END_IF statement');
62
+ Assert.ok(words[idx + 1] === "OP_IF", "OP_IF missing from envelope");
63
+ Assert.ok(words[idx + 2] === "6f7264", "magic bytes missing from envelope");
64
+ const stop_idx = words.indexOf("OP_ENDIF");
65
+ Assert.ok(stop_idx !== -1, "inscription envelope missing END_IF statement");
66
66
  const env = words.slice(idx + 3, stop_idx);
67
67
  envelopes.push(env);
68
68
  idx += stop_idx;
@@ -73,35 +73,35 @@ function parse_record(envelope) {
73
73
  const record = {};
74
74
  for (let i = 0; i < envelope.length; i++) {
75
75
  switch (envelope[i]) {
76
- case 'OP_1':
76
+ case "OP_1":
77
77
  record.mimetype = decode_label(envelope[i + 1]);
78
78
  i += 1;
79
79
  break;
80
- case 'OP_2':
80
+ case "OP_2":
81
81
  record.pointer = decode_pointer(envelope[i + 1]);
82
82
  i += 1;
83
83
  break;
84
- case 'OP_3':
84
+ case "OP_3":
85
85
  record.parent = decode_id(envelope[i + 1]);
86
86
  i += 1;
87
87
  break;
88
- case 'OP_11':
88
+ case "OP_11":
89
89
  record.delegate = decode_id(envelope[i + 1]);
90
90
  i += 1;
91
91
  break;
92
- case 'OP_13':
92
+ case "OP_13":
93
93
  record.rune = decode_rune_label(envelope[i + 1]);
94
94
  i += 1;
95
95
  break;
96
- case 'OP_WITHIN':
96
+ case "OP_WITHIN":
97
97
  record.ref = decode_bytes(envelope[i + 1]);
98
98
  i += 1;
99
99
  break;
100
- case 'OP_NOP':
100
+ case "OP_NOP":
101
101
  record.opcode = decode_pointer(envelope[i + 1]);
102
102
  i += 1;
103
103
  break;
104
- case 'OP_0':
104
+ case "OP_0":
105
105
  record.content = decode_content(envelope.slice(i + 1));
106
106
  return record;
107
107
  }
@@ -112,18 +112,18 @@ function decode_bytes(bytes) {
112
112
  return Buff.bytes(bytes).hex;
113
113
  }
114
114
  function encode_id(identifier) {
115
- Assert.ok(identifier.includes('i'), 'identifier must include an index');
116
- const parts = identifier.split('i');
115
+ Assert.ok(identifier.includes("i"), "identifier must include an index");
116
+ const parts = identifier.split("i");
117
117
  const bytes = Buff.hex(parts[0]);
118
118
  const idx = Number(parts[1]);
119
119
  const txid = bytes.reverse().hex;
120
- return (idx !== 0) ? txid + Buff.num(idx).hex : txid;
120
+ return idx !== 0 ? txid + Buff.num(idx).hex : txid;
121
121
  }
122
122
  function decode_id(identifier) {
123
123
  const bytes = Buff.bytes(identifier);
124
124
  const idx = bytes.at(-1) ?? 0;
125
125
  const txid = bytes.slice(0, -1).reverse().hex;
126
- return txid + 'i' + String(idx);
126
+ return `${txid}i${String(idx)}`;
127
127
  }
128
128
  function encode_pointer(pointer) {
129
129
  return Buff.num(pointer).reverse().hex;
@@ -138,9 +138,7 @@ function decode_label(label) {
138
138
  return Buff.bytes(label).str;
139
139
  }
140
140
  function encode_content(content) {
141
- const bytes = Buff.is_hex(content)
142
- ? Buff.hex(content)
143
- : Buff.str(content);
141
+ const bytes = Buff.is_hex(content) ? Buff.hex(content) : Buff.str(content);
144
142
  const stream = new Stream(bytes);
145
143
  const chunks = [];
146
144
  while (stream.size > 0) {
@@ -155,21 +153,18 @@ function encode_content(content) {
155
153
  }
156
154
  return chunks;
157
155
  }
158
- function decode_content(chunks, format = 'hex') {
156
+ function decode_content(chunks, format = "hex") {
159
157
  const data = Buff.join(chunks);
160
- return (format === 'hex')
161
- ? data.hex
162
- : data.str;
158
+ return format === "hex" ? data.hex : data.str;
163
159
  }
164
160
  function encode_rune_label(label) {
165
161
  const str = label.toUpperCase();
166
162
  let big = _0n;
167
163
  for (const char of str) {
168
- if (char >= 'A' && char <= 'Z') {
169
- big = big * _26n + BigInt(char.charCodeAt(0) - ('A'.charCodeAt(0) - 1));
164
+ if (char >= "A" && char <= "Z") {
165
+ big = big * _26n + BigInt(char.charCodeAt(0) - ("A".charCodeAt(0) - 1));
170
166
  }
171
167
  else {
172
- continue;
173
168
  }
174
169
  }
175
170
  big = big - _1n;
@@ -178,15 +173,15 @@ function encode_rune_label(label) {
178
173
  function decode_rune_label(label) {
179
174
  let big = Buff.bytes(label).reverse().big;
180
175
  big = big + _1n;
181
- let result = '';
176
+ let result = "";
182
177
  while (big > _0n) {
183
178
  const mod = big % _26n;
184
179
  if (mod === _0n) {
185
- result = 'Z' + result;
180
+ result = `Z${result}`;
186
181
  big = big / _26n - _1n;
187
182
  }
188
183
  else {
189
- const charCode = Number(mod) + 'A'.charCodeAt(0) - 1;
184
+ const charCode = Number(mod) + "A".charCodeAt(0) - 1;
190
185
  result = String.fromCharCode(charCode) + result;
191
186
  big = big / _26n;
192
187
  }
@@ -1,4 +1,4 @@
1
- import type { SequenceConfig, SequenceData } from '../../types/index.js';
1
+ import type { SequenceConfig, SequenceData } from "../../types/index.js";
2
2
  export declare namespace SequenceField {
3
3
  const encode: typeof encode_sequence;
4
4
  const decode: typeof decode_sequence;
@@ -1,7 +1,7 @@
1
1
  const TIMELOCK_DISABLE = 0x80000000;
2
2
  const TIMELOCK_TYPE = 0x00400000;
3
- const TIMELOCK_VALUE_MASK = 0x0000FFFF;
4
- const TIMELOCK_VALUE_MAX = 0xFFFF;
3
+ const TIMELOCK_VALUE_MASK = 0x0000ffff;
4
+ const TIMELOCK_VALUE_MAX = 0xffff;
5
5
  const TIMELOCK_GRANULARITY = 512;
6
6
  export var SequenceField;
7
7
  (function (SequenceField) {
@@ -9,15 +9,15 @@ export var SequenceField;
9
9
  SequenceField.decode = decode_sequence;
10
10
  })(SequenceField || (SequenceField = {}));
11
11
  export function encode_sequence(data) {
12
- if (data.mode === 'height') {
12
+ if (data.mode === "height") {
13
13
  const height = parse_height(data.height);
14
14
  return (height & TIMELOCK_VALUE_MASK) >>> 0;
15
15
  }
16
- if (data.mode === 'stamp') {
16
+ if (data.mode === "stamp") {
17
17
  const stamp = parse_stamp(data.stamp);
18
18
  return (TIMELOCK_TYPE | (stamp & TIMELOCK_VALUE_MASK)) >>> 0;
19
19
  }
20
- throw new Error('invalid timelock mode: ' + data.mode);
20
+ throw new Error(`invalid timelock mode: ${data.mode}`);
21
21
  }
22
22
  export function decode_sequence(sequence) {
23
23
  const seq = parse_sequence(sequence);
@@ -26,23 +26,21 @@ export function decode_sequence(sequence) {
26
26
  const value = seq & TIMELOCK_VALUE_MASK;
27
27
  if (seq & TIMELOCK_TYPE) {
28
28
  const stamp = value * TIMELOCK_GRANULARITY;
29
- if (stamp > 0xFFFFFFFF) {
30
- throw new Error('Decoded timestamp exceeds 32-bit limit');
29
+ if (stamp > 0xffffffff) {
30
+ throw new Error("Decoded timestamp exceeds 32-bit limit");
31
31
  }
32
- return { mode: 'stamp', stamp };
32
+ return { mode: "stamp", stamp };
33
33
  }
34
34
  else {
35
35
  if (value > TIMELOCK_VALUE_MAX) {
36
- throw new Error('Decoded height exceeds maximum');
36
+ throw new Error("Decoded height exceeds maximum");
37
37
  }
38
- return { mode: 'height', height: value };
38
+ return { mode: "height", height: value };
39
39
  }
40
40
  }
41
41
  function parse_sequence(sequence) {
42
- const seq = (typeof sequence === 'string')
43
- ? parseInt(sequence, 16)
44
- : sequence;
45
- if (!Number.isInteger(seq) || seq < 0 || seq > 0xFFFFFFFF) {
42
+ const seq = typeof sequence === "string" ? parseInt(sequence, 16) : sequence;
43
+ if (!Number.isInteger(seq) || seq < 0 || seq > 0xffffffff) {
46
44
  throw new Error(`invalid sequence value: ${seq}`);
47
45
  }
48
46
  return seq;
@@ -58,7 +56,10 @@ function parse_stamp(stamp) {
58
56
  return ts;
59
57
  }
60
58
  function parse_height(height) {
61
- if (height === undefined || !Number.isInteger(height) || height < 0 || height > TIMELOCK_VALUE_MAX) {
59
+ if (height === undefined ||
60
+ !Number.isInteger(height) ||
61
+ height < 0 ||
62
+ height > TIMELOCK_VALUE_MAX) {
62
63
  throw new Error(`Heightlock value must be an integer between 0 and ${TIMELOCK_VALUE_MAX}`);
63
64
  }
64
65
  return height;
@@ -1,5 +1,5 @@
1
- import { Bytes } from '@vbyte/buff';
2
- import type { ScriptInfo } from '../../types/script.js';
1
+ import { type Bytes } from "@vbyte/buff";
2
+ import type { ScriptInfo } from "../../types/script.js";
3
3
  export declare function parse_script(script: Bytes): ScriptInfo;
4
4
  export declare function decode_script(script: Bytes): string[];
5
5
  export declare function is_valid_script(script: string | Uint8Array): boolean;
@@ -1,10 +1,10 @@
1
- import { Buff, Stream } from '@vbyte/buff';
2
- import { get_op_code, get_op_type, is_valid_op } from './words.js';
1
+ import { Buff, Stream } from "@vbyte/buff";
2
+ import { get_op_code, get_op_type, is_valid_op } from "./words.js";
3
3
  export function parse_script(script) {
4
4
  const bytes = Buff.bytes(script);
5
5
  return {
6
6
  asm: decode_script(bytes),
7
- hex: bytes.hex
7
+ hex: bytes.hex,
8
8
  };
9
9
  }
10
10
  export function decode_script(script) {
@@ -20,26 +20,61 @@ export function decode_script(script) {
20
20
  word_type = get_op_type(word);
21
21
  count++;
22
22
  switch (word_type) {
23
- case 'varint':
24
- stack.push(stream.read(word).hex);
23
+ case "varint":
24
+ try {
25
+ stack.push(stream.read(word).hex);
26
+ }
27
+ catch {
28
+ throw new Error(`Malformed script: varint push at position ${count - 1} requires ${word} bytes but stream exhausted`);
29
+ }
25
30
  count += word;
26
31
  break;
27
- case 'pushdata1':
28
- word_size = stream.read(1).reverse().num;
29
- stack.push(stream.read(word_size).hex);
32
+ case "pushdata1":
33
+ try {
34
+ word_size = stream.read(1).reverse().num;
35
+ }
36
+ catch {
37
+ throw new Error(`Malformed script: PUSHDATA1 at position ${count - 1} missing size byte`);
38
+ }
39
+ try {
40
+ stack.push(stream.read(word_size).hex);
41
+ }
42
+ catch {
43
+ throw new Error(`Malformed script: PUSHDATA1 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
44
+ }
30
45
  count += word_size + 1;
31
46
  break;
32
- case 'pushdata2':
33
- word_size = stream.read(2).reverse().num;
34
- stack.push(stream.read(word_size).hex);
47
+ case "pushdata2":
48
+ try {
49
+ word_size = stream.read(2).reverse().num;
50
+ }
51
+ catch {
52
+ throw new Error(`Malformed script: PUSHDATA2 at position ${count - 1} missing size bytes`);
53
+ }
54
+ try {
55
+ stack.push(stream.read(word_size).hex);
56
+ }
57
+ catch {
58
+ throw new Error(`Malformed script: PUSHDATA2 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
59
+ }
35
60
  count += word_size + 2;
36
61
  break;
37
- case 'pushdata4':
38
- word_size = stream.read(4).reverse().num;
39
- stack.push(stream.read(word_size).hex);
62
+ case "pushdata4":
63
+ try {
64
+ word_size = stream.read(4).reverse().num;
65
+ }
66
+ catch {
67
+ throw new Error(`Malformed script: PUSHDATA4 at position ${count - 1} missing size bytes`);
68
+ }
69
+ try {
70
+ stack.push(stream.read(word_size).hex);
71
+ }
72
+ catch {
73
+ throw new Error(`Malformed script: PUSHDATA4 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
74
+ }
40
75
  count += word_size + 4;
41
76
  break;
42
- case 'opcode':
77
+ case "opcode":
43
78
  if (!is_valid_op(word)) {
44
79
  throw new Error(`Invalid OPCODE: ${word}`);
45
80
  }
@@ -1,4 +1,4 @@
1
- import { Buff } from '@vbyte/buff';
1
+ import { Buff } from "@vbyte/buff";
2
2
  export declare function encode_script(words: (string | number | Uint8Array)[], varint?: boolean): Buff;
3
3
  export declare function encode_script_word(word: string | number | Uint8Array): Uint8Array;
4
4
  export declare function split_script_word(word: Uint8Array): Buff[];
@@ -1,5 +1,6 @@
1
- import { Buff, Stream } from '@vbyte/buff';
2
- import { get_asm_code, } from './words.js';
1
+ import { Buff, Stream } from "@vbyte/buff";
2
+ import { MAX_SCRIPT_SIZE, OP_1_OFFSET } from "../../const.js";
3
+ import { get_asm_code } from "./words.js";
3
4
  const MAX_WORD_SIZE = 520;
4
5
  export function encode_script(words, varint = false) {
5
6
  if (words.length === 0)
@@ -9,14 +10,17 @@ export function encode_script(words, varint = false) {
9
10
  bytes.push(encode_script_word(word));
10
11
  }
11
12
  const buffer = Buff.join(bytes);
12
- return (varint)
13
- ? buffer.prepend(Buff.varint(buffer.length, 'le'))
13
+ if (buffer.length > MAX_SCRIPT_SIZE) {
14
+ throw new Error(`script size ${buffer.length} exceeds consensus limit of ${MAX_SCRIPT_SIZE} bytes`);
15
+ }
16
+ return varint
17
+ ? buffer.prepend(Buff.create_varint(buffer.length, "le"))
14
18
  : buffer;
15
19
  }
16
20
  export function encode_script_word(word) {
17
21
  let buff;
18
- if (typeof (word) === 'string') {
19
- if (word.startsWith('OP_')) {
22
+ if (typeof word === "string") {
23
+ if (word.startsWith("OP_")) {
20
24
  const asm_code = get_asm_code(word);
21
25
  return Buff.num(asm_code, 1);
22
26
  }
@@ -27,23 +31,23 @@ export function encode_script_word(word) {
27
31
  buff = Buff.str(word);
28
32
  }
29
33
  }
30
- else if (typeof (word) === 'number') {
34
+ else if (typeof word === "number") {
31
35
  buff = Buff.num(word);
32
36
  }
33
37
  else if (word instanceof Uint8Array) {
34
38
  buff = new Buff(word);
35
39
  }
36
40
  else {
37
- throw new Error('invalid word type:' + typeof (word));
41
+ throw new Error(`invalid word type:${typeof word}`);
38
42
  }
39
43
  if (buff.length === 1 && buff[0] <= 16) {
40
44
  if (buff[0] !== 0)
41
- buff[0] += 0x50;
45
+ buff[0] += OP_1_OFFSET;
42
46
  }
43
47
  else if (buff.length > MAX_WORD_SIZE) {
44
48
  let words;
45
49
  words = split_script_word(buff);
46
- words = words.map(e => prefix_word_size(e));
50
+ words = words.map((e) => prefix_word_size(e));
47
51
  buff = Buff.join(words);
48
52
  }
49
53
  else {
@@ -68,13 +72,13 @@ export function get_size_varint(size) {
68
72
  const OP_PUSHDATA1 = Buff.num(0x4c, 1);
69
73
  const OP_PUSHDATA2 = Buff.num(0x4d, 1);
70
74
  switch (true) {
71
- case (size <= 0x4b):
75
+ case size <= 0x4b:
72
76
  return Buff.num(size);
73
- case (size > 0x4b && size < 0x100):
74
- return Buff.join([OP_PUSHDATA1, Buff.num(size, 1, 'le')]);
75
- case (size >= 0x100 && size <= MAX_WORD_SIZE):
76
- return Buff.join([OP_PUSHDATA2, Buff.num(size, 2, 'le')]);
77
+ case size > 0x4b && size < 0x100:
78
+ return Buff.join([OP_PUSHDATA1, Buff.num(size, 1, "le")]);
79
+ case size >= 0x100 && size <= MAX_WORD_SIZE:
80
+ return Buff.join([OP_PUSHDATA2, Buff.num(size, 2, "le")]);
77
81
  default:
78
- throw new Error('Invalid word size:' + size.toString());
82
+ throw new Error(`Invalid word size:${size.toString()}`);
79
83
  }
80
84
  }
@@ -1,13 +1,5 @@
1
- import { encode_script } from './encode.js';
2
- import { decode_script, is_valid_script, parse_script } from './decode.js';
3
- export * from './decode.js';
4
- export * from './encode.js';
5
- export * from './lock.js';
6
- export * from './util.js';
7
- export * from './words.js';
8
- export declare namespace ScriptUtil {
9
- const parse: typeof parse_script;
10
- const decode: typeof decode_script;
11
- const encode: typeof encode_script;
12
- const is_valid: typeof is_valid_script;
13
- }
1
+ export * from "./decode.js";
2
+ export * from "./encode.js";
3
+ export * from "./lock.js";
4
+ export * from "./util.js";
5
+ export * from "./words.js";
@@ -1,14 +1,5 @@
1
- import { encode_script } from './encode.js';
2
- import { decode_script, is_valid_script, parse_script } from './decode.js';
3
- export * from './decode.js';
4
- export * from './encode.js';
5
- export * from './lock.js';
6
- export * from './util.js';
7
- export * from './words.js';
8
- export var ScriptUtil;
9
- (function (ScriptUtil) {
10
- ScriptUtil.parse = parse_script;
11
- ScriptUtil.decode = decode_script;
12
- ScriptUtil.encode = encode_script;
13
- ScriptUtil.is_valid = is_valid_script;
14
- })(ScriptUtil || (ScriptUtil = {}));
1
+ export * from "./decode.js";
2
+ export * from "./encode.js";
3
+ export * from "./lock.js";
4
+ export * from "./util.js";
5
+ export * from "./words.js";
@@ -1,5 +1,5 @@
1
- import { Bytes } from '@vbyte/buff';
2
- import type { LockScriptInfo, LockScriptType, WitnessVersion } from '../../types/index.js';
1
+ import { type Bytes } from "@vbyte/buff";
2
+ import type { LockScriptInfo, LockScriptType, WitnessVersion } from "../../types/index.js";
3
3
  export declare function is_return_script(script: Bytes): boolean;
4
4
  export declare function get_lock_script_info(script: Bytes): LockScriptInfo;
5
5
  export declare function get_lock_script_type(script: Bytes): LockScriptType | null;
@@ -1,5 +1,5 @@
1
- import { Buff } from '@vbyte/buff';
2
- import { LOCK_SCRIPT_REGEX } from '../../const.js';
1
+ import { Buff } from "@vbyte/buff";
2
+ import { LOCK_SCRIPT_REGEX } from "../../const.js";
3
3
  export function is_return_script(script) {
4
4
  const bytes = Buff.bytes(script);
5
5
  return bytes.at(0) === 0x6a;
@@ -7,7 +7,7 @@ export function is_return_script(script) {
7
7
  export function get_lock_script_info(script) {
8
8
  return {
9
9
  type: get_lock_script_type(script),
10
- version: get_lock_script_version(script)
10
+ version: get_lock_script_version(script),
11
11
  };
12
12
  }
13
13
  export function get_lock_script_type(script) {
@@ -21,32 +21,35 @@ export function get_lock_script_type(script) {
21
21
  export function get_lock_script_version(script) {
22
22
  const version = Buff.bytes(script);
23
23
  switch (version.at(0)) {
24
- case 0x00: return 0;
25
- case 0x51: return 1;
26
- default: return null;
24
+ case 0x00:
25
+ return 0;
26
+ case 0x51:
27
+ return 1;
28
+ default:
29
+ return null;
27
30
  }
28
31
  }
29
32
  export function is_p2pkh_script(script) {
30
33
  const hex = Buff.bytes(script).hex;
31
- return LOCK_SCRIPT_REGEX['p2pkh'].test(hex);
34
+ return LOCK_SCRIPT_REGEX.p2pkh.test(hex);
32
35
  }
33
36
  export function is_p2sh_script(script) {
34
37
  const hex = Buff.bytes(script).hex;
35
- return LOCK_SCRIPT_REGEX['p2sh'].test(hex);
38
+ return LOCK_SCRIPT_REGEX.p2sh.test(hex);
36
39
  }
37
40
  export function is_p2wpkh_script(script) {
38
41
  const hex = Buff.bytes(script).hex;
39
- return LOCK_SCRIPT_REGEX['p2wpkh'].test(hex);
42
+ return LOCK_SCRIPT_REGEX.p2wpkh.test(hex);
40
43
  }
41
44
  export function is_p2wsh_script(script) {
42
45
  const hex = Buff.bytes(script).hex;
43
- return LOCK_SCRIPT_REGEX['p2wsh'].test(hex);
46
+ return LOCK_SCRIPT_REGEX.p2wsh.test(hex);
44
47
  }
45
48
  export function is_p2tr_script(script) {
46
49
  const hex = Buff.bytes(script).hex;
47
- return LOCK_SCRIPT_REGEX['p2tr'].test(hex);
50
+ return LOCK_SCRIPT_REGEX.p2tr.test(hex);
48
51
  }
49
52
  export function is_opreturn_script(script) {
50
53
  const hex = Buff.bytes(script).hex;
51
- return LOCK_SCRIPT_REGEX['opreturn'].test(hex);
54
+ return LOCK_SCRIPT_REGEX.opreturn.test(hex);
52
55
  }
@@ -1,10 +1,10 @@
1
- import { Buff } from '@vbyte/buff';
1
+ import { Buff } from "@vbyte/buff";
2
2
  export function prefix_script_size(script) {
3
- return Buff.bytes(script).prefix_varint('le').hex;
3
+ return Buff.bytes(script).prefix_varint("le").hex;
4
4
  }
5
5
  export function parse_script_pubkeys(script) {
6
- const scriptHex = typeof script === 'string' ? script : Buff.bytes(script).hex;
6
+ const scriptHex = typeof script === "string" ? script : Buff.bytes(script).hex;
7
7
  const pubkeyPattern = /20([0-9a-f]{64})(ac|ad|ba)/gi;
8
8
  const matches = [...scriptHex.matchAll(pubkeyPattern)];
9
- return matches.map(match => match[1]);
9
+ return matches.map((match) => match[1]);
10
10
  }