@vbyte/btc-dev 1.0.11 → 1.0.13

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 (67) hide show
  1. package/dist/index.d.ts +0 -1
  2. package/dist/index.js +0 -1
  3. package/dist/lib/sighash/segwit.d.ts +4 -1
  4. package/dist/lib/sighash/segwit.js +6 -6
  5. package/dist/lib/sighash/taproot.d.ts +7 -6
  6. package/dist/lib/sighash/taproot.js +24 -53
  7. package/dist/lib/sighash/util.d.ts +4 -2
  8. package/dist/lib/sighash/util.js +16 -2
  9. package/dist/lib/signer/sign.js +8 -5
  10. package/dist/lib/signer/verify.d.ts +1 -2
  11. package/dist/lib/signer/verify.js +1 -5
  12. package/dist/lib/tx/create.d.ts +7 -6
  13. package/dist/lib/tx/create.js +25 -27
  14. package/dist/lib/tx/decode.d.ts +4 -9
  15. package/dist/lib/tx/decode.js +16 -28
  16. package/dist/lib/tx/encode.d.ts +1 -1
  17. package/dist/lib/tx/encode.js +6 -6
  18. package/dist/lib/tx/parse.d.ts +3 -2
  19. package/dist/lib/tx/parse.js +38 -5
  20. package/dist/lib/tx/util.d.ts +8 -4
  21. package/dist/lib/tx/util.js +39 -15
  22. package/dist/lib/tx/validate.d.ts +4 -2
  23. package/dist/lib/tx/validate.js +9 -2
  24. package/dist/main.cjs +4049 -4230
  25. package/dist/main.cjs.map +1 -1
  26. package/dist/module.mjs +4040 -4216
  27. package/dist/module.mjs.map +1 -1
  28. package/dist/package.json +2 -2
  29. package/dist/schema/taproot.d.ts +2 -2
  30. package/dist/schema/tx.d.ts +53 -40
  31. package/dist/schema/tx.js +9 -6
  32. package/dist/script.js +8 -8
  33. package/dist/script.js.map +1 -1
  34. package/dist/types/txdata.d.ts +17 -1
  35. package/package.json +2 -2
  36. package/src/index.ts +0 -2
  37. package/src/lib/sighash/segwit.ts +6 -6
  38. package/src/lib/sighash/taproot.ts +40 -70
  39. package/src/lib/sighash/util.ts +25 -3
  40. package/src/lib/signer/sign.ts +9 -5
  41. package/src/lib/signer/verify.ts +1 -18
  42. package/src/lib/tx/create.ts +46 -38
  43. package/src/lib/tx/decode.ts +23 -45
  44. package/src/lib/tx/encode.ts +10 -9
  45. package/src/lib/tx/parse.ts +61 -8
  46. package/src/lib/tx/util.ts +57 -20
  47. package/src/lib/tx/validate.ts +15 -2
  48. package/src/schema/tx.ts +10 -6
  49. package/src/types/txdata.ts +20 -1
  50. package/dist/class/index.d.ts +0 -5
  51. package/dist/class/index.js +0 -5
  52. package/dist/class/signer.d.ts +0 -18
  53. package/dist/class/signer.js +0 -34
  54. package/dist/class/tx.d.ts +0 -40
  55. package/dist/class/tx.js +0 -96
  56. package/dist/class/txin.d.ts +0 -29
  57. package/dist/class/txin.js +0 -62
  58. package/dist/class/txout.d.ts +0 -19
  59. package/dist/class/txout.js +0 -37
  60. package/dist/class/witness.d.ts +0 -18
  61. package/dist/class/witness.js +0 -46
  62. package/src/class/index.ts +0 -5
  63. package/src/class/signer.ts +0 -49
  64. package/src/class/tx.ts +0 -136
  65. package/src/class/txin.ts +0 -89
  66. package/src/class/txout.ts +0 -61
  67. package/src/class/witness.ts +0 -75
