@vbyte/btc-dev 1.1.7 → 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.
- package/CHANGELOG.md +94 -0
- package/README.md +260 -3
- package/dist/const.d.ts +3 -0
- package/dist/const.js +23 -22
- package/dist/index.d.ts +11 -11
- package/dist/index.js +10 -10
- package/dist/lib/address/api.d.ts +2 -2
- package/dist/lib/address/api.js +12 -12
- package/dist/lib/address/encode.d.ts +1 -1
- package/dist/lib/address/encode.js +24 -24
- package/dist/lib/address/index.d.ts +6 -6
- package/dist/lib/address/index.js +6 -6
- package/dist/lib/address/p2pkh.d.ts +2 -2
- package/dist/lib/address/p2pkh.js +14 -14
- package/dist/lib/address/p2sh.d.ts +2 -2
- package/dist/lib/address/p2sh.js +13 -13
- package/dist/lib/address/p2tr.d.ts +2 -2
- package/dist/lib/address/p2tr.js +13 -13
- package/dist/lib/address/p2wpkh.d.ts +2 -2
- package/dist/lib/address/p2wpkh.js +14 -14
- package/dist/lib/address/p2wsh.d.ts +2 -2
- package/dist/lib/address/p2wsh.js +13 -13
- package/dist/lib/address/script.d.ts +1 -1
- package/dist/lib/address/script.js +16 -16
- package/dist/lib/address/util.d.ts +1 -1
- package/dist/lib/address/util.js +22 -22
- package/dist/lib/meta/index.d.ts +4 -4
- package/dist/lib/meta/index.js +4 -4
- package/dist/lib/meta/locktime.d.ts +1 -1
- package/dist/lib/meta/locktime.js +12 -12
- package/dist/lib/meta/ref.js +9 -6
- package/dist/lib/meta/scribe.d.ts +2 -2
- package/dist/lib/meta/scribe.js +48 -53
- package/dist/lib/meta/sequence.d.ts +1 -1
- package/dist/lib/meta/sequence.js +16 -15
- package/dist/lib/script/decode.d.ts +2 -2
- package/dist/lib/script/decode.js +50 -15
- package/dist/lib/script/encode.d.ts +1 -1
- package/dist/lib/script/encode.js +20 -16
- package/dist/lib/script/index.d.ts +5 -13
- package/dist/lib/script/index.js +5 -14
- package/dist/lib/script/lock.d.ts +2 -2
- package/dist/lib/script/lock.js +15 -12
- package/dist/lib/script/util.js +4 -4
- package/dist/lib/script/words.js +129 -129
- package/dist/lib/sighash/index.d.ts +3 -3
- package/dist/lib/sighash/index.js +3 -3
- package/dist/lib/sighash/segwit.d.ts +2 -2
- package/dist/lib/sighash/segwit.js +15 -14
- package/dist/lib/sighash/taproot.d.ts +2 -2
- package/dist/lib/sighash/taproot.js +24 -23
- package/dist/lib/sighash/util.d.ts +2 -2
- package/dist/lib/sighash/util.js +7 -7
- package/dist/lib/signer/index.d.ts +2 -2
- package/dist/lib/signer/index.js +2 -2
- package/dist/lib/signer/sign.d.ts +1 -1
- package/dist/lib/signer/sign.js +42 -7
- package/dist/lib/signer/verify.d.ts +17 -3
- package/dist/lib/signer/verify.js +233 -3
- package/dist/lib/taproot/cblock.d.ts +1 -1
- package/dist/lib/taproot/cblock.js +14 -16
- package/dist/lib/taproot/encode.d.ts +1 -1
- package/dist/lib/taproot/encode.js +7 -7
- package/dist/lib/taproot/index.d.ts +4 -4
- package/dist/lib/taproot/index.js +4 -4
- package/dist/lib/taproot/parse.d.ts +1 -1
- package/dist/lib/taproot/parse.js +12 -14
- package/dist/lib/taproot/tree.d.ts +2 -2
- package/dist/lib/taproot/tree.js +11 -7
- package/dist/lib/tx/create.d.ts +1 -1
- package/dist/lib/tx/create.js +28 -12
- package/dist/lib/tx/decode.d.ts +2 -2
- package/dist/lib/tx/decode.js +50 -17
- package/dist/lib/tx/encode.d.ts +2 -2
- package/dist/lib/tx/encode.js +13 -16
- package/dist/lib/tx/index.d.ts +7 -7
- package/dist/lib/tx/index.js +7 -7
- package/dist/lib/tx/parse.d.ts +1 -1
- package/dist/lib/tx/parse.js +9 -9
- package/dist/lib/tx/size.d.ts +2 -2
- package/dist/lib/tx/size.js +9 -9
- package/dist/lib/tx/util.d.ts +2 -2
- package/dist/lib/tx/util.js +23 -22
- package/dist/lib/tx/validate.d.ts +1 -1
- package/dist/lib/tx/validate.js +3 -3
- package/dist/lib/witness/index.d.ts +2 -2
- package/dist/lib/witness/index.js +2 -2
- package/dist/lib/witness/parse.d.ts +2 -2
- package/dist/lib/witness/parse.js +24 -23
- package/dist/lib/witness/util.d.ts +2 -2
- package/dist/lib/witness/util.js +5 -5
- package/dist/main.cjs +2308 -1007
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +2308 -1007
- package/dist/module.mjs.map +1 -1
- package/dist/package.json +20 -17
- package/dist/schema/base.d.ts +1 -1
- package/dist/schema/base.js +17 -13
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +2 -2
- package/dist/schema/taproot.d.ts +1 -1
- package/dist/schema/taproot.js +2 -2
- package/dist/schema/tx.d.ts +1 -1
- package/dist/schema/tx.js +4 -4
- package/dist/script.js +8 -8
- package/dist/script.js.map +1 -1
- package/dist/types/address.d.ts +4 -4
- package/dist/types/index.d.ts +8 -8
- package/dist/types/index.js +8 -8
- package/dist/types/meta.d.ts +4 -4
- package/dist/types/psbt.d.ts +2 -2
- package/dist/types/script.d.ts +2 -2
- package/dist/types/sighash.d.ts +2 -2
- package/dist/types/witness.d.ts +5 -5
- package/package.json +20 -17
- package/src/const.ts +0 -61
- package/src/index.ts +0 -13
- package/src/lib/address/api.ts +0 -50
- package/src/lib/address/encode.ts +0 -183
- package/src/lib/address/index.ts +0 -7
- package/src/lib/address/p2pkh.ts +0 -94
- package/src/lib/address/p2sh.ts +0 -96
- package/src/lib/address/p2tr.ts +0 -91
- package/src/lib/address/p2wpkh.ts +0 -94
- package/src/lib/address/p2wsh.ts +0 -92
- package/src/lib/address/script.ts +0 -63
- package/src/lib/address/util.ts +0 -87
- package/src/lib/meta/index.ts +0 -4
- package/src/lib/meta/locktime.ts +0 -57
- package/src/lib/meta/ref.ts +0 -107
- package/src/lib/meta/scribe.ts +0 -256
- package/src/lib/meta/sequence.ts +0 -146
- package/src/lib/script/decode.ts +0 -85
- package/src/lib/script/encode.ts +0 -129
- package/src/lib/script/index.ts +0 -20
- package/src/lib/script/lock.ts +0 -73
- package/src/lib/script/util.ts +0 -78
- package/src/lib/script/words.ts +0 -182
- package/src/lib/sighash/index.ts +0 -3
- package/src/lib/sighash/segwit.ts +0 -152
- package/src/lib/sighash/taproot.ts +0 -206
- package/src/lib/sighash/util.ts +0 -51
- package/src/lib/signer/index.ts +0 -2
- package/src/lib/signer/sign.ts +0 -39
- package/src/lib/signer/verify.ts +0 -88
- package/src/lib/taproot/cblock.ts +0 -96
- package/src/lib/taproot/encode.ts +0 -49
- package/src/lib/taproot/index.ts +0 -4
- package/src/lib/taproot/parse.ts +0 -65
- package/src/lib/taproot/tree.ts +0 -94
- package/src/lib/tx/create.ts +0 -90
- package/src/lib/tx/decode.ts +0 -123
- package/src/lib/tx/encode.ts +0 -155
- package/src/lib/tx/index.ts +0 -7
- package/src/lib/tx/parse.ts +0 -69
- package/src/lib/tx/size.ts +0 -68
- package/src/lib/tx/util.ts +0 -113
- package/src/lib/tx/validate.ts +0 -49
- package/src/lib/witness/index.ts +0 -2
- package/src/lib/witness/parse.ts +0 -127
- package/src/lib/witness/util.ts +0 -18
- package/src/schema/base.ts +0 -57
- package/src/schema/index.ts +0 -2
- package/src/schema/taproot.ts +0 -12
- package/src/schema/tx.ts +0 -48
- package/src/types/address.ts +0 -35
- package/src/types/index.ts +0 -8
- package/src/types/meta.ts +0 -48
- package/src/types/psbt.ts +0 -15
- package/src/types/script.ts +0 -18
- package/src/types/sighash.ts +0 -16
- package/src/types/taproot.ts +0 -41
- package/src/types/txdata.ts +0 -85
- package/src/types/witness.ts +0 -42
package/src/lib/tx/encode.ts
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { Buff } from '@vbyte/buff'
|
|
2
|
-
import { Assert } from '@vbyte/micro-lib'
|
|
3
|
-
import { assert_tx_data } from './validate.js'
|
|
4
|
-
import { COINBASE } from '@/const.js'
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
TxInput,
|
|
8
|
-
TxOutput,
|
|
9
|
-
TxData
|
|
10
|
-
} from '@/types/index.js'
|
|
11
|
-
|
|
12
|
-
export function encode_tx (
|
|
13
|
-
txdata : TxData,
|
|
14
|
-
use_segwit = true
|
|
15
|
-
) : Buff {
|
|
16
|
-
// Assert the txdata is a valid tx data object.
|
|
17
|
-
assert_tx_data(txdata)
|
|
18
|
-
// Unpack the transaction data.
|
|
19
|
-
const { version, vin, vout, locktime } = txdata
|
|
20
|
-
// Create a buffer for the transaction.
|
|
21
|
-
const buffer : Buff[] = [ encode_tx_version(version) ]
|
|
22
|
-
// If the transaction is a segwit transaction,
|
|
23
|
-
if (use_segwit) {
|
|
24
|
-
// Add the segwit marker to the buffer.
|
|
25
|
-
buffer.push(Buff.hex('0001'))
|
|
26
|
-
}
|
|
27
|
-
// Add the inputs to the buffer.
|
|
28
|
-
buffer.push(encode_tx_inputs(vin))
|
|
29
|
-
// Add the outputs to the buffer.
|
|
30
|
-
buffer.push(encode_tx_outputs(vout))
|
|
31
|
-
// If the transaction is a segwit transaction,
|
|
32
|
-
if (use_segwit) {
|
|
33
|
-
// For each input in the transaction,
|
|
34
|
-
for (const input of vin) {
|
|
35
|
-
// Add the witness data to the buffer.
|
|
36
|
-
buffer.push(encode_vin_witness(input.witness))
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// Add the locktime to the buffer.
|
|
40
|
-
buffer.push(encode_tx_locktime(locktime))
|
|
41
|
-
// Return the buffer as a single payload.
|
|
42
|
-
return Buff.join(buffer)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function encode_tx_version (num : number) : Buff {
|
|
46
|
-
// Encode the transaction version as a 4-byte little-endian number.
|
|
47
|
-
return Buff.num(num, 4).reverse()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function encode_txin_txid (txid : string) : Buff {
|
|
51
|
-
// Encode the transaction ID as a 32-byte little-endian number.
|
|
52
|
-
return Buff.hex(txid, 32).reverse()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function encode_txin_vout (vout : number) : Buff {
|
|
56
|
-
// Encode the output index as a 4-byte little-endian number.
|
|
57
|
-
return Buff.num(vout, 4).reverse()
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function encode_txin_sequence (sequence : number) : Buff {
|
|
61
|
-
// Encode the sequence number as a 4-byte little-endian number.
|
|
62
|
-
return Buff.num(sequence, 4).reverse()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function encode_tx_inputs (vin : TxInput[]) : Buff {
|
|
66
|
-
// Create a buffer for the inputs, starting with the array length.
|
|
67
|
-
const raw : Buff[] = [ Buff.varint(vin.length, 'le') ]
|
|
68
|
-
// For each input in the array,
|
|
69
|
-
for (const input of vin) {
|
|
70
|
-
// Encode the input, and add it to the buffer.
|
|
71
|
-
raw.push(encode_vin(input))
|
|
72
|
-
}
|
|
73
|
-
// Return the buffer as a single payload.
|
|
74
|
-
return Buff.join(raw)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function encode_vin (txin : TxInput) : Buff {
|
|
78
|
-
// If the input is a coinbase,
|
|
79
|
-
if (txin.coinbase !== null) {
|
|
80
|
-
// Encode and return the coinbase as a single payload.
|
|
81
|
-
return Buff.join([
|
|
82
|
-
encode_txin_txid(COINBASE.TXID),
|
|
83
|
-
encode_txin_vout(COINBASE.VOUT),
|
|
84
|
-
encode_script_data(txin.coinbase),
|
|
85
|
-
encode_txin_sequence(txin.sequence)
|
|
86
|
-
])
|
|
87
|
-
} else {
|
|
88
|
-
// Encode and return the input as a single payload.
|
|
89
|
-
return Buff.join([
|
|
90
|
-
encode_txin_txid(txin.txid),
|
|
91
|
-
encode_txin_vout(txin.vout),
|
|
92
|
-
encode_script_data(txin.script_sig),
|
|
93
|
-
encode_txin_sequence(txin.sequence)
|
|
94
|
-
])
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function encode_vout_value (value : bigint) : Buff {
|
|
99
|
-
// Encode the value as an 8-byte little-endian number.
|
|
100
|
-
return Buff.big(value, 8).reverse()
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function encode_tx_outputs (vout : TxOutput[]) : Buff {
|
|
104
|
-
// Create a buffer for the outputs, starting with the array length.
|
|
105
|
-
const buffer : Buff[] = [ Buff.varint(vout.length, 'le') ]
|
|
106
|
-
// For each output in the array,
|
|
107
|
-
for (const output of vout) {
|
|
108
|
-
// Encode the output, and add it to the buffer.
|
|
109
|
-
buffer.push(encode_tx_vout(output))
|
|
110
|
-
}
|
|
111
|
-
// Return the buffer as a single payload.
|
|
112
|
-
return Buff.join(buffer)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function encode_tx_vout (txout : TxOutput) : Buff {
|
|
116
|
-
// Get the value and script pubkey from the output.
|
|
117
|
-
const { value, script_pk } = txout
|
|
118
|
-
// Return the data encoded as a single payload.
|
|
119
|
-
return Buff.join([
|
|
120
|
-
encode_vout_value(value),
|
|
121
|
-
encode_script_data(script_pk)
|
|
122
|
-
])
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function encode_vin_witness (data : string[]) : Buff {
|
|
126
|
-
// Create a buffer for the witness data, starting with the array length.
|
|
127
|
-
const buffer : Buff[] = [ Buff.varint(data.length) ]
|
|
128
|
-
// For each parameter in the witness array,
|
|
129
|
-
for (const param of data) {
|
|
130
|
-
// Encode the parameter, and add it to the buffer.
|
|
131
|
-
buffer.push(encode_script_data(param))
|
|
132
|
-
}
|
|
133
|
-
// Return the buffer as a single payload.
|
|
134
|
-
return Buff.join(buffer)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function encode_tx_locktime (locktime : number) : Buff {
|
|
138
|
-
// Encode the locktime as a 4-byte little-endian number.
|
|
139
|
-
return Buff.num(locktime, 4).reverse()
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export function encode_script_data (
|
|
143
|
-
script : string | null
|
|
144
|
-
) : Buff {
|
|
145
|
-
// If the script is not null,
|
|
146
|
-
if (script !== null) {
|
|
147
|
-
// Assert that the script is a hex string.
|
|
148
|
-
Assert.is_hex(script)
|
|
149
|
-
// Encode the script, and add it to the buffer.
|
|
150
|
-
return Buff.hex(script).prefix_varint('le')
|
|
151
|
-
} else {
|
|
152
|
-
// Return a single byte of zero.
|
|
153
|
-
return Buff.hex('00')
|
|
154
|
-
}
|
|
155
|
-
}
|
package/src/lib/tx/index.ts
DELETED
package/src/lib/tx/parse.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Assert } from '@vbyte/micro-lib/assert'
|
|
2
|
-
import { decode_tx } from './decode.js'
|
|
3
|
-
import { assert_tx_template } from './validate.js'
|
|
4
|
-
import { create_tx, create_tx_output } from './create.js'
|
|
5
|
-
|
|
6
|
-
import type { TxData, TxOutputTemplate } from '@/types/index.js'
|
|
7
|
-
|
|
8
|
-
export function parse_tx (
|
|
9
|
-
txdata : unknown,
|
|
10
|
-
prevouts? : TxOutputTemplate[]
|
|
11
|
-
) : TxData {
|
|
12
|
-
// Define the tx variable.
|
|
13
|
-
let tx : TxData
|
|
14
|
-
// If the txdata is a string or Uint8Array,
|
|
15
|
-
if (typeof txdata === 'string' || txdata instanceof Uint8Array) {
|
|
16
|
-
// Decode the tx.
|
|
17
|
-
tx = decode_tx(txdata)
|
|
18
|
-
} else {
|
|
19
|
-
// Assert the txdata is a valid tx template.
|
|
20
|
-
assert_tx_template(txdata)
|
|
21
|
-
// Create the tx.
|
|
22
|
-
tx = create_tx(txdata)
|
|
23
|
-
}
|
|
24
|
-
// If the prevouts are provided,
|
|
25
|
-
if (prevouts) {
|
|
26
|
-
// Assert the prevouts are a non-empty array.
|
|
27
|
-
Assert.has_items(prevouts, 'prevouts must be a non-empty array')
|
|
28
|
-
// Iterate over the inputs.
|
|
29
|
-
for (const [ idx, vin ] of tx.vin.entries()) {
|
|
30
|
-
// Get the prevout.
|
|
31
|
-
const prevout = prevouts.at(idx)
|
|
32
|
-
// Assert the prevout exists.
|
|
33
|
-
Assert.exists(prevout, 'prevout not found for input index: ' + idx)
|
|
34
|
-
// Create the prevout.
|
|
35
|
-
vin.prevout = create_tx_output(prevout)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Return the tx.
|
|
39
|
-
return tx
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function serialize_tx (
|
|
43
|
-
txdata : unknown
|
|
44
|
-
) : Record<string, unknown> {
|
|
45
|
-
const tx = parse_tx(txdata)
|
|
46
|
-
const version = tx.version
|
|
47
|
-
const locktime = tx.locktime
|
|
48
|
-
|
|
49
|
-
const vin : Record<string, unknown>[] = []
|
|
50
|
-
const vout : Record<string, unknown>[] = []
|
|
51
|
-
|
|
52
|
-
for (const e of tx.vin) {
|
|
53
|
-
if (e.prevout !== null) {
|
|
54
|
-
vin.push({
|
|
55
|
-
script_pk : e.prevout.script_pk,
|
|
56
|
-
value : Number(e.prevout.value)
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
for (const e of tx.vout) {
|
|
62
|
-
vout.push({
|
|
63
|
-
script_pk : e.script_pk,
|
|
64
|
-
value : Number(e.value)
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return { version, locktime, vin, vout }
|
|
69
|
-
}
|
package/src/lib/tx/size.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Buff, Bytes } from '@vbyte/buff'
|
|
2
|
-
import { parse_tx } from './parse.js'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
encode_tx,
|
|
6
|
-
encode_tx_inputs,
|
|
7
|
-
encode_tx_outputs,
|
|
8
|
-
encode_tx_vout,
|
|
9
|
-
encode_vin,
|
|
10
|
-
encode_vin_witness
|
|
11
|
-
} from './encode.js'
|
|
12
|
-
|
|
13
|
-
import type {
|
|
14
|
-
TxData,
|
|
15
|
-
TxInput,
|
|
16
|
-
TxOutput,
|
|
17
|
-
TxSize
|
|
18
|
-
} from '@/types/index.js'
|
|
19
|
-
|
|
20
|
-
const WIT_FLAG_BYTES = 2
|
|
21
|
-
|
|
22
|
-
export function get_vsize (
|
|
23
|
-
bytes : Bytes
|
|
24
|
-
) : number {
|
|
25
|
-
const weight = Buff.bytes(bytes).length
|
|
26
|
-
const remain = (weight % 4 > 0) ? 1 : 0
|
|
27
|
-
return Math.ceil(weight / 4) + remain
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function get_txsize (
|
|
31
|
-
txdata : string | TxData
|
|
32
|
-
) : TxSize {
|
|
33
|
-
const json = parse_tx(txdata)
|
|
34
|
-
const base = encode_tx(json, false).length
|
|
35
|
-
const total = encode_tx(json, true).length
|
|
36
|
-
const weight = base * 3 + total
|
|
37
|
-
const remain = (weight % 4 > 0) ? 1 : 0
|
|
38
|
-
const vsize = Math.ceil(weight / 4) + remain
|
|
39
|
-
return { base, total, vsize, weight }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function get_vin_size (vin : TxInput[]) : number {
|
|
43
|
-
const bytes = encode_tx_inputs(vin)
|
|
44
|
-
return bytes.length
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function get_vout_size (vout : TxOutput[]) : number {
|
|
48
|
-
const bytes = encode_tx_outputs(vout)
|
|
49
|
-
return bytes.length
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function get_segwit_size (txinputs : TxInput[]) : number {
|
|
53
|
-
const segwit_data = txinputs
|
|
54
|
-
.filter(e => e.witness.length > 0)
|
|
55
|
-
.map(e => e.witness)
|
|
56
|
-
return WIT_FLAG_BYTES + segwit_data
|
|
57
|
-
.reduce((acc, e) => acc + encode_vin_witness(e).length, 0)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function get_txin_size (txinput : TxInput) : number {
|
|
61
|
-
const bytes = encode_vin(txinput)
|
|
62
|
-
return bytes.length
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function get_txout_size (txoutput : TxOutput) : number {
|
|
66
|
-
const bytes = encode_tx_vout(txoutput)
|
|
67
|
-
return bytes.length
|
|
68
|
-
}
|
package/src/lib/tx/util.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { Buff } from '@vbyte/buff'
|
|
2
|
-
import { Test } from '@vbyte/micro-lib'
|
|
3
|
-
import { Assert } from '@vbyte/micro-lib/assert'
|
|
4
|
-
import { hash256 } from '@vbyte/micro-lib/hash'
|
|
5
|
-
import { decode_tx } from './decode.js'
|
|
6
|
-
import { encode_tx } from './encode.js'
|
|
7
|
-
import { parse_tx } from './parse.js'
|
|
8
|
-
import { assert_tx_template } from './validate.js'
|
|
9
|
-
|
|
10
|
-
import { DEFAULT } from '@/const.js'
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
TxData,
|
|
14
|
-
TxOutput,
|
|
15
|
-
TxOutputTemplate,
|
|
16
|
-
TxValue
|
|
17
|
-
} from '@/types/index.js'
|
|
18
|
-
|
|
19
|
-
export function transcode_tx (
|
|
20
|
-
txdata : string | Uint8Array,
|
|
21
|
-
use_segwit = true
|
|
22
|
-
) : Buff {
|
|
23
|
-
console.log('txdata:', txdata)
|
|
24
|
-
// Decode the transaction data.
|
|
25
|
-
const decoded = decode_tx(txdata)
|
|
26
|
-
console.log('decoded:', decoded)
|
|
27
|
-
// Re-encode and return the encoded transaction data.
|
|
28
|
-
return encode_tx(decoded, use_segwit)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function get_txid (txdata : string | Uint8Array | TxData) : string {
|
|
32
|
-
let buffer : Uint8Array
|
|
33
|
-
|
|
34
|
-
if (txdata instanceof Uint8Array) {
|
|
35
|
-
// Set the buffer to the transaction data.
|
|
36
|
-
buffer = transcode_tx(txdata, false)
|
|
37
|
-
} else if (typeof txdata === 'object') {
|
|
38
|
-
// Assert the structure of the transaction data is valid.
|
|
39
|
-
assert_tx_template(txdata)
|
|
40
|
-
// Encode the transaction data.
|
|
41
|
-
buffer = encode_tx(txdata, false)
|
|
42
|
-
} else if (typeof txdata === 'string') {
|
|
43
|
-
// Assert the transaction data is a hex string.
|
|
44
|
-
Assert.is_hex(txdata)
|
|
45
|
-
// Convert the hex string to a Uint8Array.
|
|
46
|
-
buffer = transcode_tx(txdata, false)
|
|
47
|
-
} else {
|
|
48
|
-
throw new TypeError('invalid txdata type: ' + typeof txdata)
|
|
49
|
-
}
|
|
50
|
-
// Return the txid of the transaction data.
|
|
51
|
-
return hash256(buffer).reverse().hex
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function get_txhash (txdata : string | Uint8Array | TxData) : string {
|
|
55
|
-
// If the transaction data is an object,
|
|
56
|
-
if (typeof txdata === 'object') {
|
|
57
|
-
// Assert the structure of the transaction data is valid.
|
|
58
|
-
assert_tx_template(txdata)
|
|
59
|
-
// Encode the transaction data.
|
|
60
|
-
txdata = encode_tx(txdata, true)
|
|
61
|
-
}
|
|
62
|
-
// Return the txhash of the transaction data.
|
|
63
|
-
return hash256(txdata).reverse().hex
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function get_tx_value (txdata : string | Uint8Array | TxData) : TxValue {
|
|
67
|
-
// Parse the transaction data.
|
|
68
|
-
const tx = parse_tx(txdata)
|
|
69
|
-
// Assert the structure of the transaction data is valid.
|
|
70
|
-
assert_tx_template(tx)
|
|
71
|
-
// Calculate the value of the transaction.
|
|
72
|
-
const vin = tx.vin.reduce((acc, txin) => acc + (txin.prevout?.value ?? 0n), 0n)
|
|
73
|
-
const vout = tx.vout.reduce((acc, txout) => acc + txout.value, 0n)
|
|
74
|
-
const fees = (vin > vout) ? (vin - vout) : 0n
|
|
75
|
-
// Return the value of the transaction.
|
|
76
|
-
return { fees, vin, vout }
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function get_prevouts (txdata : TxData) : TxOutput[] {
|
|
80
|
-
// Assert the structure of the transaction data is valid.
|
|
81
|
-
assert_tx_template(txdata)
|
|
82
|
-
// Collect the prevouts from the transaction.
|
|
83
|
-
const prevouts = txdata.vin.map(e => e.prevout)
|
|
84
|
-
// Assert that all the prevouts are defined.
|
|
85
|
-
Assert.ok(prevouts.every(e => e !== null), 'prevouts missing from tx')
|
|
86
|
-
// Return the array of prevouts.
|
|
87
|
-
return prevouts
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function normalize_sequence (sequence? : number | string | null) : number {
|
|
91
|
-
// If sequence is not defined, return a default sequence value.
|
|
92
|
-
if (!Test.exists(sequence)) return DEFAULT.SEQUENCE
|
|
93
|
-
// If sequence is a hex string, decode it and return the number value.
|
|
94
|
-
if (Test.is_hex(sequence)) return Buff.hex(sequence as string, 4).reverse().num
|
|
95
|
-
// If sequence is a valid unsigned integer, return the value.
|
|
96
|
-
if (Test.is_uint(sequence)) return sequence
|
|
97
|
-
// Else, throw an error.
|
|
98
|
-
throw new Error('invalid sequence value: ' + String(sequence))
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function normalize_value (value : number | bigint) : bigint {
|
|
102
|
-
// If value is a unsigned integer, return it as a bigint.
|
|
103
|
-
if (Test.is_uint(value)) return BigInt(value)
|
|
104
|
-
// If value is a bigint, return it as-is.
|
|
105
|
-
if (typeof value === 'bigint') return value
|
|
106
|
-
// Else, throw an error.
|
|
107
|
-
throw new TypeError('invalid output value: ' + String(value))
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function normalize_prevout (prevout : TxOutputTemplate) : TxOutput {
|
|
111
|
-
// Return the output with a normalized value.
|
|
112
|
-
return { script_pk: prevout.script_pk, value: normalize_value(prevout.value) }
|
|
113
|
-
}
|
package/src/lib/tx/validate.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import * as Schema from '@/schema/index.js'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
TxSpendInput,
|
|
5
|
-
TxData,
|
|
6
|
-
TxInput,
|
|
7
|
-
TxInputTemplate,
|
|
8
|
-
TxOutput,
|
|
9
|
-
TxTemplate,
|
|
10
|
-
TxOutputTemplate,
|
|
11
|
-
TxSpendData,
|
|
12
|
-
} from '@/types/index.js'
|
|
13
|
-
|
|
14
|
-
export function assert_tx_template (txdata : unknown) : asserts txdata is TxTemplate {
|
|
15
|
-
Schema.tx.tx_template.parse(txdata)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function assert_has_prevouts (vin : TxInput[]) : asserts vin is TxSpendInput[] {
|
|
19
|
-
if (vin.some(txin => txin.prevout === null)) {
|
|
20
|
-
throw new Error('transaction missing prevouts')
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function assert_tx_data (txdata : unknown) : asserts txdata is TxData {
|
|
25
|
-
Schema.tx.tx_data.parse(txdata)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function assert_tx_spend_data (txdata : unknown) : asserts txdata is TxSpendData {
|
|
29
|
-
// Assert the txdata is a valid tx data object.
|
|
30
|
-
assert_tx_data(txdata)
|
|
31
|
-
// Assert the txdata has prevouts.
|
|
32
|
-
assert_has_prevouts(txdata.vin)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function assert_tx_input (tx_input : unknown) : asserts tx_input is TxInput {
|
|
36
|
-
Schema.tx.tx_input.parse(tx_input)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function assert_tx_output (tx_output : unknown) : asserts tx_output is TxOutput {
|
|
40
|
-
Schema.tx.tx_output.parse(tx_output)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function assert_vin_template (vin : unknown) : asserts vin is TxInputTemplate {
|
|
44
|
-
Schema.tx.vin_template.parse(vin)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function assert_vout_template (vout : unknown) : asserts vout is TxOutputTemplate {
|
|
48
|
-
Schema.tx.vout_template.parse(vout)
|
|
49
|
-
}
|
package/src/lib/witness/index.ts
DELETED
package/src/lib/witness/parse.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { Buff, Bytes } from '@vbyte/buff'
|
|
2
|
-
import { is_valid_script } from '@/lib/script/decode.js'
|
|
3
|
-
import { TAPLEAF_VERSIONS } from '@/const.js'
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
WitnessData,
|
|
7
|
-
SpendScriptType,
|
|
8
|
-
WitnessVersion
|
|
9
|
-
} from '@/types/index.js'
|
|
10
|
-
|
|
11
|
-
export function parse_witness (
|
|
12
|
-
witness : Bytes[]
|
|
13
|
-
) : WitnessData {
|
|
14
|
-
// Parse the witness data.
|
|
15
|
-
const elems = witness.map(e => Buff.bytes(e))
|
|
16
|
-
const stack = witness.map(e => Buff.bytes(e).hex)
|
|
17
|
-
const annex = parse_annex_data(elems)
|
|
18
|
-
if (annex !== null) elems.pop()
|
|
19
|
-
const cblock = parse_cblock_data(elems)
|
|
20
|
-
if (cblock !== null) elems.pop()
|
|
21
|
-
const type = parse_witness_type(elems, cblock)
|
|
22
|
-
const version = parse_witness_version(type)
|
|
23
|
-
const script = parse_witness_script(elems, type)
|
|
24
|
-
if (script !== null) elems.pop()
|
|
25
|
-
const params = elems.map(e => e.hex)
|
|
26
|
-
return { annex, cblock, params, script, stack, type, version }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function parse_annex_data (
|
|
30
|
-
data : Uint8Array[]
|
|
31
|
-
) : string | null {
|
|
32
|
-
// Get the last element of the array.
|
|
33
|
-
let elem = data.at(-1)
|
|
34
|
-
// Check if the element fits the annex format.
|
|
35
|
-
if (
|
|
36
|
-
data.length > 1 &&
|
|
37
|
-
elem instanceof Uint8Array &&
|
|
38
|
-
elem[0] === 0x50
|
|
39
|
-
) {
|
|
40
|
-
// Return the element.
|
|
41
|
-
return new Buff(elem).hex
|
|
42
|
-
} else {
|
|
43
|
-
// Return null.
|
|
44
|
-
return null
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function parse_cblock_data (
|
|
49
|
-
data : Uint8Array[]
|
|
50
|
-
) : string | null {
|
|
51
|
-
let elem = data.at(-1)
|
|
52
|
-
if (
|
|
53
|
-
data.length > 1 &&
|
|
54
|
-
elem instanceof Uint8Array &&
|
|
55
|
-
elem.length > 32 &&
|
|
56
|
-
TAPLEAF_VERSIONS.includes(elem[0] & 0xfe)
|
|
57
|
-
) {
|
|
58
|
-
// Return the element.
|
|
59
|
-
return new Buff(elem).hex
|
|
60
|
-
} else {
|
|
61
|
-
// Return null.
|
|
62
|
-
return null
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function parse_witness_script (
|
|
67
|
-
elems : Uint8Array[],
|
|
68
|
-
type : SpendScriptType | null
|
|
69
|
-
) {
|
|
70
|
-
let script : Uint8Array | undefined
|
|
71
|
-
switch (type) {
|
|
72
|
-
case 'p2ts':
|
|
73
|
-
script = elems.at(-1)
|
|
74
|
-
case 'p2wsh':
|
|
75
|
-
script = elems.at(-1)
|
|
76
|
-
}
|
|
77
|
-
return (script !== undefined) ? new Buff(script).hex : null
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function parse_witness_type (
|
|
81
|
-
elems : Uint8Array[],
|
|
82
|
-
cblock : string | null
|
|
83
|
-
) : SpendScriptType | null{
|
|
84
|
-
// Get the important elements of the witness.
|
|
85
|
-
let param_0 = elems.at(0),
|
|
86
|
-
param_1 = elems.at(1),
|
|
87
|
-
param_x = elems.at(-1)
|
|
88
|
-
// If the cblock is present and the last element exists:
|
|
89
|
-
if (cblock !== null && param_x !== undefined) {
|
|
90
|
-
return 'p2ts'
|
|
91
|
-
// If the witness elements match the profile of a p2w-pkh:
|
|
92
|
-
} else if (
|
|
93
|
-
elems.length === 2 &&
|
|
94
|
-
param_0 !== undefined &&
|
|
95
|
-
param_1 !== undefined &&
|
|
96
|
-
param_0.length >= 64 &&
|
|
97
|
-
param_1.length === 33
|
|
98
|
-
) {
|
|
99
|
-
return 'p2wpkh'
|
|
100
|
-
// If the witness elements match the profile of a p2tr-pk:
|
|
101
|
-
} else if (
|
|
102
|
-
elems.length === 1 &&
|
|
103
|
-
param_0 !== undefined &&
|
|
104
|
-
param_0.length === 64
|
|
105
|
-
) {
|
|
106
|
-
return 'p2tr'
|
|
107
|
-
// If there is at least two witness elements:
|
|
108
|
-
} else if (
|
|
109
|
-
elems.length > 1 &&
|
|
110
|
-
param_x !== undefined &&
|
|
111
|
-
is_valid_script(param_x)
|
|
112
|
-
) {
|
|
113
|
-
return 'p2wsh'
|
|
114
|
-
// If the witness elements don't match any known profile:
|
|
115
|
-
} else {
|
|
116
|
-
return null
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function parse_witness_version (
|
|
121
|
-
type : SpendScriptType | null
|
|
122
|
-
) : WitnessVersion | null {
|
|
123
|
-
if (type === null) return null
|
|
124
|
-
if (type.startsWith('p2w')) return 0
|
|
125
|
-
if (type.startsWith('p2t')) return 1
|
|
126
|
-
return null
|
|
127
|
-
}
|
package/src/lib/witness/util.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Buff, Bytes } from '@vbyte/buff'
|
|
2
|
-
import { Assert } from '@vbyte/micro-lib'
|
|
3
|
-
|
|
4
|
-
import type { WitnessSize } from '@/types/index.js'
|
|
5
|
-
|
|
6
|
-
const WIT_LENGTH_BYTE = 1
|
|
7
|
-
|
|
8
|
-
export function get_witness_size (witness : Bytes[]) : WitnessSize {
|
|
9
|
-
const stack = witness.map(e => Buff.bytes(e))
|
|
10
|
-
const size = stack.reduce((prev, next) => prev + next.length, 0)
|
|
11
|
-
const vsize = Math.ceil(WIT_LENGTH_BYTE + size / 4)
|
|
12
|
-
return { total: size, vsize }
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function assert_witness (witness : unknown) : asserts witness is Bytes[] {
|
|
16
|
-
Assert.ok(Array.isArray(witness), 'witness must be an array')
|
|
17
|
-
Assert.ok(witness.every(e => Buff.is_bytes(e)), 'witness must be an array of strings or bytes')
|
|
18
|
-
}
|
package/src/schema/base.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
type Literal = z.infer<typeof literal>
|
|
4
|
-
type Json = Literal | { [key : string] : Json } | Json[]
|
|
5
|
-
|
|
6
|
-
export const big = z.bigint()
|
|
7
|
-
export const bool = z.boolean()
|
|
8
|
-
export const date = z.date()
|
|
9
|
-
export const num = z.number().min(Number.MIN_SAFE_INTEGER).max(Number.MAX_SAFE_INTEGER)
|
|
10
|
-
export const int = num.int()
|
|
11
|
-
export const u8a = z.instanceof(Uint8Array)
|
|
12
|
-
export const str = z.string()
|
|
13
|
-
export const stamp = int.min(500_000_000)
|
|
14
|
-
export const any = z.any()
|
|
15
|
-
export const zod = z
|
|
16
|
-
export const char = int.min(0).max(0xFF)
|
|
17
|
-
export const short = int.min(0).max(0xFFFF)
|
|
18
|
-
export const uint = int.min(0).max(0xFFFFFFFF)
|
|
19
|
-
|
|
20
|
-
export const float = z.number().refine((e) => String(e).includes('.'))
|
|
21
|
-
|
|
22
|
-
export const float2 = float.refine((e) => {
|
|
23
|
-
const parts = String(e).split('.').at(1)
|
|
24
|
-
return parts !== undefined && parts.length <= 2
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export const hex = z.string()
|
|
28
|
-
.regex(/^[0-9a-fA-F]*$/)
|
|
29
|
-
.refine(e => e.length % 2 === 0)
|
|
30
|
-
|
|
31
|
-
export const literal = z.union([
|
|
32
|
-
z.string(), z.number(), z.boolean(), z.null()
|
|
33
|
-
])
|
|
34
|
-
|
|
35
|
-
export const json : z.ZodType<Json> = z.lazy(() =>
|
|
36
|
-
z.union([ literal, z.array(json), z.record(str, json) ])
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
export const u8a20 = u8a.refine((e) => e.length === 20)
|
|
40
|
-
export const u8a32 = u8a.refine((e) => e.length === 32)
|
|
41
|
-
export const u8a33 = u8a.refine((e) => e.length === 33)
|
|
42
|
-
export const u8a64 = u8a.refine((e) => e.length === 64)
|
|
43
|
-
|
|
44
|
-
export const hex20 = hex.refine((e) => e.length === 40)
|
|
45
|
-
export const hex32 = hex.refine((e) => e.length === 64)
|
|
46
|
-
export const hex33 = hex.refine((e) => e.length === 66)
|
|
47
|
-
export const hex64 = hex.refine((e) => e.length === 128)
|
|
48
|
-
|
|
49
|
-
export const bytes = z.union([ hex, u8a ])
|
|
50
|
-
export const byte32 = z.union([ hex32, u8a32 ])
|
|
51
|
-
export const byte33 = z.union([ hex33, u8a33 ])
|
|
52
|
-
export const byte64 = z.union([ hex64, u8a64 ])
|
|
53
|
-
|
|
54
|
-
export const base58 = z.string().regex(/^[1-9A-HJ-NP-Za-km-z]+$/)
|
|
55
|
-
export const base64 = z.string().regex(/^[a-zA-Z0-9+/]+={0,2}$/)
|
|
56
|
-
export const base64url = z.string().regex(/^[a-zA-Z0-9\-_]+={0,2}$/)
|
|
57
|
-
export const bech32 = z.string().regex(/^[a-z]+1[023456789acdefghjklmnpqrstuvwxyz]+$/)
|
package/src/schema/index.ts
DELETED
package/src/schema/taproot.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
import { byte32, uint } from './base.js'
|
|
4
|
-
|
|
5
|
-
export const taptree = z.union([ z.array(byte32), byte32 ])
|
|
6
|
-
|
|
7
|
-
export const config = z.object({
|
|
8
|
-
pubkey : byte32,
|
|
9
|
-
leaves : taptree.array().optional(),
|
|
10
|
-
target : byte32.optional(),
|
|
11
|
-
version : uint.optional(),
|
|
12
|
-
})
|