@vbyte/btc-dev 1.0.9 → 1.0.11

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,8 +1,10 @@
1
1
  import { Buff } from '@vbyte/buff';
2
- import { ECC } from '@vbyte/micro-lib';
2
+ import { Assert, ECC } from '@vbyte/micro-lib';
3
3
  import { sign_segwit_tx, sign_taproot_tx } from '../lib/signer/sign.js';
4
4
  export class TxSigner {
5
5
  constructor(seckey) {
6
+ Assert.ok(Buff.is_bytes(seckey), 'seckey must be a string or bytes');
7
+ Assert.size(seckey, 32, 'seckey must be 32 bytes');
6
8
  this._seckey = Buff.bytes(seckey).hex;
7
9
  }
8
10
  get pubkey() {
@@ -1,14 +1,8 @@
1
1
  import { TransactionInput } from './txin.js';
2
2
  import { TransactionOutput } from './txout.js';
3
- import type { TxData, TxTemplate, TxOutput, TxSize, TxValue, TxInputTemplate } from '../types/index.js';
3
+ import type { TxData, TxTemplate, TxOutput, TxInputTemplate } from '../types/index.js';
4
4
  export declare class Transaction {
5
5
  private readonly _tx;
6
- private _size;
7
- private _hash;
8
- private _txid;
9
- private _value;
10
- private _vin;
11
- private _vout;
12
6
  constructor(txdata?: string | TxData | TxTemplate);
13
7
  get data(): TxData;
14
8
  get hash(): string;
@@ -18,12 +12,10 @@ export declare class Transaction {
18
12
  value: number;
19
13
  };
20
14
  get return(): TxOutput | null;
21
- get size(): TxSize & {
22
- segwit: number;
23
- };
24
- get spends(): TransactionOutput[];
15
+ get size(): import("../types/index.js").TxSize;
16
+ get spends(): TxOutput[];
25
17
  get txid(): string;
26
- get value(): TxValue;
18
+ get value(): import("../types/index.js").TxValue;
27
19
  get version(): number;
28
20
  get vin(): TransactionInput[];
29
21
  get vout(): TransactionOutput[];
@@ -43,9 +35,6 @@ export declare class Transaction {
43
35
  vsize: number;
44
36
  weight: number;
45
37
  };
46
- _update_tx(): void;
47
- _update_vin(): void;
48
- _update_vout(): void;
49
38
  toJSON(): TxData;
50
39
  toString(): string;
51
40
  }
package/dist/class/tx.js CHANGED
@@ -2,24 +2,16 @@ import { Assert } from '@vbyte/micro-lib';
2
2
  import { LocktimeUtil } from '../lib/meta/index.js';
3
3
  import { TransactionInput } from './txin.js';
4
4
  import { TransactionOutput } from './txout.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
+ import { 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';
6
6
  export class Transaction {
7
7
  constructor(txdata = {}) {
8
- this._tx = (typeof txdata !== 'string')
9
- ? parse_tx(txdata)
10
- : decode_tx(txdata);
11
- this._size = this._get_size();
12
- this._hash = get_txhash(this._tx);
13
- this._txid = get_txid(this._tx);
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));
8
+ this._tx = parse_tx(txdata);
17
9
  }
18
10
  get data() {
19
11
  return this._tx;
20
12
  }
21
13
  get hash() {
22
- return this._hash;
14
+ return get_txhash(this._tx);
23
15
  }
24
16
  get locktime() {
25
17
  return {
@@ -32,37 +24,35 @@ export class Transaction {
32
24
  return this._tx.vout.find(txout => is_return_script(txout.script_pk)) || null;
33
25
  }
34
26
  get size() {
35
- return this._size;
27
+ return get_txsize(this._tx);
36
28
  }
37
29
  get spends() {
38
30
  return this._tx.vin
39
31
  .filter(txin => txin.prevout !== null)
40
- .map(txin => new TransactionOutput(txin.prevout));
32
+ .map(txin => txin.prevout);
41
33
  }
42
34
  get txid() {
43
- return this._txid;
35
+ return get_txid(this._tx);
44
36
  }
45
37
  get value() {
46
- return this._value;
38
+ return get_tx_value(this._tx);
47
39
  }
48
40
  get version() {
49
41
  return this._tx.version;
50
42
  }
51
43
  get vin() {
52
- return this._vin;
44
+ return this._tx.vin.map((_, idx) => new TransactionInput(this, idx));
53
45
  }
54
46
  get vout() {
55
- return this._vout;
47
+ return this._tx.vout.map((_, idx) => new TransactionOutput(this, idx));
56
48
  }
57
49
  add_vin(tx_input) {
58
50
  const txin = create_tx_input(tx_input);
59
51
  this._tx.vin.push(txin);
60
- this._update_vin();
61
52
  }
62
53
  add_vout(tx_output) {
63
54
  const txout = create_tx_output(tx_output);
64
55
  this._tx.vout.push(txout);
65
- this._update_vout();
66
56
  }
67
57
  insert_vin(index, tx_input) {
68
58
  Assert.ok(index >= 0 && index <= this._tx.vin.length, 'input goes out of bounds');
@@ -73,7 +63,6 @@ export class Transaction {
73
63
  else {
74
64
  this._tx.vin.splice(index, 0, txin);
75
65
  }
76
- this._update_vin();
77
66
  }
78
67
  insert_vout(index, tx_output) {
79
68
  Assert.ok(index >= 0 && index <= this._tx.vout.length, 'output goes out of bounds');
@@ -84,17 +73,14 @@ export class Transaction {
84
73
  else {
85
74
  this._tx.vout.splice(index, 0, txout);
86
75
  }
87
- this._update_vout();
88
76
  }
89
77
  remove_vin(index) {
90
78
  Assert.ok(this._tx.vin.at(index) !== undefined, 'input does not exist at index');
91
79
  this._tx.vin.splice(index, 1);
92
- this._update_vin();
93
80
  }
94
81
  remove_vout(index) {
95
82
  Assert.ok(this._tx.vout.at(index) !== undefined, 'output does not exist at index');
96
83
  this._tx.vout.splice(index, 1);
97
- this._update_vout();
98
84
  }
99
85
  _get_size() {
100
86
  return {
@@ -105,20 +91,6 @@ export class Transaction {
105
91
  witness: this.vin.reduce((acc, txin) => acc + (txin.witness?.size.total ?? 0), 0)
106
92
  };
107
93
  }
108
- _update_tx() {
109
- this._size = this._get_size();
110
- this._hash = get_txhash(this._tx);
111
- this._txid = get_txid(this._tx);
112
- this._value = get_tx_value(this._tx);
113
- }
114
- _update_vin() {
115
- this._vin = this._tx.vin.map(txin => new TransactionInput(txin));
116
- this._update_tx();
117
- }
118
- _update_vout() {
119
- this._vout = this._tx.vout.map(txout => new TransactionOutput(txout));
120
- this._update_tx();
121
- }
122
94
  toJSON() { return this.data; }
123
95
  toString() { return JSON.stringify(this.data); }
124
96
  }
@@ -1,14 +1,16 @@
1
- import { TransactionOutput } from './txout.js';
1
+ import { Transaction } from './tx.js';
2
2
  import { TransactionWitness } from './witness.js';
3
- import type { TxInput } from '../types/index.js';
3
+ import type { TxInput, TxOutput } from '../types/index.js';
4
4
  export declare class TransactionInput {
5
- private readonly _txin;
6
- constructor(txin: TxInput);
5
+ private readonly _tx;
6
+ private readonly _index;
7
+ constructor(transaction: Transaction, index: number);
7
8
  get coinbase(): string | null;
8
9
  get data(): TxInput;
9
10
  get has_prevout(): boolean;
11
+ get index(): number;
10
12
  get is_coinbase(): boolean;
11
- get prevout(): TransactionOutput | null;
13
+ get prevout(): TxOutput | null;
12
14
  get script_sig(): {
13
15
  asm: string[];
14
16
  hex: string;
@@ -1,56 +1,60 @@
1
+ import { Assert } from '@vbyte/micro-lib';
1
2
  import { decode_script } from '../lib/script/index.js';
2
3
  import { SequenceUtil } from '../lib/meta/index.js';
3
- import { TransactionOutput } from './txout.js';
4
4
  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
- constructor(txin) {
8
- this._txin = txin;
7
+ constructor(transaction, index) {
8
+ this._tx = transaction;
9
+ this._index = index;
9
10
  }
10
11
  get coinbase() {
11
- return this._txin.coinbase;
12
+ return this.data.coinbase;
12
13
  }
13
14
  get data() {
14
- return this._txin;
15
+ const txin = this._tx.data.vin.at(this.index);
16
+ Assert.exists(txin, 'txin not found');
17
+ return txin;
15
18
  }
16
19
  get has_prevout() {
17
- return this._txin.prevout !== null;
20
+ return this.data.prevout !== null;
21
+ }
22
+ get index() {
23
+ return this._index;
18
24
  }
19
25
  get is_coinbase() {
20
- return this._txin.coinbase !== null;
26
+ return this.data.coinbase !== null;
21
27
  }
22
28
  get prevout() {
23
- return this._txin.prevout
24
- ? new TransactionOutput(this._txin.prevout)
25
- : null;
29
+ return this.data.prevout;
26
30
  }
27
31
  get script_sig() {
28
- if (this._txin.script_sig === null)
32
+ if (this.data.script_sig === null)
29
33
  return null;
30
34
  return {
31
- asm: decode_script(this._txin.script_sig),
32
- hex: this._txin.script_sig
35
+ asm: decode_script(this.data.script_sig),
36
+ hex: this.data.script_sig
33
37
  };
34
38
  }
35
39
  get sequence() {
36
40
  return {
37
- hex: encode_txin_sequence(this._txin.sequence).hex,
38
- data: SequenceUtil.decode(this._txin.sequence),
39
- value: this._txin.sequence
41
+ hex: encode_txin_sequence(this.data.sequence).hex,
42
+ data: SequenceUtil.decode(this.data.sequence),
43
+ value: this.data.sequence
40
44
  };
41
45
  }
42
46
  get size() {
43
- return get_txin_size(this._txin);
47
+ return get_txin_size(this.data);
44
48
  }
45
49
  get txid() {
46
- return this._txin.txid;
50
+ return this.data.txid;
47
51
  }
48
52
  get vout() {
49
- return this._txin.vout;
53
+ return this.data.vout;
50
54
  }
51
55
  get witness() {
52
- return this._txin.witness.length > 0
53
- ? new TransactionWitness(this._txin.witness)
56
+ return this.data.witness.length > 0
57
+ ? new TransactionWitness(this._tx, this.index)
54
58
  : null;
55
59
  }
56
60
  toJSON() { return this.data; }
@@ -1,8 +1,11 @@
1
+ import { Transaction } from './tx.js';
1
2
  import type { TxOutput } from '../types/index.js';
2
3
  export declare class TransactionOutput {
3
- private readonly _txout;
4
- constructor(txout: TxOutput);
4
+ private readonly _tx;
5
+ private readonly _index;
6
+ constructor(transaction: Transaction, index: number);
5
7
  get data(): TxOutput;
8
+ get index(): number;
6
9
  get script_pk(): {
7
10
  hex: string;
8
11
  asm: string[];
@@ -1,29 +1,36 @@
1
+ import { Assert } from '@vbyte/micro-lib';
1
2
  import { decode_script } from '../lib/script/index.js';
2
3
  import { get_txout_size, get_vout_type, get_vout_version } from '../lib/tx/index.js';
3
4
  export class TransactionOutput {
4
- constructor(txout) {
5
- this._txout = txout;
5
+ constructor(transaction, index) {
6
+ this._tx = transaction;
7
+ this._index = index;
6
8
  }
7
9
  get data() {
8
- return this._txout;
10
+ const txout = this._tx.data.vout.at(this.index);
11
+ Assert.exists(txout, 'txout not found');
12
+ return txout;
13
+ }
14
+ get index() {
15
+ return this._index;
9
16
  }
10
17
  get script_pk() {
11
18
  return {
12
- hex: this._txout.script_pk,
13
- asm: decode_script(this._txout.script_pk)
19
+ hex: this.data.script_pk,
20
+ asm: decode_script(this.data.script_pk)
14
21
  };
15
22
  }
16
23
  get size() {
17
- return get_txout_size(this._txout);
24
+ return get_txout_size(this.data);
18
25
  }
19
26
  get type() {
20
- return get_vout_type(this._txout.script_pk);
27
+ return get_vout_type(this.data.script_pk);
21
28
  }
22
29
  get value() {
23
- return this._txout.value;
30
+ return this.data.value;
24
31
  }
25
32
  get version() {
26
- return get_vout_version(this._txout.script_pk);
33
+ return get_vout_version(this.data.script_pk);
27
34
  }
28
35
  toJSON() { return this.data; }
29
36
  toString() { return JSON.stringify(this.data); }
@@ -1,10 +1,9 @@
1
- import { Bytes } from '@vbyte/buff';
1
+ import { Transaction } from './tx.js';
2
2
  import type { ScriptField, WitnessData, WitnessSize, WitnessType } from '../types/index.js';
3
3
  export declare class TransactionWitness {
4
- private readonly _elems;
5
- private _data;
6
- private _size;
7
- constructor(witness: Bytes[]);
4
+ private readonly _tx;
5
+ private readonly _index;
6
+ constructor(transaction: Transaction, index: number);
8
7
  get annex(): string | null;
9
8
  get cblock(): string | null;
10
9
  get data(): WitnessData;
@@ -14,10 +13,6 @@ export declare class TransactionWitness {
14
13
  get stack(): string[];
15
14
  get type(): WitnessType;
16
15
  get version(): number | null;
17
- _update(): void;
18
- add(elem: Bytes): void;
19
- insert(index: number, elem: Bytes): void;
20
- remove(index: number): void;
21
16
  toJSON(): WitnessData;
22
17
  toString(): string;
23
18
  }
@@ -1,66 +1,45 @@
1
- import { Buff } from '@vbyte/buff';
2
1
  import { Assert } from '@vbyte/micro-lib';
3
2
  import { decode_script } from '../lib/script/index.js';
4
- import { parse_witness, get_witness_size, } from '../lib/witness/index.js';
3
+ import { parse_witness, get_witness_size } from '../lib/witness/index.js';
5
4
  export class TransactionWitness {
6
- constructor(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);
5
+ constructor(transaction, index) {
6
+ this._tx = transaction;
7
+ this._index = index;
10
8
  }
11
9
  get annex() {
12
- return this._data.annex;
10
+ return this.data.annex;
13
11
  }
14
12
  get cblock() {
15
- return this._data.cblock;
13
+ return this.data.cblock;
16
14
  }
17
15
  get data() {
18
- return this._data;
16
+ return parse_witness(this.stack);
19
17
  }
20
18
  get params() {
21
- return this._data.params;
19
+ return this.data.params;
22
20
  }
23
21
  get script() {
24
- if (this._data.script === null)
22
+ if (this.data.script === null)
25
23
  return null;
26
24
  return {
27
- hex: this._data.script,
28
- asm: decode_script(this._data.script)
25
+ hex: this.data.script,
26
+ asm: decode_script(this.data.script)
29
27
  };
30
28
  }
31
29
  get size() {
32
- return this._size;
30
+ return get_witness_size(this.stack);
33
31
  }
34
32
  get stack() {
35
- return this._elems.map(e => e.hex);
33
+ const txin = this._tx.data.vin.at(this._index);
34
+ Assert.exists(txin, 'txin not found at index ' + this._index);
35
+ Assert.exists(txin.witness, 'witness not found at index ' + this._index);
36
+ return txin.witness;
36
37
  }
37
38
  get type() {
38
- return this._data.type;
39
+ return this.data.type;
39
40
  }
40
41
  get 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();
60
- }
61
- remove(index) {
62
- this._elems.splice(index, 1);
63
- this._update();
42
+ return this.data.version;
64
43
  }
65
44
  toJSON() { return this.data; }
66
45
  toString() { return JSON.stringify(this.data); }
@@ -8,7 +8,7 @@ const DEFAULT_CONFIG = {
8
8
  };
9
9
  export function decode_tx(txbytes, options = {}) {
10
10
  const config = { ...DEFAULT_CONFIG, ...options };
11
- Assert.is_bytes(txbytes, 'txbytes must be hex or a unit array');
11
+ Assert.is_bytes(txbytes, 'transaction must be hex or a byte-array');
12
12
  const stream = new Stream(txbytes);
13
13
  const version = read_version(stream);
14
14
  const has_witness = (config.segwit)
@@ -5,7 +5,7 @@ const WIT_FLAG_BYTES = 2;
5
5
  export function get_vsize(bytes) {
6
6
  const weight = Buff.bytes(bytes).length;
7
7
  const remain = (weight % 4 > 0) ? 1 : 0;
8
- return Math.floor(weight / 4) + remain;
8
+ return Math.ceil(weight / 4) + remain;
9
9
  }
10
10
  export function get_txsize(txdata) {
11
11
  const json = parse_tx(txdata);
@@ -13,7 +13,7 @@ export function get_txsize(txdata) {
13
13
  const total = encode_tx(json, true).length;
14
14
  const weight = base * 3 + total;
15
15
  const remain = (weight % 4 > 0) ? 1 : 0;
16
- const vsize = Math.floor(weight / 4) + remain;
16
+ const vsize = Math.ceil(weight / 4) + remain;
17
17
  return { base, total, vsize, weight };
18
18
  }
19
19
  export function get_vin_size(vin) {
@@ -1,3 +1,4 @@
1
1
  import { Bytes } from '@vbyte/buff';
2
2
  import type { WitnessSize } from '../../types/index.js';
3
3
  export declare function get_witness_size(witness: Bytes[]): WitnessSize;
4
+ export declare function assert_witness(witness: unknown): asserts witness is Bytes[];
@@ -1,4 +1,5 @@
1
1
  import { Buff } from '@vbyte/buff';
2
+ import { Assert } from '@vbyte/micro-lib';
2
3
  const WIT_LENGTH_BYTE = 1;
3
4
  export function get_witness_size(witness) {
4
5
  const stack = witness.map(e => Buff.bytes(e));
@@ -6,3 +7,7 @@ export function get_witness_size(witness) {
6
7
  const vsize = Math.ceil(WIT_LENGTH_BYTE + size / 4);
7
8
  return { total: size, vsize };
8
9
  }
10
+ export function assert_witness(witness) {
11
+ Assert.ok(Array.isArray(witness), 'witness must be an array');
12
+ Assert.ok(witness.every(e => Buff.is_bytes(e)), 'witness must be an array of strings or bytes');
13
+ }