@@ -27,6 +27,10 @@ export interface TxVirtualInput extends TxOutpoint {
27
27
  export interface TxSpendInput extends TxVirtualInput {
28
28
  prevout: TxOutput;
29
29
  }
30
+ export interface TxOutputTemplate {
31
+ script_pk: string;
32
+ value: number | bigint;
33
+ }
30
34
  export interface TxOutput {
31
35
  script_pk: string;
32
36
  value: bigint;
@@ -34,7 +38,7 @@ export interface TxOutput {
34
38
  export interface TxTemplate {
35
39
  locktime?: number;
36
40
  vin?: TxInputTemplate[];
37
- vout?: TxOutput[];
41
+ vout?: TxOutputTemplate[];
38
42
  version?: number;
39
43
  }
40
44
  export interface TxData {
@@ -43,6 +47,18 @@ export interface TxData {
43
47
  vout: TxOutput[];
44
48
  version: number;
45
49
  }
50
+ export interface TxDecodedData {
51
+ locktime: number;
52
+ vin: (TxCoinbaseInput | TxVirtualInput)[];
53
+ vout: TxOutput[];
54
+ version: number;
55
+ }
56
+ export interface TxSpendData {
57
+ locktime: number;
58
+ vin: TxSpendInput[];
59
+ vout: TxOutput[];
60
+ version: number;
61
+ }
46
62
  export interface TxSize {
47
63
  base: number;
48
64
  total: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vbyte/btc-dev",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Batteries-included toolset for plebian bitcoin development",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -87,7 +87,7 @@
87
87
  "@noble/hashes": "^1.8.0",
88
88
  "@scure/btc-signer": "^1.8.1",
89
89
  "@vbyte/buff": "^1.0.2",
90
- "@vbyte/micro-lib": "^1.0.11",
90
+ "@vbyte/micro-lib": "^1.0.14",
91
91
  "zod": "^3.25.69"
92
92
  },
93
93
  "devDependencies": {
package/src/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- export * from './class/index.js'
2
-
3
1
  export * as ADDRESS from './lib/address/index.js'
4
2
  export * as META from './lib/meta/index.js'
5
3
  export * as PSBT from './lib/psbt/index.js'
@@ -73,14 +73,14 @@ export function hash_segwit_tx (
73
73
 
74
74
  const sighash = [
75
75
  encode_tx_version(version),
76
- hash_prevouts(vin, is_anypay),
77
- hash_sequence(vin, flag, is_anypay),
76
+ bip143_hash_prevouts(vin, is_anypay),
77
+ bip143_hash_sequence(vin, flag, is_anypay),
78
78
  encode_txin_txid(txid),
79
79
  encode_txin_vout(prevIdx),
80
80
  prefix_script_size(script),
81
81
  encode_vout_value(value),
82
82
  encode_txin_sequence(sequence),
83
- hash_outputs(vout, flag, txindex),
83
+ bip143_hash_outputs(vout, flag, txindex),
84
84
  encode_tx_locktime(locktime),
85
85
  Buff.num(sigflag, 4).reverse()
86
86
  ]
@@ -88,7 +88,7 @@ export function hash_segwit_tx (
88
88
  return hash256(Buff.join(sighash))
89
89
  }
90
90
 
91
- function hash_prevouts (
91
+ export function bip143_hash_prevouts (
92
92
  vin : TxInput[],
93
93
  isAnypay ?: boolean
94
94
  ) : Uint8Array {
@@ -106,7 +106,7 @@ function hash_prevouts (
106
106
  return hash256(Buff.join(stack))
107
107
  }
108
108
 
109
- function hash_sequence (
109
+ export function bip143_hash_sequence (
110
110
  vin : TxInput[],
111
111
  sigflag : number,
112
112
  isAnyPay : boolean
@@ -123,7 +123,7 @@ function hash_sequence (
123
123
  return hash256(Buff.join(stack))
124
124
  }
125
125
 
126
- function hash_outputs (
126
+ export function bip143_hash_outputs (
127
127
  vout : TxOutput[],
128
128
  sigflag : number,
129
129
  idx ?: number
@@ -1,11 +1,15 @@
1
1
  import { Buff } from '@vbyte/buff'
2
2
  import { Assert } from '@vbyte/micro-lib'
3
3
  import { hash340, sha256 } from '@vbyte/micro-lib/hash'
4
- import { prefix_script_size } from '@/lib/script/util.js'
5
4
  import { encode_tapscript } from '@/lib/taproot/encode.js'
6
5
  import { parse_tx } from '@/lib/tx/parse.js'
7
6
  import * as CONST from '@/const.js'
8
- import { parse_txinput } from './util.js'
7
+
8
+ import {
9
+ parse_txinput,
10
+ get_annex_data,
11
+ get_prevout
12
+ } from './util.js'
9
13
 
10
14
  import {
11
15
  encode_txin_vout,
@@ -13,7 +17,8 @@ import {
13
17
  encode_txin_sequence,
14
18
  encode_txin_txid,
15
19
  encode_vout_value,
16
- encode_tx_version
20
+ encode_tx_version,
21
+ encode_script_data
17
22
  } from '@/lib/tx/encode.js'
18
23
 
19
24
  import type {
@@ -26,6 +31,14 @@ import type {
26
31
  export function hash_taproot_tx (
27
32
  template : TxData | string,
28
33
  config : SigHashOptions = {}
34
+ ) : Buff {
35
+ const preimage = get_taproot_tx_preimage(template, config)
36
+ return hash340('TapSighash', preimage)
37
+ }
38
+
39
+ export function get_taproot_tx_preimage (
40
+ template : TxData | string,
41
+ config : SigHashOptions = {}
29
42
  ) : Buff {
30
43
  // Unpack configuration.
31
44
  const {
@@ -36,6 +49,7 @@ export function hash_taproot_tx (
36
49
  key_version = 0x00,
37
50
  separator_pos = 0xFFFFFFFF
38
51
  } = config
52
+
39
53
  // Normalize the txdata object.
40
54
  const tx = parse_tx(template)
41
55
  // Unpack the txdata object.
@@ -66,11 +80,9 @@ export function hash_taproot_tx (
66
80
  const annexBit = (annex !== undefined) ? 1 : 0
67
81
  const extendBit = (extension !== undefined) ? 1 : 0
68
82
  const spendType = ((extflag + extendBit) * 2) + annexBit
69
- const hashtag = hash340('TapSighash')
70
83
 
71
84
  // Begin building our preimage.
72
85
  const preimage : (string | Uint8Array)[] = [
73
- hashtag, // Buffer input with TapSighash.
74
86
  Buff.num(0x00, 1), // Add zero-byte.
75
87
  Buff.num(sigflag, 1), // Commit to signature flag.
76
88
  encode_tx_version(version), // Commit to tx version.
@@ -82,17 +94,17 @@ export function hash_taproot_tx (
82
94
  // then commit to all inputs.
83
95
  const prevouts = input.map(e => get_prevout(e))
84
96
  preimage.push(
85
- hash_outpoints(input), // Commit to txid/vout for each input.
86
- hash_amounts(prevouts), // Commit to prevout amount for each input.
87
- hash_scripts(prevouts), // Commit to prevout script for each input.
88
- hash_sequence(input) // Commit to sequence value for each input.
97
+ bip341_hash_outpoints(input), // Commit to txid/vout for each input.
98
+ bip341_hash_amounts(prevouts), // Commit to prevout amount for each input.
99
+ bip341_hash_scripts(prevouts), // Commit to prevout script for each input.
100
+ bip341_hash_sequence(input) // Commit to sequence value for each input.
89
101
  )
90
102
  }
91
103
 
92
104
  if ((sigflag & 0x03) < 2 || (sigflag & 0x03) > 3) {
93
105
  // If neither SINGLE or NONE flags are set,
94
106
  // include a commitment to all outputs.
95
- preimage.push(hash_outputs(output))
107
+ preimage.push(bip341_hash_outputs(output))
96
108
  }
97
109
 
98
110
  // At this step, we include the spend type.
@@ -106,7 +118,7 @@ export function hash_taproot_tx (
106
118
  encode_txin_txid(txid), // Commit to the input txid.
107
119
  encode_txin_vout(vout), // Commit to the input vout index.
108
120
  encode_vout_value(value), // Commit to the input's prevout value.
109
- prefix_script_size(script_pk), // Commit to the input's prevout script.
121
+ encode_script_data(script_pk), // Commit to the input's prevout script.
110
122
  encode_txin_sequence(sequence) // Commit to the input's sequence value.
111
123
  )
112
124
  } else {
@@ -127,7 +139,7 @@ export function hash_taproot_tx (
127
139
  // commitment to the output which is adjacent
128
140
  // to the input that we are signing for.
129
141
  Assert.ok(typeof txindex === 'number')
130
- preimage.push(hash_output(output[txindex]))
142
+ preimage.push(bip341_hash_output(output[txindex]))
131
143
  }
132
144
 
133
145
  if (extension !== undefined) {
@@ -135,19 +147,16 @@ export function hash_taproot_tx (
135
147
  // other commitments (such as a tapleaf), then we
136
148
  // will add it to the preimage here.
137
149
  preimage.push(
138
- Buff.bytes(extension), // Extention data (in bytes).
139
- Buff.num(key_version), // Key version (reserved for future upgrades).
140
- Buff.num(separator_pos, 4) // If OP_CODESEPARATOR is used, this must be set.
150
+ Buff.bytes(extension), // Extention data (in bytes).
151
+ Buff.num(key_version), // Key version (reserved for future upgrades).
152
+ Buff.num(separator_pos, 4,'le') // If OP_CODESEPARATOR is used, this must be set.
141
153
  )
142
154
  }
143
155
 
144
- // Useful for debugging the preimage stack.
145
- // console.log(preimage.map(e => Buff.raw(e).hex))
146
-
147
- return sha256(Buff.join(preimage))
156
+ return Buff.join(preimage)
148
157
  }
149
158
 
150
- export function hash_outpoints (
159
+ export function bip341_hash_outpoints (
151
160
  vin : TxInput[]
152
161
  ) : Buff {
153
162
  const stack = []
@@ -158,79 +167,40 @@ export function hash_outpoints (
158
167
  return sha256(Buff.join(stack))
159
168
  }
160
169
 
161
- export function hash_sequence (
170
+ export function bip341_hash_sequence (
162
171
  vin : TxInput[]
163
172
  ) : Buff {
164
- const stack = []
165
- for (const { sequence } of vin) {
166
- stack.push(encode_txin_sequence(sequence))
167
- }
168
- return sha256(Buff.join(stack))
173
+ return sha256(...vin.map(vin => encode_txin_sequence(vin.sequence)))
169
174
  }
170
175
 
171
- export function hash_amounts (
176
+ export function bip341_hash_amounts (
172
177
  prevouts : TxOutput[]
173
178
  ) : Buff {
174
- const stack = []
175
- for (const { value } of prevouts) {
176
- stack.push(encode_vout_value(value))
177
- }
178
- return sha256(Buff.join(stack))
179
+ return sha256(...prevouts.map(prevout => encode_vout_value(prevout.value)))
179
180
  }
180
181
 
181
- export function hash_scripts (
182
+ export function bip341_hash_scripts (
182
183
  prevouts : TxOutput[]
183
184
  ) : Buff {
184
- const stack = []
185
- for (const { script_pk } of prevouts) {
186
- stack.push(prefix_script_size(script_pk))
187
- }
188
- return sha256(Buff.join(stack))
185
+ return sha256(...prevouts.map(prevout => encode_script_data(prevout.script_pk)))
189
186
  }
190
187
 
191
- export function hash_outputs (
188
+ export function bip341_hash_outputs (
192
189
  vout : TxOutput[]
193
190
  ) : Buff {
194
191
  const stack = []
195
192
  for (const { value, script_pk } of vout) {
196
193
  stack.push(encode_vout_value(value))
197
- stack.push(prefix_script_size(script_pk))
194
+ stack.push(encode_script_data(script_pk))
198
195
  }
199
- return sha256(Buff.join(stack))
196
+ return sha256(...stack)
200
197
  }
201
198
 
202
- export function hash_output (
199
+ export function bip341_hash_output (
203
200
  vout : TxOutput
204
201
  ) : Buff {
205
202
  return sha256(
206
203
  encode_vout_value(vout.value),
207
- prefix_script_size(vout.script_pk)
204
+ encode_script_data(vout.script_pk)
208
205
  )
209
206
  }
210
-
211
- function get_annex_data (
212
- witness ?: string[]
213
- ) : Buff | undefined {
214
- // If no witness exists, return undefined.
215
- if (witness === undefined) return
216
- // If there are less than two elements, return undefined.
217
- if (witness.length < 2) return
218
- // Define the last element as the annex.
219
- const annex = witness.at(-1)
220
- // If the annex is a string and starts with '50',
221
- if (typeof annex === 'string' && annex.startsWith('50')) {
222
- // Convert the annex to a buffer with a varint prefix.
223
- const bytes = Buff.hex(annex).prefix_varint('be')
224
- // Return the sha256 of the annex.
225
- return sha256(bytes)
226
- }
227
- // Else, return undefined.
228
- return undefined
229
- }
230
-
231
- function get_prevout (vin : TxInput) : TxOutput {
232
- if (vin.prevout === null) {
233
- throw new Error('Prevout data missing for input: ' + String(vin.txid))
234
- }
235
- return vin.prevout
236
- }
@@ -1,12 +1,19 @@
1
1
  import { Buff } from '@vbyte/buff'
2
2
  import { Assert } from '@vbyte/micro-lib'
3
+ import { sha256 } from '@vbyte/micro-lib/hash'
3
4
 
4
5
  import type {
5
6
  SigHashOptions,
6
7
  TxInput,
7
8
  TxData,
9
+ TxOutput,
8
10
  } from '@/types/index.js'
9
11
 
12
+ export function get_prevout (vin : TxInput) : TxOutput {
13
+ Assert.exists(vin.prevout, 'Prevout data missing for input: ' + String(vin.txid))
14
+ return vin.prevout
15
+ }
16
+
10
17
  export function parse_txinput (
11
18
  txdata : TxData,
12
19
  config ?: SigHashOptions
@@ -23,7 +30,22 @@ export function parse_txinput (
23
30
  return txinput
24
31
  }
25
32
 
26
- export function format_sigflag (flag : number) {
27
- return (flag !== 0) ? Buff.num(flag, 1).hex : ''
33
+ export function get_annex_data (
34
+ witness ?: string[]
35
+ ) : Buff | undefined {
36
+ // If no witness exists, return undefined.
37
+ if (witness === undefined) return
38
+ // If there are less than two elements, return undefined.
39
+ if (witness.length < 2) return
40
+ // Define the last element as the annex.
41
+ const annex = witness.at(-1)
42
+ // If the annex is a string and starts with '50',
43
+ if (typeof annex === 'string' && annex.startsWith('50')) {
44
+ // Convert the annex to a buffer with a varint prefix.
45
+ const bytes = Buff.hex(annex).prefix_varint('be')
46
+ // Return the sha256 of the annex.
47
+ return sha256(bytes)
48
+ }
49
+ // Else, return undefined.
50
+ return undefined
28
51
  }
29
-
@@ -1,9 +1,9 @@
1
+ import { Buff } from '@vbyte/buff'
1
2
  import { ECC } from '@vbyte/micro-lib'
2
3
  import { parse_tx } from '@/lib/tx/parse.js'
3
4
  import { SIGHASH_DEFAULT } from '@/const.js'
4
- import { hash_segwit_tx } from '../sighash/segwit.js'
5
- import { hash_taproot_tx } from '../sighash/taproot.js'
6
- import { format_sigflag } from '../sighash/util.js'
5
+ import { hash_segwit_tx } from '@/lib/sighash/segwit.js'
6
+ import { hash_taproot_tx } from '@/lib/sighash/taproot.js'
7
7
 
8
8
  import type {
9
9
  SigHashOptions,
@@ -17,7 +17,7 @@ export function sign_segwit_tx (
17
17
  ) {
18
18
  const tx = parse_tx(txdata)
19
19
  const msg = hash_segwit_tx(tx, options)
20
- const sig = ECC.sign_ecdsa(seckey, msg).hex
20
+ const sig = ECC.get_ecdsa_sig(seckey, msg).hex
21
21
  const flag = format_sigflag(options.sigflag ?? SIGHASH_DEFAULT)
22
22
  return sig + flag
23
23
  }
@@ -29,7 +29,11 @@ export function sign_taproot_tx (
29
29
  ) {
30
30
  const tx = parse_tx(txdata)
31
31
  const msg = hash_taproot_tx(tx, options)
32
- const sig = ECC.sign_bip340(seckey, msg).hex
32
+ const sig = ECC.get_bip340_sig(seckey, msg).hex
33
33
  const flag = format_sigflag(options.sigflag ?? 0)
34
34
  return sig + flag
35
35
  }
36
+
37
+ function format_sigflag (flag : number) {
38
+ return (flag !== 0) ? Buff.num(flag, 1).hex : ''
39
+ }
@@ -1,12 +1,3 @@
1
- // import { Buff, Bytes, Stream } from '@vbyte/buff'
2
- // import { safeThrow } from '@/lib/utils.js'
3
- // import { checkPath } from '@/lib/tap/key.js'
4
- // import { getTapLeaf } from '@/lib/tap/tree.js'
5
- // import { Tx } from '@/lib/tx/index.js'
6
- // import { Script } from '@/lib/script/index.js'
7
- // import { HashConfig, TxData } from '@/types/index.js'
8
- // import { TxTemplate } from '@/schema/types.js'
9
- // import { hashTx } from './segwit.js'
10
1
  import { Bytes } from '@vbyte/buff'
11
2
 
12
3
  import type {
@@ -14,7 +5,7 @@ import type {
14
5
  TxData
15
6
  } from '@/types/index.js'
16
7
 
17
- export function verify_segwit_tx (
8
+ export function verify_tx (
18
9
  _txdata : TxData | Bytes,
19
10
  _config : SigHashOptions = {}
20
11
  ) : boolean {
@@ -22,14 +13,6 @@ export function verify_segwit_tx (
22
13
  return true
23
14
  }
24
15
 
25
- export function verify_taproot_tx (
26
- _txdata : TxData | Bytes,
27
- _config : SigHashOptions = {}
28
- ) : boolean {
29
- console.warn('verify_taproot_tx is not implemented')
30
- return true
31
- }
32
-
33
16
  // export function verify_signature (
34
17
  // txdata : TxData | Bytes,
35
18
  // index : number,
@@ -1,79 +1,87 @@
1
- import { Assert } from '@vbyte/micro-lib'
2
- import { COINBASE, DEFAULT } from '@/const.js'
1
+ import { Assert } from '@vbyte/micro-lib'
2
+ import { COINBASE, DEFAULT } from '@/const.js'
3
+
4
+ import {
5
+ normalize_prevout,
6
+ normalize_sequence,
7
+ normalize_value
8
+ } from './util.js'
3
9
 
4
10
  import {
5
- assert_tx_output,
6
11
  assert_tx_template,
7
- assert_vin_template
12
+ assert_vin_template,
13
+ assert_vout_template
8
14
  } from './validate.js'
9
15
 
10
16
  import type {
11
17
  TxData,
12
- TxInputTemplate,
13
18
  TxInput,
14
19
  TxOutput,
15
20
  TxTemplate,
16
21
  TxSpendInput,
17
- TxCoinbaseInput
22
+ TxCoinbaseInput,
23
+ TxOutputTemplate,
24
+ TxVirtualInput,
25
+ TxInputTemplate
18
26
  } from '@/types/index.js'
19
27
 
20
28
  export function create_coinbase_input (
21
- config : TxInputTemplate | TxInput
29
+ config : TxInputTemplate
22
30
  ) : TxCoinbaseInput {
23
31
  assert_vin_template(config)
24
32
  Assert.exists(config.coinbase, 'coinbase is required')
25
- const coinbase = config.coinbase
26
- const prevout = null
27
- const script_sig = null
28
- const sequence = config.sequence ?? DEFAULT.SEQUENCE
29
33
  const txid = COINBASE.TXID
30
34
  const vout = COINBASE.VOUT
31
- const witness = config.witness ?? []
32
- return { coinbase, prevout, script_sig, sequence, witness, txid, vout }
35
+ const coinbase = config.coinbase
36
+ const witness = config.witness ?? []
37
+ const sequence = normalize_sequence(config.sequence)
38
+ return { coinbase, prevout: null, script_sig: null, sequence, witness, txid, vout }
39
+ }
40
+
41
+ export function create_virtual_input (
42
+ config : TxInputTemplate
43
+ ) : TxVirtualInput {
44
+ assert_vin_template(config)
45
+ Assert.is_empty(config.coinbase, 'coinbase is not allowed')
46
+ Assert.is_empty(config.prevout, 'prevout is not allowed')
47
+ const { txid, vout, script_sig = null, witness = [] } = config
48
+ const sequence = normalize_sequence(config.sequence)
49
+ return { txid, vout, coinbase: null, prevout: null, script_sig, sequence, witness }
33
50
  }
34
51
 
35
52
  export function create_spend_input (
36
- config : TxInputTemplate | TxInput
53
+ config : TxInputTemplate
37
54
  ) : TxSpendInput {
38
55
  assert_vin_template(config)
39
56
  Assert.exists(config.prevout, 'prevout is required')
40
- const prevout = config.prevout
41
- const coinbase = null
42
- const script_sig = config.script_sig ?? null
43
- const sequence = config.sequence ?? DEFAULT.SEQUENCE
44
- const witness = config.witness ?? []
45
- return { ...config, coinbase, prevout, script_sig, sequence, witness }
57
+ const { txid, vout, script_sig = null, witness = [] } = config
58
+ const prevout = normalize_prevout(config.prevout)
59
+ const sequence = normalize_sequence(config.sequence)
60
+ return { txid, vout, coinbase: null, prevout, script_sig, sequence, witness }
46
61
  }
47
62
 
48
63
  export function create_tx_input (
49
- config : TxInputTemplate | TxInput
64
+ config : TxInputTemplate
50
65
  ) : TxInput {
51
- assert_vin_template(config)
52
- Assert.exists(config.txid, 'txid is required')
53
- Assert.exists(config.vout, 'vout is required')
54
- const coinbase = config.coinbase ?? null
55
- const prevout = config.prevout ?? null
56
- const script_sig = config.script_sig ?? null
57
- const sequence = config.sequence ?? DEFAULT.SEQUENCE
58
- const witness = config.witness ?? []
59
- if (coinbase !== null) return create_coinbase_input(config)
60
- if (prevout !== null) return create_spend_input(config)
61
- return { ...config, coinbase, prevout, script_sig, sequence, witness }
66
+ if (config.coinbase) return create_coinbase_input(config)
67
+ if (config.prevout) return create_spend_input(config)
68
+ return create_virtual_input(config)
62
69
  }
63
70
 
64
71
  export function create_tx_output (
65
- config : TxOutput
72
+ config : TxOutputTemplate
66
73
  ) : TxOutput {
67
- assert_tx_output(config)
68
- const { script_pk, value } = config
69
- return { script_pk, value : BigInt(value) }
74
+ assert_vout_template(config)
75
+ const script_pk = config.script_pk
76
+ const value = normalize_value(config.value)
77
+ return { script_pk, value }
70
78
  }
71
79
 
72
80
  export function create_tx (
73
- config: TxTemplate | TxData
81
+ config? : TxTemplate
74
82
  ) : TxData {
75
83
  assert_tx_template(config)
76
- const { vin = [], vout = [] } = config
84
+ const { vin = [], vout = [] } = config ?? { vin: [], vout: [] }
77
85
  const locktime = config.locktime ?? DEFAULT.LOCKTIME
78
86
  const version = config.version ?? DEFAULT.VERSION
79
87
  const inputs = vin.map(txin => create_tx_input(txin))