@opcat-labs/bip174 1.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/LICENSE +21 -0
- package/README.md +109 -0
- package/package.json +66 -0
- package/src/cjs/lib/combiner/index.js +67 -0
- package/src/cjs/lib/converter/global/globalXpub.js +83 -0
- package/src/cjs/lib/converter/global/unsignedTx.js +10 -0
- package/src/cjs/lib/converter/index.js +72 -0
- package/src/cjs/lib/converter/input/finalScriptSig.js +36 -0
- package/src/cjs/lib/converter/input/finalScriptWitness.js +36 -0
- package/src/cjs/lib/converter/input/nonWitnessUtxo.js +35 -0
- package/src/cjs/lib/converter/input/opcatUtxo.js +74 -0
- package/src/cjs/lib/converter/input/partialSig.js +74 -0
- package/src/cjs/lib/converter/input/porCommitment.js +36 -0
- package/src/cjs/lib/converter/input/sighashType.js +38 -0
- package/src/cjs/lib/converter/input/tapKeySig.js +36 -0
- package/src/cjs/lib/converter/input/tapLeafScript.js +56 -0
- package/src/cjs/lib/converter/input/tapMerkleRoot.js +36 -0
- package/src/cjs/lib/converter/input/tapScriptSig.js +59 -0
- package/src/cjs/lib/converter/input/witnessUtxo.js +53 -0
- package/src/cjs/lib/converter/output/tapTree.js +60 -0
- package/src/cjs/lib/converter/shared/bip32Derivation.js +84 -0
- package/src/cjs/lib/converter/shared/checkPubkey.js +25 -0
- package/src/cjs/lib/converter/shared/redeemScript.js +41 -0
- package/src/cjs/lib/converter/shared/tapBip32Derivation.js +55 -0
- package/src/cjs/lib/converter/shared/tapInternalKey.js +41 -0
- package/src/cjs/lib/converter/shared/witnessScript.js +41 -0
- package/src/cjs/lib/converter/tools.js +45 -0
- package/src/cjs/lib/interfaces.js +2 -0
- package/src/cjs/lib/parser/fromBuffer.js +325 -0
- package/src/cjs/lib/parser/index.js +7 -0
- package/src/cjs/lib/parser/toBuffer.js +69 -0
- package/src/cjs/lib/psbt.js +145 -0
- package/src/cjs/lib/typeFields.js +64 -0
- package/src/cjs/lib/utils.js +141 -0
- package/src/esm/lib/combiner/index.d.ts +2 -0
- package/src/esm/lib/combiner/index.js +57 -0
- package/src/esm/lib/converter/global/globalXpub.d.ts +6 -0
- package/src/esm/lib/converter/global/globalXpub.js +70 -0
- package/src/esm/lib/converter/global/unsignedTx.d.ts +2 -0
- package/src/esm/lib/converter/global/unsignedTx.js +7 -0
- package/src/esm/lib/converter/index.d.ts +110 -0
- package/src/esm/lib/converter/index.js +61 -0
- package/src/esm/lib/converter/input/finalScriptSig.d.ts +6 -0
- package/src/esm/lib/converter/input/finalScriptSig.js +23 -0
- package/src/esm/lib/converter/input/finalScriptWitness.d.ts +6 -0
- package/src/esm/lib/converter/input/finalScriptWitness.js +23 -0
- package/src/esm/lib/converter/input/nonWitnessUtxo.d.ts +6 -0
- package/src/esm/lib/converter/input/nonWitnessUtxo.js +22 -0
- package/src/esm/lib/converter/input/opcatUtxo.d.ts +6 -0
- package/src/esm/lib/converter/input/opcatUtxo.js +61 -0
- package/src/esm/lib/converter/input/partialSig.d.ts +6 -0
- package/src/esm/lib/converter/input/partialSig.js +61 -0
- package/src/esm/lib/converter/input/porCommitment.d.ts +6 -0
- package/src/esm/lib/converter/input/porCommitment.js +23 -0
- package/src/esm/lib/converter/input/sighashType.d.ts +6 -0
- package/src/esm/lib/converter/input/sighashType.js +25 -0
- package/src/esm/lib/converter/input/tapKeySig.d.ts +6 -0
- package/src/esm/lib/converter/input/tapKeySig.js +23 -0
- package/src/esm/lib/converter/input/tapLeafScript.d.ts +6 -0
- package/src/esm/lib/converter/input/tapLeafScript.js +43 -0
- package/src/esm/lib/converter/input/tapMerkleRoot.d.ts +6 -0
- package/src/esm/lib/converter/input/tapMerkleRoot.js +23 -0
- package/src/esm/lib/converter/input/tapScriptSig.d.ts +6 -0
- package/src/esm/lib/converter/input/tapScriptSig.js +46 -0
- package/src/esm/lib/converter/input/witnessUtxo.d.ts +6 -0
- package/src/esm/lib/converter/input/witnessUtxo.js +40 -0
- package/src/esm/lib/converter/output/tapTree.d.ts +6 -0
- package/src/esm/lib/converter/output/tapTree.js +47 -0
- package/src/esm/lib/converter/shared/bip32Derivation.d.ts +8 -0
- package/src/esm/lib/converter/shared/bip32Derivation.js +74 -0
- package/src/esm/lib/converter/shared/checkPubkey.d.ts +2 -0
- package/src/esm/lib/converter/shared/checkPubkey.js +15 -0
- package/src/esm/lib/converter/shared/redeemScript.d.ts +8 -0
- package/src/esm/lib/converter/shared/redeemScript.js +31 -0
- package/src/esm/lib/converter/shared/tapBip32Derivation.d.ts +8 -0
- package/src/esm/lib/converter/shared/tapBip32Derivation.js +45 -0
- package/src/esm/lib/converter/shared/tapInternalKey.d.ts +8 -0
- package/src/esm/lib/converter/shared/tapInternalKey.js +31 -0
- package/src/esm/lib/converter/shared/witnessScript.d.ts +8 -0
- package/src/esm/lib/converter/shared/witnessScript.js +31 -0
- package/src/esm/lib/converter/tools.d.ts +5 -0
- package/src/esm/lib/converter/tools.js +33 -0
- package/src/esm/lib/interfaces.d.ts +120 -0
- package/src/esm/lib/interfaces.js +0 -0
- package/src/esm/lib/parser/fromBuffer.d.ts +11 -0
- package/src/esm/lib/parser/fromBuffer.js +313 -0
- package/src/esm/lib/parser/index.d.ts +8 -0
- package/src/esm/lib/parser/index.js +2 -0
- package/src/esm/lib/parser/toBuffer.d.ts +8 -0
- package/src/esm/lib/parser/toBuffer.js +58 -0
- package/src/esm/lib/psbt.d.ts +26 -0
- package/src/esm/lib/psbt.js +133 -0
- package/src/esm/lib/typeFields.d.ts +34 -0
- package/src/esm/lib/typeFields.js +62 -0
- package/src/esm/lib/utils.d.ts +13 -0
- package/src/esm/lib/utils.js +123 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
import * as varuint from 'varuint-bitcoin';
|
4
|
+
export function decode(keyVal) {
|
5
|
+
if (keyVal.key[0] !== InputTypes.OPCAT_UTXO) {
|
6
|
+
throw new Error('Decode Error: could not decode opcatUtxo with key 0x' +
|
7
|
+
tools.toHex(keyVal.key));
|
8
|
+
}
|
9
|
+
let offset = 0;
|
10
|
+
const value = tools.readInt64(keyVal.value, offset, 'LE');
|
11
|
+
offset += 8;
|
12
|
+
const { numberValue: scriptLen, bytes: scriptLenBytes } = varuint.decode(keyVal.value, offset);
|
13
|
+
if (scriptLen == null)
|
14
|
+
throw new Error('Decode Error: scriptLen is null');
|
15
|
+
offset += scriptLenBytes;
|
16
|
+
const script = keyVal.value.slice(offset, offset + scriptLen);
|
17
|
+
offset += scriptLen;
|
18
|
+
const { numberValue: dataLen, bytes: dataLenBytes } = varuint.decode(keyVal.value, offset);
|
19
|
+
if (dataLen == null)
|
20
|
+
throw new Error('Decode Error: dataLen is null');
|
21
|
+
offset += dataLenBytes;
|
22
|
+
const data = keyVal.value.slice(offset, offset + dataLen);
|
23
|
+
offset += dataLen;
|
24
|
+
return {
|
25
|
+
script,
|
26
|
+
data,
|
27
|
+
value,
|
28
|
+
};
|
29
|
+
}
|
30
|
+
export function encode(data) {
|
31
|
+
const { script, data: opcatData, value } = data;
|
32
|
+
const scriptLen = script.length;
|
33
|
+
const dataLen = opcatData.length;
|
34
|
+
const scriptLenVar = varuint.encodingLength(scriptLen);
|
35
|
+
const dataLenVar = varuint.encodingLength(dataLen);
|
36
|
+
const totalLen = 8 + scriptLenVar + scriptLen + dataLenVar + dataLen;
|
37
|
+
const result = new Uint8Array(totalLen);
|
38
|
+
let offset = 0;
|
39
|
+
tools.writeInt64(result, offset, BigInt(value), 'LE');
|
40
|
+
offset += 8;
|
41
|
+
varuint.encode(scriptLen, result, offset);
|
42
|
+
offset += scriptLenVar;
|
43
|
+
result.set(script, offset);
|
44
|
+
offset += scriptLen;
|
45
|
+
varuint.encode(dataLen, result, offset);
|
46
|
+
offset += dataLenVar;
|
47
|
+
result.set(opcatData, offset);
|
48
|
+
return {
|
49
|
+
key: Uint8Array.from([InputTypes.OPCAT_UTXO]),
|
50
|
+
value: result,
|
51
|
+
};
|
52
|
+
}
|
53
|
+
export const expected = '{ script: Uint8Array; data: Uint8Array; value: bigint; }';
|
54
|
+
export function check(data) {
|
55
|
+
return (data.script instanceof Uint8Array &&
|
56
|
+
data.data instanceof Uint8Array &&
|
57
|
+
typeof data.value === 'bigint');
|
58
|
+
}
|
59
|
+
export function canAdd(currentData, newData) {
|
60
|
+
return !!currentData && !!newData && currentData.opcatUtxo === undefined;
|
61
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, PartialSig } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): PartialSig;
|
3
|
+
export declare function encode(pSig: PartialSig): KeyValue;
|
4
|
+
export declare const expected = "{ pubkey: Uint8Array; signature: Uint8Array; }";
|
5
|
+
export declare function check(data: any): data is PartialSig;
|
6
|
+
export declare function canAddToArray(array: PartialSig[], item: PartialSig, dupeSet: Set<string>): boolean;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.PARTIAL_SIG) {
|
5
|
+
throw new Error('Decode Error: could not decode partialSig with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
if (!(keyVal.key.length === 34 || keyVal.key.length === 66) ||
|
9
|
+
![2, 3, 4].includes(keyVal.key[1])) {
|
10
|
+
throw new Error('Decode Error: partialSig has invalid pubkey in key 0x' +
|
11
|
+
tools.toHex(keyVal.key));
|
12
|
+
}
|
13
|
+
const pubkey = keyVal.key.slice(1);
|
14
|
+
return {
|
15
|
+
pubkey,
|
16
|
+
signature: keyVal.value,
|
17
|
+
};
|
18
|
+
}
|
19
|
+
export function encode(pSig) {
|
20
|
+
const head = new Uint8Array([InputTypes.PARTIAL_SIG]);
|
21
|
+
return {
|
22
|
+
key: tools.concat([head, pSig.pubkey]),
|
23
|
+
value: pSig.signature,
|
24
|
+
};
|
25
|
+
}
|
26
|
+
export const expected = '{ pubkey: Uint8Array; signature: Uint8Array; }';
|
27
|
+
export function check(data) {
|
28
|
+
return (data.pubkey instanceof Uint8Array &&
|
29
|
+
data.signature instanceof Uint8Array &&
|
30
|
+
[33, 65].includes(data.pubkey.length) &&
|
31
|
+
[2, 3, 4].includes(data.pubkey[0]) &&
|
32
|
+
isDerSigWithSighash(data.signature));
|
33
|
+
}
|
34
|
+
function isDerSigWithSighash(buf) {
|
35
|
+
if (!(buf instanceof Uint8Array) || buf.length < 9)
|
36
|
+
return false;
|
37
|
+
if (buf[0] !== 0x30)
|
38
|
+
return false;
|
39
|
+
if (buf.length !== buf[1] + 3)
|
40
|
+
return false;
|
41
|
+
if (buf[2] !== 0x02)
|
42
|
+
return false;
|
43
|
+
const rLen = buf[3];
|
44
|
+
if (rLen > 33 || rLen < 1)
|
45
|
+
return false;
|
46
|
+
if (buf[3 + rLen + 1] !== 0x02)
|
47
|
+
return false;
|
48
|
+
const sLen = buf[3 + rLen + 2];
|
49
|
+
if (sLen > 33 || sLen < 1)
|
50
|
+
return false;
|
51
|
+
if (buf.length !== 3 + rLen + 2 + sLen + 2)
|
52
|
+
return false;
|
53
|
+
return true;
|
54
|
+
}
|
55
|
+
export function canAddToArray(array, item, dupeSet) {
|
56
|
+
const dupeString = tools.toHex(item.pubkey);
|
57
|
+
if (dupeSet.has(dupeString))
|
58
|
+
return false;
|
59
|
+
dupeSet.add(dupeString);
|
60
|
+
return (array.filter(v => tools.compare(v.pubkey, item.pubkey) === 0).length === 0);
|
61
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, PorCommitment } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): PorCommitment;
|
3
|
+
export declare function encode(data: PorCommitment): KeyValue;
|
4
|
+
export declare const expected = "string";
|
5
|
+
export declare function check(data: any): data is PorCommitment;
|
6
|
+
export declare function canAdd(currentData: any, newData: any): boolean;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.POR_COMMITMENT) {
|
5
|
+
throw new Error('Decode Error: could not decode porCommitment with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
return tools.toUtf8(keyVal.value);
|
9
|
+
}
|
10
|
+
export function encode(data) {
|
11
|
+
const key = new Uint8Array([InputTypes.POR_COMMITMENT]);
|
12
|
+
return {
|
13
|
+
key,
|
14
|
+
value: tools.fromUtf8(data),
|
15
|
+
};
|
16
|
+
}
|
17
|
+
export const expected = 'string';
|
18
|
+
export function check(data) {
|
19
|
+
return typeof data === 'string';
|
20
|
+
}
|
21
|
+
export function canAdd(currentData, newData) {
|
22
|
+
return !!currentData && !!newData && currentData.porCommitment === undefined;
|
23
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, SighashType } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): SighashType;
|
3
|
+
export declare function encode(data: SighashType): KeyValue;
|
4
|
+
export declare const expected = "number";
|
5
|
+
export declare function check(data: any): data is SighashType;
|
6
|
+
export declare function canAdd(currentData: any, newData: any): boolean;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.SIGHASH_TYPE) {
|
5
|
+
throw new Error('Decode Error: could not decode sighashType with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
return Number(tools.readUInt32(keyVal.value, 0, 'LE'));
|
9
|
+
}
|
10
|
+
export function encode(data) {
|
11
|
+
const key = Uint8Array.from([InputTypes.SIGHASH_TYPE]);
|
12
|
+
const value = new Uint8Array(4);
|
13
|
+
tools.writeUInt32(value, 0, data, 'LE');
|
14
|
+
return {
|
15
|
+
key,
|
16
|
+
value,
|
17
|
+
};
|
18
|
+
}
|
19
|
+
export const expected = 'number';
|
20
|
+
export function check(data) {
|
21
|
+
return typeof data === 'number';
|
22
|
+
}
|
23
|
+
export function canAdd(currentData, newData) {
|
24
|
+
return !!currentData && !!newData && currentData.sighashType === undefined;
|
25
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, TapKeySig } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): TapKeySig;
|
3
|
+
export declare function encode(value: TapKeySig): KeyValue;
|
4
|
+
export declare const expected = "Uint8Array";
|
5
|
+
export declare function check(data: any): data is TapKeySig;
|
6
|
+
export declare function canAdd(currentData: any, newData: any): boolean;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.TAP_KEY_SIG || keyVal.key.length !== 1) {
|
5
|
+
throw new Error('Decode Error: could not decode tapKeySig with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
if (!check(keyVal.value)) {
|
9
|
+
throw new Error('Decode Error: tapKeySig not a valid 64-65-byte BIP340 signature');
|
10
|
+
}
|
11
|
+
return keyVal.value;
|
12
|
+
}
|
13
|
+
export function encode(value) {
|
14
|
+
const key = Uint8Array.from([InputTypes.TAP_KEY_SIG]);
|
15
|
+
return { key, value };
|
16
|
+
}
|
17
|
+
export const expected = 'Uint8Array';
|
18
|
+
export function check(data) {
|
19
|
+
return (data instanceof Uint8Array && (data.length === 64 || data.length === 65));
|
20
|
+
}
|
21
|
+
export function canAdd(currentData, newData) {
|
22
|
+
return !!currentData && !!newData && currentData.tapKeySig === undefined;
|
23
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, TapLeafScript } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): TapLeafScript;
|
3
|
+
export declare function encode(tScript: TapLeafScript): KeyValue;
|
4
|
+
export declare const expected = "{ controlBlock: Uint8Array; leafVersion: number, script: Uint8Array; }";
|
5
|
+
export declare function check(data: any): data is TapLeafScript;
|
6
|
+
export declare function canAddToArray(array: TapLeafScript[], item: TapLeafScript, dupeSet: Set<string>): boolean;
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.TAP_LEAF_SCRIPT) {
|
5
|
+
throw new Error('Decode Error: could not decode tapLeafScript with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
if ((keyVal.key.length - 2) % 32 !== 0) {
|
9
|
+
throw new Error('Decode Error: tapLeafScript has invalid control block in key 0x' +
|
10
|
+
tools.toHex(keyVal.key));
|
11
|
+
}
|
12
|
+
const leafVersion = keyVal.value[keyVal.value.length - 1];
|
13
|
+
if ((keyVal.key[1] & 0xfe) !== leafVersion) {
|
14
|
+
throw new Error('Decode Error: tapLeafScript bad leaf version in key 0x' +
|
15
|
+
tools.toHex(keyVal.key));
|
16
|
+
}
|
17
|
+
const script = keyVal.value.slice(0, -1);
|
18
|
+
const controlBlock = keyVal.key.slice(1);
|
19
|
+
return { controlBlock, script, leafVersion };
|
20
|
+
}
|
21
|
+
export function encode(tScript) {
|
22
|
+
const head = Uint8Array.from([InputTypes.TAP_LEAF_SCRIPT]);
|
23
|
+
const verBuf = Uint8Array.from([tScript.leafVersion]);
|
24
|
+
return {
|
25
|
+
key: tools.concat([head, tScript.controlBlock]),
|
26
|
+
value: tools.concat([tScript.script, verBuf]),
|
27
|
+
};
|
28
|
+
}
|
29
|
+
export const expected = '{ controlBlock: Uint8Array; leafVersion: number, script: Uint8Array; }';
|
30
|
+
export function check(data) {
|
31
|
+
return (data.controlBlock instanceof Uint8Array &&
|
32
|
+
(data.controlBlock.length - 1) % 32 === 0 &&
|
33
|
+
(data.controlBlock[0] & 0xfe) === data.leafVersion &&
|
34
|
+
data.script instanceof Uint8Array);
|
35
|
+
}
|
36
|
+
export function canAddToArray(array, item, dupeSet) {
|
37
|
+
const dupeString = tools.toHex(item.controlBlock);
|
38
|
+
if (dupeSet.has(dupeString))
|
39
|
+
return false;
|
40
|
+
dupeSet.add(dupeString);
|
41
|
+
return (array.filter(v => tools.compare(v.controlBlock, item.controlBlock) === 0)
|
42
|
+
.length === 0);
|
43
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, TapMerkleRoot } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): TapMerkleRoot;
|
3
|
+
export declare function encode(value: TapMerkleRoot): KeyValue;
|
4
|
+
export declare const expected = "Uint8Array";
|
5
|
+
export declare function check(data: any): data is TapMerkleRoot;
|
6
|
+
export declare function canAdd(currentData: any, newData: any): boolean;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.TAP_MERKLE_ROOT || keyVal.key.length !== 1) {
|
5
|
+
throw new Error('Decode Error: could not decode tapMerkleRoot with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
if (!check(keyVal.value)) {
|
9
|
+
throw new Error('Decode Error: tapMerkleRoot not a 32-byte hash');
|
10
|
+
}
|
11
|
+
return keyVal.value;
|
12
|
+
}
|
13
|
+
export function encode(value) {
|
14
|
+
const key = Uint8Array.from([InputTypes.TAP_MERKLE_ROOT]);
|
15
|
+
return { key, value };
|
16
|
+
}
|
17
|
+
export const expected = 'Uint8Array';
|
18
|
+
export function check(data) {
|
19
|
+
return data instanceof Uint8Array && data.length === 32;
|
20
|
+
}
|
21
|
+
export function canAdd(currentData, newData) {
|
22
|
+
return !!currentData && !!newData && currentData.tapMerkleRoot === undefined;
|
23
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, TapScriptSig } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): TapScriptSig;
|
3
|
+
export declare function encode(tSig: TapScriptSig): KeyValue;
|
4
|
+
export declare const expected = "{ pubkey: Uint8Array; leafHash: Uint8Array; signature: Uint8Array; }";
|
5
|
+
export declare function check(data: any): data is TapScriptSig;
|
6
|
+
export declare function canAddToArray(array: TapScriptSig[], item: TapScriptSig, dupeSet: Set<string>): boolean;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
export function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== InputTypes.TAP_SCRIPT_SIG) {
|
5
|
+
throw new Error('Decode Error: could not decode tapScriptSig with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
if (keyVal.key.length !== 65) {
|
9
|
+
throw new Error('Decode Error: tapScriptSig has invalid key 0x' + tools.toHex(keyVal.key));
|
10
|
+
}
|
11
|
+
if (keyVal.value.length !== 64 && keyVal.value.length !== 65) {
|
12
|
+
throw new Error('Decode Error: tapScriptSig has invalid signature in key 0x' +
|
13
|
+
tools.toHex(keyVal.key));
|
14
|
+
}
|
15
|
+
const pubkey = keyVal.key.slice(1, 33);
|
16
|
+
const leafHash = keyVal.key.slice(33);
|
17
|
+
return {
|
18
|
+
pubkey,
|
19
|
+
leafHash,
|
20
|
+
signature: keyVal.value,
|
21
|
+
};
|
22
|
+
}
|
23
|
+
export function encode(tSig) {
|
24
|
+
const head = Uint8Array.from([InputTypes.TAP_SCRIPT_SIG]);
|
25
|
+
return {
|
26
|
+
key: tools.concat([head, tSig.pubkey, tSig.leafHash]),
|
27
|
+
value: tSig.signature,
|
28
|
+
};
|
29
|
+
}
|
30
|
+
export const expected = '{ pubkey: Uint8Array; leafHash: Uint8Array; signature: Uint8Array; }';
|
31
|
+
export function check(data) {
|
32
|
+
return (data.pubkey instanceof Uint8Array &&
|
33
|
+
data.leafHash instanceof Uint8Array &&
|
34
|
+
data.signature instanceof Uint8Array &&
|
35
|
+
data.pubkey.length === 32 &&
|
36
|
+
data.leafHash.length === 32 &&
|
37
|
+
(data.signature.length === 64 || data.signature.length === 65));
|
38
|
+
}
|
39
|
+
export function canAddToArray(array, item, dupeSet) {
|
40
|
+
const dupeString = tools.toHex(item.pubkey) + tools.toHex(item.leafHash);
|
41
|
+
if (dupeSet.has(dupeString))
|
42
|
+
return false;
|
43
|
+
dupeSet.add(dupeString);
|
44
|
+
return (array.filter(v => tools.compare(v.pubkey, item.pubkey) === 0 &&
|
45
|
+
tools.compare(v.leafHash, item.leafHash) === 0).length === 0);
|
46
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, WitnessUtxo } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): WitnessUtxo;
|
3
|
+
export declare function encode(data: WitnessUtxo): KeyValue;
|
4
|
+
export declare const expected = "{ script: Uint8Array; value: bigint; }";
|
5
|
+
export declare function check(data: any): data is WitnessUtxo;
|
6
|
+
export declare function canAdd(currentData: any, newData: any): boolean;
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { InputTypes } from '../../typeFields.js';
|
2
|
+
import * as tools from 'uint8array-tools';
|
3
|
+
import * as varuint from 'varuint-bitcoin';
|
4
|
+
export function decode(keyVal) {
|
5
|
+
if (keyVal.key[0] !== InputTypes.WITNESS_UTXO) {
|
6
|
+
throw new Error('Decode Error: could not decode witnessUtxo with key 0x' +
|
7
|
+
tools.toHex(keyVal.key));
|
8
|
+
}
|
9
|
+
const value = tools.readInt64(keyVal.value, 0, 'LE');
|
10
|
+
let _offset = 8;
|
11
|
+
const { numberValue: scriptLen, bytes } = varuint.decode(keyVal.value, _offset);
|
12
|
+
_offset += bytes;
|
13
|
+
const script = keyVal.value.slice(_offset);
|
14
|
+
if (script.length !== scriptLen) {
|
15
|
+
throw new Error('Decode Error: WITNESS_UTXO script is not proper length');
|
16
|
+
}
|
17
|
+
return {
|
18
|
+
script,
|
19
|
+
value,
|
20
|
+
};
|
21
|
+
}
|
22
|
+
export function encode(data) {
|
23
|
+
const { script, value } = data;
|
24
|
+
const varuintlen = varuint.encodingLength(script.length);
|
25
|
+
const result = new Uint8Array(8 + varuintlen + script.length);
|
26
|
+
tools.writeInt64(result, 0, BigInt(value), 'LE');
|
27
|
+
varuint.encode(script.length, result, 8);
|
28
|
+
result.set(script, 8 + varuintlen);
|
29
|
+
return {
|
30
|
+
key: Uint8Array.from([InputTypes.WITNESS_UTXO]),
|
31
|
+
value: result,
|
32
|
+
};
|
33
|
+
}
|
34
|
+
export const expected = '{ script: Uint8Array; value: bigint; }';
|
35
|
+
export function check(data) {
|
36
|
+
return data.script instanceof Uint8Array && typeof data.value === 'bigint';
|
37
|
+
}
|
38
|
+
export function canAdd(currentData, newData) {
|
39
|
+
return !!currentData && !!newData && currentData.witnessUtxo === undefined;
|
40
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { KeyValue, TapTree } from '../../interfaces';
|
2
|
+
export declare function decode(keyVal: KeyValue): TapTree;
|
3
|
+
export declare function encode(tree: TapTree): KeyValue;
|
4
|
+
export declare const expected = "{ leaves: [{ depth: number; leafVersion: number, script: Uint8Array; }] }";
|
5
|
+
export declare function check(data: any): data is TapTree;
|
6
|
+
export declare function canAdd(currentData: any, newData: any): boolean;
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { OutputTypes } from '../../typeFields.js';
|
2
|
+
import * as varuint from 'varuint-bitcoin';
|
3
|
+
import * as tools from 'uint8array-tools';
|
4
|
+
export function decode(keyVal) {
|
5
|
+
if (keyVal.key[0] !== OutputTypes.TAP_TREE || keyVal.key.length !== 1) {
|
6
|
+
throw new Error('Decode Error: could not decode tapTree with key 0x' +
|
7
|
+
tools.toHex(keyVal.key));
|
8
|
+
}
|
9
|
+
let _offset = 0;
|
10
|
+
const data = [];
|
11
|
+
while (_offset < keyVal.value.length) {
|
12
|
+
const depth = keyVal.value[_offset++];
|
13
|
+
const leafVersion = keyVal.value[_offset++];
|
14
|
+
const { numberValue: scriptLen, bytes } = varuint.decode(keyVal.value, _offset);
|
15
|
+
_offset += bytes;
|
16
|
+
data.push({
|
17
|
+
depth,
|
18
|
+
leafVersion,
|
19
|
+
script: keyVal.value.slice(_offset, _offset + scriptLen),
|
20
|
+
});
|
21
|
+
_offset += scriptLen;
|
22
|
+
}
|
23
|
+
return { leaves: data };
|
24
|
+
}
|
25
|
+
export function encode(tree) {
|
26
|
+
const key = Uint8Array.from([OutputTypes.TAP_TREE]);
|
27
|
+
const bufs = [].concat(...tree.leaves.map(tapLeaf => [
|
28
|
+
Uint8Array.of(tapLeaf.depth, tapLeaf.leafVersion),
|
29
|
+
varuint.encode(BigInt(tapLeaf.script.length)).buffer,
|
30
|
+
tapLeaf.script,
|
31
|
+
]));
|
32
|
+
return {
|
33
|
+
key,
|
34
|
+
value: tools.concat(bufs),
|
35
|
+
};
|
36
|
+
}
|
37
|
+
export const expected = '{ leaves: [{ depth: number; leafVersion: number, script: Uint8Array; }] }';
|
38
|
+
export function check(data) {
|
39
|
+
return (Array.isArray(data.leaves) &&
|
40
|
+
data.leaves.every((tapLeaf) => tapLeaf.depth >= 0 &&
|
41
|
+
tapLeaf.depth <= 128 &&
|
42
|
+
(tapLeaf.leafVersion & 0xfe) === tapLeaf.leafVersion &&
|
43
|
+
tapLeaf.script instanceof Uint8Array));
|
44
|
+
}
|
45
|
+
export function canAdd(currentData, newData) {
|
46
|
+
return !!currentData && !!newData && currentData.tapTree === undefined;
|
47
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { Bip32Derivation, KeyValue } from '../../interfaces';
|
2
|
+
export declare function makeConverter(TYPE_BYTE: number, isValidPubkey?: (pubkey: Uint8Array) => boolean): {
|
3
|
+
decode: (keyVal: KeyValue) => Bip32Derivation;
|
4
|
+
encode: (data: Bip32Derivation) => KeyValue;
|
5
|
+
check: (data: any) => data is Bip32Derivation;
|
6
|
+
expected: string;
|
7
|
+
canAddToArray: (array: Bip32Derivation[], item: Bip32Derivation, dupeSet: Set<string>) => boolean;
|
8
|
+
};
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import * as tools from 'uint8array-tools';
|
2
|
+
const range = (n) => [...Array(n).keys()];
|
3
|
+
const isValidDERKey = (pubkey) => (pubkey.length === 33 && [2, 3].includes(pubkey[0])) ||
|
4
|
+
(pubkey.length === 65 && 4 === pubkey[0]);
|
5
|
+
export function makeConverter(TYPE_BYTE, isValidPubkey = isValidDERKey) {
|
6
|
+
function decode(keyVal) {
|
7
|
+
if (keyVal.key[0] !== TYPE_BYTE) {
|
8
|
+
throw new Error('Decode Error: could not decode bip32Derivation with key 0x' +
|
9
|
+
tools.toHex(keyVal.key));
|
10
|
+
}
|
11
|
+
const pubkey = keyVal.key.slice(1);
|
12
|
+
if (!isValidPubkey(pubkey)) {
|
13
|
+
throw new Error('Decode Error: bip32Derivation has invalid pubkey in key 0x' +
|
14
|
+
tools.toHex(keyVal.key));
|
15
|
+
}
|
16
|
+
if ((keyVal.value.length / 4) % 1 !== 0) {
|
17
|
+
throw new Error('Decode Error: Input BIP32_DERIVATION value length should be multiple of 4');
|
18
|
+
}
|
19
|
+
const data = {
|
20
|
+
masterFingerprint: keyVal.value.slice(0, 4),
|
21
|
+
pubkey,
|
22
|
+
path: 'm',
|
23
|
+
};
|
24
|
+
for (const i of range(keyVal.value.length / 4 - 1)) {
|
25
|
+
const val = tools.readUInt32(keyVal.value, i * 4 + 4, 'LE');
|
26
|
+
const isHard = !!(val & 0x80000000);
|
27
|
+
const idx = val & 0x7fffffff;
|
28
|
+
data.path += '/' + idx.toString(10) + (isHard ? "'" : '');
|
29
|
+
}
|
30
|
+
return data;
|
31
|
+
}
|
32
|
+
function encode(data) {
|
33
|
+
const head = Uint8Array.from([TYPE_BYTE]);
|
34
|
+
const key = tools.concat([head, data.pubkey]);
|
35
|
+
const splitPath = data.path.split('/');
|
36
|
+
const value = new Uint8Array(splitPath.length * 4);
|
37
|
+
value.set(data.masterFingerprint, 0);
|
38
|
+
let offset = 4;
|
39
|
+
splitPath.slice(1).forEach(level => {
|
40
|
+
const isHard = level.slice(-1) === "'";
|
41
|
+
let num = 0x7fffffff & parseInt(isHard ? level.slice(0, -1) : level, 10);
|
42
|
+
if (isHard)
|
43
|
+
num += 0x80000000;
|
44
|
+
tools.writeUInt32(value, offset, num, 'LE');
|
45
|
+
offset += 4;
|
46
|
+
});
|
47
|
+
return {
|
48
|
+
key,
|
49
|
+
value,
|
50
|
+
};
|
51
|
+
}
|
52
|
+
const expected = '{ masterFingerprint: Uint8Array; pubkey: Uint8Array; path: string; }';
|
53
|
+
function check(data) {
|
54
|
+
return (data.pubkey instanceof Uint8Array &&
|
55
|
+
data.masterFingerprint instanceof Uint8Array &&
|
56
|
+
typeof data.path === 'string' &&
|
57
|
+
isValidPubkey(data.pubkey) &&
|
58
|
+
data.masterFingerprint.length === 4);
|
59
|
+
}
|
60
|
+
function canAddToArray(array, item, dupeSet) {
|
61
|
+
const dupeString = tools.toHex(item.pubkey);
|
62
|
+
if (dupeSet.has(dupeString))
|
63
|
+
return false;
|
64
|
+
dupeSet.add(dupeString);
|
65
|
+
return (array.filter(v => tools.compare(v.pubkey, item.pubkey) === 0).length === 0);
|
66
|
+
}
|
67
|
+
return {
|
68
|
+
decode,
|
69
|
+
encode,
|
70
|
+
check,
|
71
|
+
expected,
|
72
|
+
canAddToArray,
|
73
|
+
};
|
74
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import * as tools from 'uint8array-tools';
|
2
|
+
export function makeChecker(pubkeyTypes) {
|
3
|
+
return checkPubkey;
|
4
|
+
function checkPubkey(keyVal) {
|
5
|
+
let pubkey;
|
6
|
+
if (pubkeyTypes.includes(keyVal.key[0])) {
|
7
|
+
pubkey = keyVal.key.slice(1);
|
8
|
+
if (!(pubkey.length === 33 || pubkey.length === 65) ||
|
9
|
+
![2, 3, 4].includes(pubkey[0])) {
|
10
|
+
throw new Error('Format Error: invalid pubkey in key 0x' + tools.toHex(keyVal.key));
|
11
|
+
}
|
12
|
+
}
|
13
|
+
return pubkey;
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { KeyValue, RedeemScript } from '../../interfaces';
|
2
|
+
export declare function makeConverter(TYPE_BYTE: number): {
|
3
|
+
decode: (keyVal: KeyValue) => RedeemScript;
|
4
|
+
encode: (data: RedeemScript) => KeyValue;
|
5
|
+
check: (data: any) => data is RedeemScript;
|
6
|
+
expected: string;
|
7
|
+
canAdd: (currentData: any, newData: any) => boolean;
|
8
|
+
};
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import * as tools from 'uint8array-tools';
|
2
|
+
export function makeConverter(TYPE_BYTE) {
|
3
|
+
function decode(keyVal) {
|
4
|
+
if (keyVal.key[0] !== TYPE_BYTE) {
|
5
|
+
throw new Error('Decode Error: could not decode redeemScript with key 0x' +
|
6
|
+
tools.toHex(keyVal.key));
|
7
|
+
}
|
8
|
+
return keyVal.value;
|
9
|
+
}
|
10
|
+
function encode(data) {
|
11
|
+
const key = Uint8Array.from([TYPE_BYTE]);
|
12
|
+
return {
|
13
|
+
key,
|
14
|
+
value: data,
|
15
|
+
};
|
16
|
+
}
|
17
|
+
const expected = 'Uint8Array';
|
18
|
+
function check(data) {
|
19
|
+
return data instanceof Uint8Array;
|
20
|
+
}
|
21
|
+
function canAdd(currentData, newData) {
|
22
|
+
return !!currentData && !!newData && currentData.redeemScript === undefined;
|
23
|
+
}
|
24
|
+
return {
|
25
|
+
decode,
|
26
|
+
encode,
|
27
|
+
check,
|
28
|
+
expected,
|
29
|
+
canAdd,
|
30
|
+
};
|
31
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { KeyValue, TapBip32Derivation } from '../../interfaces';
|
2
|
+
export declare function makeConverter(TYPE_BYTE: number): {
|
3
|
+
decode: (keyVal: KeyValue) => TapBip32Derivation;
|
4
|
+
encode: (data: TapBip32Derivation) => KeyValue;
|
5
|
+
check: (data: any) => data is TapBip32Derivation;
|
6
|
+
expected: string;
|
7
|
+
canAddToArray: (array: TapBip32Derivation[], item: TapBip32Derivation, dupeSet: Set<string>) => boolean;
|
8
|
+
};
|