@vbyte/btc-dev 1.0.6 → 1.0.8

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.
@@ -1,14 +1,15 @@
1
1
  import { TransactionInput } from './txin.js';
2
2
  import { TransactionOutput } from './txout.js';
3
- import type { TxData, TxTemplate, TxValue, TransactionData } from '../types/index.js';
3
+ import type { TxData, TxTemplate, TransactionData, TxOutput, TxSize, TxValue, TxInputTemplate } from '../types/index.js';
4
4
  export declare class Transaction {
5
- private readonly _size;
6
5
  private readonly _tx;
7
- private readonly _hash;
8
- private readonly _value;
9
- private readonly _vin;
10
- private readonly _vout;
11
- constructor(txdata: string | TxData | TxTemplate);
6
+ private _size;
7
+ private _hash;
8
+ private _txid;
9
+ private _value;
10
+ private _vin;
11
+ private _vout;
12
+ constructor(txdata?: string | TxData | TxTemplate);
12
13
  get data(): TransactionData;
13
14
  get hash(): string;
14
15
  get locktime(): {
@@ -16,16 +17,9 @@ export declare class Transaction {
16
17
  data: import("../types/index.js").LocktimeData | null;
17
18
  value: number;
18
19
  };
19
- get return(): import("../types/index.js").TxOutput | null;
20
- get size(): {
20
+ get return(): TxOutput | null;
21
+ get size(): TxSize & {
21
22
  segwit: number;
22
- vin: number;
23
- vout: number;
24
- witness: number;
25
- base: number;
26
- real: number;
27
- weight: number;
28
- vsize: number;
29
23
  };
30
24
  get spends(): TransactionOutput[];
31
25
  get txid(): string;
@@ -33,6 +27,25 @@ export declare class Transaction {
33
27
  get version(): number;
34
28
  get vin(): TransactionInput[];
35
29
  get vout(): TransactionOutput[];
30
+ add_vin(tx_input: TxInputTemplate): void;
31
+ add_vout(tx_output: TxOutput): void;
32
+ insert_vin(index: number, tx_input: TxInputTemplate): void;
33
+ insert_vout(index: number, tx_output: TxOutput): void;
34
+ remove_vin(index: number): void;
35
+ remove_vout(index: number): void;
36
+ _get_size(): {
37
+ segwit: number;
38
+ vin: number;
39
+ vout: number;
40
+ witness: number;
41
+ base: number;
42
+ total: number;
43
+ weight: number;
44
+ vsize: number;
45
+ };
46
+ _update_tx(): void;
47
+ _update_vin(): void;
48
+ _update_vout(): void;
36
49
  toJSON(): TransactionData;
37
50
  toString(): string;
38
51
  }
package/dist/class/tx.js CHANGED
@@ -1,17 +1,19 @@
1
+ import { Assert } from '@vbyte/micro-lib';
1
2
  import { LocktimeUtil } from '../lib/meta/index.js';
2
3
  import { TransactionInput } from './txin.js';
3
4
  import { TransactionOutput } from './txout.js';
4
- import { decode_tx, get_txid, is_return_script, parse_tx, get_txsize, get_tx_value, get_txhash, encode_tx_locktime, } from '../lib/tx/index.js';
5
+ import { decode_tx, get_txid, is_return_script, parse_tx, get_txsize, get_tx_value, get_txhash, encode_tx_locktime, create_tx_input, create_tx_output, } from '../lib/tx/index.js';
5
6
  export class Transaction {
6
- constructor(txdata) {
7
+ constructor(txdata = {}) {
7
8
  this._tx = (typeof txdata !== 'string')
8
9
  ? parse_tx(txdata)
9
10
  : decode_tx(txdata);
10
- this._vin = this._tx.vin.map(txin => new TransactionInput(txin));
11
- this._vout = this._tx.vout.map(txout => new TransactionOutput(txout));
12
- this._size = get_txsize(this._tx);
11
+ this._size = this._get_size();
13
12
  this._hash = get_txhash(this._tx);
13
+ this._txid = get_txid(this._tx);
14
14
  this._value = get_tx_value(this._tx);
15
+ this._vin = this._tx.vin.map(txin => new TransactionInput(txin));
16
+ this._vout = this._tx.vout.map(txout => new TransactionOutput(txout));
15
17
  }
16
18
  get data() {
17
19
  return {
@@ -41,13 +43,7 @@ export class Transaction {
41
43
  return this._tx.vout.find(txout => is_return_script(txout.script_pk)) || null;
42
44
  }
43
45
  get size() {
44
- return {
45
- ...this._size,
46
- segwit: this._vin.reduce((acc, txin) => acc + (txin.witness?.vsize ?? 0), 0),
47
- vin: this._vin.reduce((acc, txin) => acc + txin.size, 0),
48
- vout: this._vout.reduce((acc, txout) => acc + txout.size, 0),
49
- witness: this._vin.reduce((acc, txin) => acc + (txin.witness?.size ?? 0), 0)
50
- };
46
+ return this._size;
51
47
  }
52
48
  get spends() {
53
49
  return this._tx.vin
@@ -55,7 +51,7 @@ export class Transaction {
55
51
  .map(txin => new TransactionOutput(txin.prevout));
56
52
  }
57
53
  get txid() {
58
- return get_txid(this._tx);
54
+ return this._txid;
59
55
  }
60
56
  get value() {
61
57
  return this._value;
@@ -69,6 +65,71 @@ export class Transaction {
69
65
  get vout() {
70
66
  return this._vout;
71
67
  }
68
+ add_vin(tx_input) {
69
+ const txin = create_tx_input(tx_input);
70
+ this._tx.vin.push(txin);
71
+ this._update_vin();
72
+ }
73
+ add_vout(tx_output) {
74
+ const txout = create_tx_output(tx_output);
75
+ this._tx.vout.push(txout);
76
+ this._update_vout();
77
+ }
78
+ insert_vin(index, tx_input) {
79
+ Assert.ok(index >= 0 && index <= this._tx.vin.length, 'input goes out of bounds');
80
+ const txin = create_tx_input(tx_input);
81
+ if (index === this._tx.vin.length) {
82
+ this._tx.vin.push(txin);
83
+ }
84
+ else {
85
+ this._tx.vin.splice(index, 0, txin);
86
+ }
87
+ this._update_vin();
88
+ }
89
+ insert_vout(index, tx_output) {
90
+ Assert.ok(index >= 0 && index <= this._tx.vout.length, 'output goes out of bounds');
91
+ const txout = create_tx_output(tx_output);
92
+ if (index === this._tx.vout.length) {
93
+ this._tx.vout.push(txout);
94
+ }
95
+ else {
96
+ this._tx.vout.splice(index, 0, txout);
97
+ }
98
+ this._update_vout();
99
+ }
100
+ remove_vin(index) {
101
+ Assert.ok(this._tx.vin.at(index) !== undefined, 'input does not exist at index');
102
+ this._tx.vin.splice(index, 1);
103
+ this._update_vin();
104
+ }
105
+ remove_vout(index) {
106
+ Assert.ok(this._tx.vout.at(index) !== undefined, 'output does not exist at index');
107
+ this._tx.vout.splice(index, 1);
108
+ this._update_vout();
109
+ }
110
+ _get_size() {
111
+ return {
112
+ ...get_txsize(this._tx),
113
+ segwit: this.vin.reduce((acc, txin) => acc + (txin.witness?.size.vsize ?? 0), 0),
114
+ vin: this.vin.reduce((acc, txin) => acc + txin.size, 0),
115
+ vout: this.vout.reduce((acc, txout) => acc + txout.size, 0),
116
+ witness: this.vin.reduce((acc, txin) => acc + (txin.witness?.size.total ?? 0), 0)
117
+ };
118
+ }
119
+ _update_tx() {
120
+ this._size = this._get_size();
121
+ this._hash = get_txhash(this._tx);
122
+ this._txid = get_txid(this._tx);
123
+ this._value = get_tx_value(this._tx);
124
+ }
125
+ _update_vin() {
126
+ this._vin = this._tx.vin.map(txin => new TransactionInput(txin));
127
+ this._update_tx();
128
+ }
129
+ _update_vout() {
130
+ this._vout = this._tx.vout.map(txout => new TransactionOutput(txout));
131
+ this._update_tx();
132
+ }
72
133
  toJSON() { return this.data; }
73
134
  toString() { return JSON.stringify(this.data); }
74
135
  }
@@ -2,9 +2,7 @@ import { TransactionOutput } from './txout.js';
2
2
  import { TransactionWitness } from './witness.js';
3
3
  import type { TxInput, TransactionInputData } from '../types/index.js';
4
4
  export declare class TransactionInput {
5
- private readonly _size;
6
5
  private readonly _txin;
7
- private readonly _witness;
8
6
  constructor(txin: TxInput);
9
7
  get coinbase(): string | null;
10
8
  get data(): TransactionInputData;
@@ -5,11 +5,7 @@ import { TransactionWitness } from './witness.js';
5
5
  import { encode_txin_sequence, get_txin_size, } from '../lib/tx/index.js';
6
6
  export class TransactionInput {
7
7
  constructor(txin) {
8
- this._size = get_txin_size(txin);
9
8
  this._txin = txin;
10
- this._witness = txin.witness.length > 0
11
- ? new TransactionWitness(txin.witness)
12
- : null;
13
9
  }
14
10
  get coinbase() {
15
11
  return this._txin.coinbase;
@@ -53,7 +49,7 @@ export class TransactionInput {
53
49
  };
54
50
  }
55
51
  get size() {
56
- return this._size;
52
+ return get_txin_size(this._txin);
57
53
  }
58
54
  get txid() {
59
55
  return this._txin.txid;
@@ -62,7 +58,9 @@ export class TransactionInput {
62
58
  return this._txin.vout;
63
59
  }
64
60
  get witness() {
65
- return this._witness;
61
+ return this._txin.witness.length > 0
62
+ ? new TransactionWitness(this._txin.witness)
63
+ : null;
66
64
  }
67
65
  toJSON() { return this.data; }
68
66
  toString() { return JSON.stringify(this.data); }
@@ -1,7 +1,5 @@
1
1
  import type { TxOutput, TransactionOutputData } from '../types/index.js';
2
2
  export declare class TransactionOutput {
3
- private readonly _info;
4
- private readonly _size;
5
3
  private readonly _txout;
6
4
  constructor(txout: TxOutput);
7
5
  get data(): TransactionOutputData;
@@ -1,9 +1,7 @@
1
1
  import { decode_script } from '../lib/script/index.js';
2
- import { get_txout_size, get_vout_info } from '../lib/tx/index.js';
2
+ import { get_txout_size, get_vout_type, get_vout_version } from '../lib/tx/index.js';
3
3
  export class TransactionOutput {
4
4
  constructor(txout) {
5
- this._info = get_vout_info(txout);
6
- this._size = get_txout_size(txout);
7
5
  this._txout = txout;
8
6
  }
9
7
  get data() {
@@ -22,16 +20,16 @@ export class TransactionOutput {
22
20
  };
23
21
  }
24
22
  get size() {
25
- return this._size;
23
+ return get_txout_size(this._txout);
26
24
  }
27
25
  get type() {
28
- return this._info.type;
26
+ return get_vout_type(this._txout.script_pk);
29
27
  }
30
28
  get value() {
31
29
  return this._txout.value;
32
30
  }
33
31
  get version() {
34
- return this._info.version;
32
+ return get_vout_version(this._txout.script_pk);
35
33
  }
36
34
  toJSON() { return this.data; }
37
35
  toString() { return JSON.stringify(this.data); }
@@ -1,20 +1,23 @@
1
1
  import { Bytes } from '@vbyte/buff';
2
- import type { ScriptField, WitnessField, WitnessType } from '../types/index.js';
2
+ import type { ScriptField, WitnessData, WitnessSize, WitnessType } from '../types/index.js';
3
3
  export declare class TransactionWitness {
4
- private readonly _data;
5
- private readonly _meta;
6
- private readonly _size;
4
+ private readonly _elems;
5
+ private _data;
6
+ private _size;
7
7
  constructor(witness: Bytes[]);
8
8
  get annex(): string | null;
9
9
  get cblock(): string | null;
10
- get data(): WitnessField;
10
+ get data(): WitnessData;
11
11
  get params(): string[];
12
12
  get script(): ScriptField | null;
13
- get size(): number;
13
+ get size(): WitnessSize;
14
14
  get stack(): string[];
15
15
  get type(): WitnessType;
16
16
  get version(): number | null;
17
- get vsize(): number;
18
- toJSON(): WitnessField;
17
+ _update(): void;
18
+ add(elem: Bytes): void;
19
+ insert(index: number, elem: Bytes): void;
20
+ remove(index: number): void;
21
+ toJSON(): WitnessData;
19
22
  toString(): string;
20
23
  }
@@ -1,56 +1,66 @@
1
1
  import { Buff } from '@vbyte/buff';
2
+ import { Assert } from '@vbyte/micro-lib';
2
3
  import { decode_script } from '../lib/script/index.js';
3
- import { parse_witness_data, get_witness_size, } from '../lib/witness/index.js';
4
+ import { parse_witness, get_witness_size, } from '../lib/witness/index.js';
4
5
  export class TransactionWitness {
5
6
  constructor(witness) {
6
- this._data = witness.map(e => Buff.bytes(e));
7
- this._meta = parse_witness_data(witness);
8
- this._size = get_witness_size(witness);
7
+ this._elems = witness.map(e => Buff.bytes(e));
8
+ this._data = parse_witness(this._elems);
9
+ this._size = get_witness_size(this._elems);
9
10
  }
10
11
  get annex() {
11
- return this._meta.annex;
12
+ return this._data.annex;
12
13
  }
13
14
  get cblock() {
14
- return this._meta.cblock;
15
+ return this._data.cblock;
15
16
  }
16
17
  get data() {
17
- return {
18
- annex: this.annex,
19
- cblock: this.cblock,
20
- params: this.params,
21
- script: this.script,
22
- size: this.size,
23
- stack: this.stack,
24
- type: this.type,
25
- version: this.version,
26
- vsize: this.vsize
27
- };
18
+ return this._data;
28
19
  }
29
20
  get params() {
30
- return this._meta.params;
21
+ return this._data.params;
31
22
  }
32
23
  get script() {
33
- if (this._meta.script === null)
24
+ if (this._data.script === null)
34
25
  return null;
35
26
  return {
36
- hex: this._meta.script,
37
- asm: decode_script(this._meta.script)
27
+ hex: this._data.script,
28
+ asm: decode_script(this._data.script)
38
29
  };
39
30
  }
40
31
  get size() {
41
- return this._size.size;
32
+ return this._size;
42
33
  }
43
34
  get stack() {
44
- return this._data.map(e => e.hex);
35
+ return this._elems.map(e => e.hex);
45
36
  }
46
37
  get type() {
47
- return this._meta.type;
38
+ return this._data.type;
48
39
  }
49
40
  get version() {
50
- return this._meta.version;
41
+ return this._data.version;
42
+ }
43
+ _update() {
44
+ this._data = parse_witness(this._elems);
45
+ this._size = get_witness_size(this._elems);
46
+ }
47
+ add(elem) {
48
+ this._elems.push(Buff.bytes(elem));
49
+ this._update();
50
+ }
51
+ insert(index, elem) {
52
+ Assert.ok(index >= 0 && index <= this._elems.length, 'index out of bounds');
53
+ if (index === this._elems.length) {
54
+ this._elems.push(Buff.bytes(elem));
55
+ }
56
+ else {
57
+ this._elems.splice(index, 0, Buff.bytes(elem));
58
+ }
59
+ this._update();
51
60
  }
52
- get vsize() {
53
- return this._size.vsize;
61
+ remove(index) {
62
+ this._elems.splice(index, 1);
63
+ this._update();
54
64
  }
55
65
  toJSON() { return this.data; }
56
66
  toString() { return JSON.stringify(this.data); }
@@ -1,9 +1,9 @@
1
1
  import { Buff, Stream } from '@vbyte/buff';
2
2
  import { Assert, ECC } from '@vbyte/micro-lib';
3
- import { parse_witness_data } from '../../lib/witness/parse.js';
3
+ import { parse_witness } from '../../lib/witness/parse.js';
4
4
  import { encode_tapbranch, encode_tapscript, encode_taptweak, } from './encode.js';
5
5
  export function parse_taproot_witness(witness) {
6
- const { cblock, params, script } = parse_witness_data(witness);
6
+ const { cblock, params, script } = parse_witness(witness);
7
7
  Assert.exists(cblock, 'cblock is null');
8
8
  Assert.exists(script, 'script is null');
9
9
  const cblk = parse_cblock(cblock);
@@ -10,11 +10,11 @@ export function get_vsize(bytes) {
10
10
  export function get_txsize(txdata) {
11
11
  const json = parse_tx(txdata);
12
12
  const base = encode_tx(json, false).length;
13
- const size = encode_tx(json, true).length;
14
- const weight = base * 3 + size;
13
+ const total = encode_tx(json, true).length;
14
+ const weight = base * 3 + total;
15
15
  const remain = (weight % 4 > 0) ? 1 : 0;
16
16
  const vsize = Math.floor(weight / 4) + remain;
17
- return { base, real: size, vsize, weight };
17
+ return { base, total, vsize, weight };
18
18
  }
19
19
  export function get_vin_size(vin) {
20
20
  const bytes = encode_tx_inputs(vin);
@@ -1,3 +1,3 @@
1
1
  import { Bytes } from '@vbyte/buff';
2
- import type { WitnessInfo } from '../../types/index.js';
3
- export declare function parse_witness_data(witness: Bytes[]): WitnessInfo;
2
+ import type { WitnessData } from '../../types/index.js';
3
+ export declare function parse_witness(witness: Bytes[]): WitnessData;
@@ -1,8 +1,9 @@
1
1
  import { Buff } from '@vbyte/buff';
2
2
  import { is_valid_script } from '../../lib/script/decode.js';
3
3
  import { TAPLEAF_VERSIONS } from '../../const.js';
4
- export function parse_witness_data(witness) {
4
+ export function parse_witness(witness) {
5
5
  const elems = witness.map(e => Buff.bytes(e));
6
+ const stack = witness.map(e => Buff.bytes(e).hex);
6
7
  const annex = parse_annex_data(elems);
7
8
  if (annex !== null)
8
9
  elems.pop();
@@ -15,7 +16,7 @@ export function parse_witness_data(witness) {
15
16
  if (script !== null)
16
17
  elems.pop();
17
18
  const params = elems.map(e => e.hex);
18
- return { annex, cblock, params, script, type, version };
19
+ return { annex, cblock, params, script, stack, type, version };
19
20
  }
20
21
  function parse_annex_data(data) {
21
22
  let elem = data.at(-1);
@@ -4,5 +4,5 @@ export function get_witness_size(witness) {
4
4
  const stack = witness.map(e => Buff.bytes(e));
5
5
  const size = stack.reduce((prev, next) => prev + next.length, 0);
6
6
  const vsize = Math.ceil(WIT_LENGTH_BYTE + size / 4);
7
- return { size, vsize };
7
+ return { total: size, vsize };
8
8
  }