@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,41 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
3
|
+
if (mod && mod.__esModule) return mod;
|
4
|
+
var result = {};
|
5
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
6
|
+
result["default"] = mod;
|
7
|
+
return result;
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
const tools = __importStar(require("uint8array-tools"));
|
11
|
+
function makeConverter(TYPE_BYTE) {
|
12
|
+
function decode(keyVal) {
|
13
|
+
if (keyVal.key[0] !== TYPE_BYTE || keyVal.key.length !== 1) {
|
14
|
+
throw new Error('Decode Error: could not decode tapInternalKey with key 0x' +
|
15
|
+
tools.toHex(keyVal.key));
|
16
|
+
}
|
17
|
+
if (keyVal.value.length !== 32) {
|
18
|
+
throw new Error('Decode Error: tapInternalKey not a 32-byte x-only pubkey');
|
19
|
+
}
|
20
|
+
return keyVal.value;
|
21
|
+
}
|
22
|
+
function encode(value) {
|
23
|
+
const key = Uint8Array.from([TYPE_BYTE]);
|
24
|
+
return { key, value };
|
25
|
+
}
|
26
|
+
const expected = 'Uint8Array';
|
27
|
+
function check(data) {
|
28
|
+
return data instanceof Uint8Array && data.length === 32;
|
29
|
+
}
|
30
|
+
function canAdd(currentData, newData) {
|
31
|
+
return (!!currentData && !!newData && currentData.tapInternalKey === undefined);
|
32
|
+
}
|
33
|
+
return {
|
34
|
+
decode,
|
35
|
+
encode,
|
36
|
+
check,
|
37
|
+
expected,
|
38
|
+
canAdd,
|
39
|
+
};
|
40
|
+
}
|
41
|
+
exports.makeConverter = makeConverter;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
3
|
+
if (mod && mod.__esModule) return mod;
|
4
|
+
var result = {};
|
5
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
6
|
+
result["default"] = mod;
|
7
|
+
return result;
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
const tools = __importStar(require("uint8array-tools"));
|
11
|
+
function makeConverter(TYPE_BYTE) {
|
12
|
+
function decode(keyVal) {
|
13
|
+
if (keyVal.key[0] !== TYPE_BYTE) {
|
14
|
+
throw new Error('Decode Error: could not decode witnessScript with key 0x' +
|
15
|
+
tools.toHex(keyVal.key));
|
16
|
+
}
|
17
|
+
return keyVal.value;
|
18
|
+
}
|
19
|
+
function encode(data) {
|
20
|
+
const key = Uint8Array.from([TYPE_BYTE]);
|
21
|
+
return {
|
22
|
+
key,
|
23
|
+
value: data,
|
24
|
+
};
|
25
|
+
}
|
26
|
+
const expected = 'Uint8Array';
|
27
|
+
function check(data) {
|
28
|
+
return data instanceof Uint8Array;
|
29
|
+
}
|
30
|
+
function canAdd(currentData, newData) {
|
31
|
+
return (!!currentData && !!newData && currentData.witnessScript === undefined);
|
32
|
+
}
|
33
|
+
return {
|
34
|
+
decode,
|
35
|
+
encode,
|
36
|
+
check,
|
37
|
+
expected,
|
38
|
+
canAdd,
|
39
|
+
};
|
40
|
+
}
|
41
|
+
exports.makeConverter = makeConverter;
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
3
|
+
if (mod && mod.__esModule) return mod;
|
4
|
+
var result = {};
|
5
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
6
|
+
result["default"] = mod;
|
7
|
+
return result;
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
const varuint = __importStar(require("varuint-bitcoin"));
|
11
|
+
const tools = __importStar(require("uint8array-tools"));
|
12
|
+
exports.range = (n) => [...Array(n).keys()];
|
13
|
+
function reverseBuffer(buffer) {
|
14
|
+
if (buffer.length < 1)
|
15
|
+
return buffer;
|
16
|
+
let j = buffer.length - 1;
|
17
|
+
let tmp = 0;
|
18
|
+
for (let i = 0; i < buffer.length / 2; i++) {
|
19
|
+
tmp = buffer[i];
|
20
|
+
buffer[i] = buffer[j];
|
21
|
+
buffer[j] = tmp;
|
22
|
+
j--;
|
23
|
+
}
|
24
|
+
return buffer;
|
25
|
+
}
|
26
|
+
exports.reverseBuffer = reverseBuffer;
|
27
|
+
function keyValsToBuffer(keyVals) {
|
28
|
+
const buffers = keyVals.map(keyValToBuffer);
|
29
|
+
buffers.push(Uint8Array.from([0]));
|
30
|
+
return tools.concat(buffers);
|
31
|
+
}
|
32
|
+
exports.keyValsToBuffer = keyValsToBuffer;
|
33
|
+
function keyValToBuffer(keyVal) {
|
34
|
+
const keyLen = keyVal.key.length;
|
35
|
+
const valLen = keyVal.value.length;
|
36
|
+
const keyVarIntLen = varuint.encodingLength(keyLen);
|
37
|
+
const valVarIntLen = varuint.encodingLength(valLen);
|
38
|
+
const buffer = new Uint8Array(keyVarIntLen + keyLen + valVarIntLen + valLen);
|
39
|
+
varuint.encode(keyLen, buffer, 0);
|
40
|
+
buffer.set(keyVal.key, keyVarIntLen);
|
41
|
+
varuint.encode(valLen, buffer, keyVarIntLen + keyLen);
|
42
|
+
buffer.set(keyVal.value, keyVarIntLen + keyLen + valVarIntLen);
|
43
|
+
return buffer;
|
44
|
+
}
|
45
|
+
exports.keyValToBuffer = keyValToBuffer;
|
@@ -0,0 +1,325 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
3
|
+
if (mod && mod.__esModule) return mod;
|
4
|
+
var result = {};
|
5
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
6
|
+
result["default"] = mod;
|
7
|
+
return result;
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
const convert = __importStar(require("../converter/index.js"));
|
11
|
+
const tools_js_1 = require("../converter/tools.js");
|
12
|
+
const varuint = __importStar(require("varuint-bitcoin"));
|
13
|
+
const tools = __importStar(require("uint8array-tools"));
|
14
|
+
const typeFields_js_1 = require("../typeFields.js");
|
15
|
+
function psbtFromBuffer(buffer, txGetter) {
|
16
|
+
let offset = 0;
|
17
|
+
function varSlice() {
|
18
|
+
const { numberValue: keyLen, bytes } = varuint.decode(buffer, offset);
|
19
|
+
offset += bytes;
|
20
|
+
const key = buffer.slice(offset, offset + Number(keyLen));
|
21
|
+
offset += Number(keyLen);
|
22
|
+
return key;
|
23
|
+
}
|
24
|
+
function readUInt32BE() {
|
25
|
+
const num = tools.readUInt32(buffer, offset, 'BE');
|
26
|
+
offset += 4;
|
27
|
+
return num;
|
28
|
+
}
|
29
|
+
function readUInt8() {
|
30
|
+
const num = tools.readUInt8(buffer, offset);
|
31
|
+
offset += 1;
|
32
|
+
return num;
|
33
|
+
}
|
34
|
+
function getKeyValue() {
|
35
|
+
const key = varSlice();
|
36
|
+
const value = varSlice();
|
37
|
+
return {
|
38
|
+
key,
|
39
|
+
value,
|
40
|
+
};
|
41
|
+
}
|
42
|
+
function checkEndOfKeyValPairs() {
|
43
|
+
if (offset >= buffer.length) {
|
44
|
+
throw new Error('Format Error: Unexpected End of PSBT');
|
45
|
+
}
|
46
|
+
const isEnd = tools.readUInt8(buffer, offset) === 0;
|
47
|
+
if (isEnd) {
|
48
|
+
offset++;
|
49
|
+
}
|
50
|
+
return isEnd;
|
51
|
+
}
|
52
|
+
if (readUInt32BE() !== 0x70736274) {
|
53
|
+
throw new Error('Format Error: Invalid Magic Number');
|
54
|
+
}
|
55
|
+
if (readUInt8() !== 0xff) {
|
56
|
+
throw new Error('Format Error: Magic Number must be followed by 0xff separator');
|
57
|
+
}
|
58
|
+
const globalMapKeyVals = [];
|
59
|
+
const globalKeyIndex = {};
|
60
|
+
while (!checkEndOfKeyValPairs()) {
|
61
|
+
const keyVal = getKeyValue();
|
62
|
+
const hexKey = tools.toHex(keyVal.key);
|
63
|
+
if (globalKeyIndex[hexKey]) {
|
64
|
+
throw new Error('Format Error: Keys must be unique for global keymap: key ' + hexKey);
|
65
|
+
}
|
66
|
+
globalKeyIndex[hexKey] = 1;
|
67
|
+
globalMapKeyVals.push(keyVal);
|
68
|
+
}
|
69
|
+
const unsignedTxMaps = globalMapKeyVals.filter(keyVal => keyVal.key[0] === typeFields_js_1.GlobalTypes.UNSIGNED_TX);
|
70
|
+
if (unsignedTxMaps.length !== 1) {
|
71
|
+
throw new Error('Format Error: Only one UNSIGNED_TX allowed');
|
72
|
+
}
|
73
|
+
const unsignedTx = txGetter(unsignedTxMaps[0].value);
|
74
|
+
// Get input and output counts to loop the respective fields
|
75
|
+
const { inputCount, outputCount } = unsignedTx.getInputOutputCounts();
|
76
|
+
const inputKeyVals = [];
|
77
|
+
const outputKeyVals = [];
|
78
|
+
// Get input fields
|
79
|
+
for (const index of tools_js_1.range(inputCount)) {
|
80
|
+
const inputKeyIndex = {};
|
81
|
+
const input = [];
|
82
|
+
while (!checkEndOfKeyValPairs()) {
|
83
|
+
const keyVal = getKeyValue();
|
84
|
+
const hexKey = tools.toHex(keyVal.key);
|
85
|
+
if (inputKeyIndex[hexKey]) {
|
86
|
+
throw new Error('Format Error: Keys must be unique for each input: ' +
|
87
|
+
'input index ' +
|
88
|
+
index +
|
89
|
+
' key ' +
|
90
|
+
hexKey);
|
91
|
+
}
|
92
|
+
inputKeyIndex[hexKey] = 1;
|
93
|
+
input.push(keyVal);
|
94
|
+
}
|
95
|
+
inputKeyVals.push(input);
|
96
|
+
}
|
97
|
+
for (const index of tools_js_1.range(outputCount)) {
|
98
|
+
const outputKeyIndex = {};
|
99
|
+
const output = [];
|
100
|
+
while (!checkEndOfKeyValPairs()) {
|
101
|
+
const keyVal = getKeyValue();
|
102
|
+
const hexKey = tools.toHex(keyVal.key);
|
103
|
+
if (outputKeyIndex[hexKey]) {
|
104
|
+
throw new Error('Format Error: Keys must be unique for each output: ' +
|
105
|
+
'output index ' +
|
106
|
+
index +
|
107
|
+
' key ' +
|
108
|
+
hexKey);
|
109
|
+
}
|
110
|
+
outputKeyIndex[hexKey] = 1;
|
111
|
+
output.push(keyVal);
|
112
|
+
}
|
113
|
+
outputKeyVals.push(output);
|
114
|
+
}
|
115
|
+
return psbtFromKeyVals(unsignedTx, {
|
116
|
+
globalMapKeyVals,
|
117
|
+
inputKeyVals,
|
118
|
+
outputKeyVals,
|
119
|
+
});
|
120
|
+
}
|
121
|
+
exports.psbtFromBuffer = psbtFromBuffer;
|
122
|
+
function checkKeyBuffer(type, keyBuf, keyNum) {
|
123
|
+
if (tools.compare(keyBuf, Uint8Array.from([keyNum]))) {
|
124
|
+
throw new Error(
|
125
|
+
// `Format Error: Invalid ${type} key: ${keyBuf.toString('hex')}`,
|
126
|
+
`Format Error: Invalid ${type} key: ${tools.toHex(keyBuf)}`);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
exports.checkKeyBuffer = checkKeyBuffer;
|
130
|
+
function psbtFromKeyVals(unsignedTx, { globalMapKeyVals, inputKeyVals, outputKeyVals }) {
|
131
|
+
// That was easy :-)
|
132
|
+
const globalMap = {
|
133
|
+
unsignedTx,
|
134
|
+
};
|
135
|
+
let txCount = 0;
|
136
|
+
for (const keyVal of globalMapKeyVals) {
|
137
|
+
// If a globalMap item needs pubkey, uncomment
|
138
|
+
// const pubkey = convert.globals.checkPubkey(keyVal);
|
139
|
+
switch (keyVal.key[0]) {
|
140
|
+
case typeFields_js_1.GlobalTypes.UNSIGNED_TX:
|
141
|
+
checkKeyBuffer('global', keyVal.key, typeFields_js_1.GlobalTypes.UNSIGNED_TX);
|
142
|
+
if (txCount > 0) {
|
143
|
+
throw new Error('Format Error: GlobalMap has multiple UNSIGNED_TX');
|
144
|
+
}
|
145
|
+
txCount++;
|
146
|
+
break;
|
147
|
+
case typeFields_js_1.GlobalTypes.GLOBAL_XPUB:
|
148
|
+
if (globalMap.globalXpub === undefined) {
|
149
|
+
globalMap.globalXpub = [];
|
150
|
+
}
|
151
|
+
globalMap.globalXpub.push(convert.globals.globalXpub.decode(keyVal));
|
152
|
+
break;
|
153
|
+
default:
|
154
|
+
// This will allow inclusion during serialization.
|
155
|
+
if (!globalMap.unknownKeyVals)
|
156
|
+
globalMap.unknownKeyVals = [];
|
157
|
+
globalMap.unknownKeyVals.push(keyVal);
|
158
|
+
}
|
159
|
+
}
|
160
|
+
// Get input and output counts to loop the respective fields
|
161
|
+
const inputCount = inputKeyVals.length;
|
162
|
+
const outputCount = outputKeyVals.length;
|
163
|
+
const inputs = [];
|
164
|
+
const outputs = [];
|
165
|
+
// Get input fields
|
166
|
+
for (const index of tools_js_1.range(inputCount)) {
|
167
|
+
const input = {};
|
168
|
+
for (const keyVal of inputKeyVals[index]) {
|
169
|
+
convert.inputs.checkPubkey(keyVal);
|
170
|
+
switch (keyVal.key[0]) {
|
171
|
+
case typeFields_js_1.InputTypes.NON_WITNESS_UTXO:
|
172
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.NON_WITNESS_UTXO);
|
173
|
+
if (input.nonWitnessUtxo !== undefined) {
|
174
|
+
throw new Error('Format Error: Input has multiple NON_WITNESS_UTXO');
|
175
|
+
}
|
176
|
+
input.nonWitnessUtxo = convert.inputs.nonWitnessUtxo.decode(keyVal);
|
177
|
+
break;
|
178
|
+
case typeFields_js_1.InputTypes.WITNESS_UTXO:
|
179
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.WITNESS_UTXO);
|
180
|
+
if (input.witnessUtxo !== undefined) {
|
181
|
+
throw new Error('Format Error: Input has multiple WITNESS_UTXO');
|
182
|
+
}
|
183
|
+
input.witnessUtxo = convert.inputs.witnessUtxo.decode(keyVal);
|
184
|
+
break;
|
185
|
+
case typeFields_js_1.InputTypes.PARTIAL_SIG:
|
186
|
+
if (input.partialSig === undefined) {
|
187
|
+
input.partialSig = [];
|
188
|
+
}
|
189
|
+
input.partialSig.push(convert.inputs.partialSig.decode(keyVal));
|
190
|
+
break;
|
191
|
+
case typeFields_js_1.InputTypes.SIGHASH_TYPE:
|
192
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.SIGHASH_TYPE);
|
193
|
+
if (input.sighashType !== undefined) {
|
194
|
+
throw new Error('Format Error: Input has multiple SIGHASH_TYPE');
|
195
|
+
}
|
196
|
+
input.sighashType = convert.inputs.sighashType.decode(keyVal);
|
197
|
+
break;
|
198
|
+
case typeFields_js_1.InputTypes.REDEEM_SCRIPT:
|
199
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.REDEEM_SCRIPT);
|
200
|
+
if (input.redeemScript !== undefined) {
|
201
|
+
throw new Error('Format Error: Input has multiple REDEEM_SCRIPT');
|
202
|
+
}
|
203
|
+
input.redeemScript = convert.inputs.redeemScript.decode(keyVal);
|
204
|
+
break;
|
205
|
+
case typeFields_js_1.InputTypes.WITNESS_SCRIPT:
|
206
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.WITNESS_SCRIPT);
|
207
|
+
if (input.witnessScript !== undefined) {
|
208
|
+
throw new Error('Format Error: Input has multiple WITNESS_SCRIPT');
|
209
|
+
}
|
210
|
+
input.witnessScript = convert.inputs.witnessScript.decode(keyVal);
|
211
|
+
break;
|
212
|
+
case typeFields_js_1.InputTypes.BIP32_DERIVATION:
|
213
|
+
if (input.bip32Derivation === undefined) {
|
214
|
+
input.bip32Derivation = [];
|
215
|
+
}
|
216
|
+
input.bip32Derivation.push(convert.inputs.bip32Derivation.decode(keyVal));
|
217
|
+
break;
|
218
|
+
case typeFields_js_1.InputTypes.FINAL_SCRIPTSIG:
|
219
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.FINAL_SCRIPTSIG);
|
220
|
+
input.finalScriptSig = convert.inputs.finalScriptSig.decode(keyVal);
|
221
|
+
break;
|
222
|
+
case typeFields_js_1.InputTypes.FINAL_SCRIPTWITNESS:
|
223
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.FINAL_SCRIPTWITNESS);
|
224
|
+
input.finalScriptWitness = convert.inputs.finalScriptWitness.decode(keyVal);
|
225
|
+
break;
|
226
|
+
case typeFields_js_1.InputTypes.POR_COMMITMENT:
|
227
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.POR_COMMITMENT);
|
228
|
+
input.porCommitment = convert.inputs.porCommitment.decode(keyVal);
|
229
|
+
break;
|
230
|
+
case typeFields_js_1.InputTypes.TAP_KEY_SIG:
|
231
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.TAP_KEY_SIG);
|
232
|
+
input.tapKeySig = convert.inputs.tapKeySig.decode(keyVal);
|
233
|
+
break;
|
234
|
+
case typeFields_js_1.InputTypes.TAP_SCRIPT_SIG:
|
235
|
+
if (input.tapScriptSig === undefined) {
|
236
|
+
input.tapScriptSig = [];
|
237
|
+
}
|
238
|
+
input.tapScriptSig.push(convert.inputs.tapScriptSig.decode(keyVal));
|
239
|
+
break;
|
240
|
+
case typeFields_js_1.InputTypes.TAP_LEAF_SCRIPT:
|
241
|
+
if (input.tapLeafScript === undefined) {
|
242
|
+
input.tapLeafScript = [];
|
243
|
+
}
|
244
|
+
input.tapLeafScript.push(convert.inputs.tapLeafScript.decode(keyVal));
|
245
|
+
break;
|
246
|
+
case typeFields_js_1.InputTypes.TAP_BIP32_DERIVATION:
|
247
|
+
if (input.tapBip32Derivation === undefined) {
|
248
|
+
input.tapBip32Derivation = [];
|
249
|
+
}
|
250
|
+
input.tapBip32Derivation.push(convert.inputs.tapBip32Derivation.decode(keyVal));
|
251
|
+
break;
|
252
|
+
case typeFields_js_1.InputTypes.TAP_INTERNAL_KEY:
|
253
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.TAP_INTERNAL_KEY);
|
254
|
+
input.tapInternalKey = convert.inputs.tapInternalKey.decode(keyVal);
|
255
|
+
break;
|
256
|
+
case typeFields_js_1.InputTypes.TAP_MERKLE_ROOT:
|
257
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.TAP_MERKLE_ROOT);
|
258
|
+
input.tapMerkleRoot = convert.inputs.tapMerkleRoot.decode(keyVal);
|
259
|
+
break;
|
260
|
+
case typeFields_js_1.InputTypes.OPCAT_UTXO:
|
261
|
+
checkKeyBuffer('input', keyVal.key, typeFields_js_1.InputTypes.OPCAT_UTXO);
|
262
|
+
if (input.opcatUtxo !== undefined) {
|
263
|
+
throw new Error('Format Error: Input has multiple OPCAT_UTXO');
|
264
|
+
}
|
265
|
+
input.opcatUtxo = convert.inputs.opcatUtxo.decode(keyVal);
|
266
|
+
break;
|
267
|
+
default:
|
268
|
+
// This will allow inclusion during serialization.
|
269
|
+
if (!input.unknownKeyVals)
|
270
|
+
input.unknownKeyVals = [];
|
271
|
+
input.unknownKeyVals.push(keyVal);
|
272
|
+
}
|
273
|
+
}
|
274
|
+
inputs.push(input);
|
275
|
+
}
|
276
|
+
for (const index of tools_js_1.range(outputCount)) {
|
277
|
+
const output = {};
|
278
|
+
for (const keyVal of outputKeyVals[index]) {
|
279
|
+
convert.outputs.checkPubkey(keyVal);
|
280
|
+
switch (keyVal.key[0]) {
|
281
|
+
case typeFields_js_1.OutputTypes.REDEEM_SCRIPT:
|
282
|
+
checkKeyBuffer('output', keyVal.key, typeFields_js_1.OutputTypes.REDEEM_SCRIPT);
|
283
|
+
if (output.redeemScript !== undefined) {
|
284
|
+
throw new Error('Format Error: Output has multiple REDEEM_SCRIPT');
|
285
|
+
}
|
286
|
+
output.redeemScript = convert.outputs.redeemScript.decode(keyVal);
|
287
|
+
break;
|
288
|
+
case typeFields_js_1.OutputTypes.WITNESS_SCRIPT:
|
289
|
+
checkKeyBuffer('output', keyVal.key, typeFields_js_1.OutputTypes.WITNESS_SCRIPT);
|
290
|
+
if (output.witnessScript !== undefined) {
|
291
|
+
throw new Error('Format Error: Output has multiple WITNESS_SCRIPT');
|
292
|
+
}
|
293
|
+
output.witnessScript = convert.outputs.witnessScript.decode(keyVal);
|
294
|
+
break;
|
295
|
+
case typeFields_js_1.OutputTypes.BIP32_DERIVATION:
|
296
|
+
if (output.bip32Derivation === undefined) {
|
297
|
+
output.bip32Derivation = [];
|
298
|
+
}
|
299
|
+
output.bip32Derivation.push(convert.outputs.bip32Derivation.decode(keyVal));
|
300
|
+
break;
|
301
|
+
case typeFields_js_1.OutputTypes.TAP_INTERNAL_KEY:
|
302
|
+
checkKeyBuffer('output', keyVal.key, typeFields_js_1.OutputTypes.TAP_INTERNAL_KEY);
|
303
|
+
output.tapInternalKey = convert.outputs.tapInternalKey.decode(keyVal);
|
304
|
+
break;
|
305
|
+
case typeFields_js_1.OutputTypes.TAP_TREE:
|
306
|
+
checkKeyBuffer('output', keyVal.key, typeFields_js_1.OutputTypes.TAP_TREE);
|
307
|
+
output.tapTree = convert.outputs.tapTree.decode(keyVal);
|
308
|
+
break;
|
309
|
+
case typeFields_js_1.OutputTypes.TAP_BIP32_DERIVATION:
|
310
|
+
if (output.tapBip32Derivation === undefined) {
|
311
|
+
output.tapBip32Derivation = [];
|
312
|
+
}
|
313
|
+
output.tapBip32Derivation.push(convert.outputs.tapBip32Derivation.decode(keyVal));
|
314
|
+
break;
|
315
|
+
default:
|
316
|
+
if (!output.unknownKeyVals)
|
317
|
+
output.unknownKeyVals = [];
|
318
|
+
output.unknownKeyVals.push(keyVal);
|
319
|
+
}
|
320
|
+
}
|
321
|
+
outputs.push(output);
|
322
|
+
}
|
323
|
+
return { globalMap, inputs, outputs };
|
324
|
+
}
|
325
|
+
exports.psbtFromKeyVals = psbtFromKeyVals;
|
@@ -0,0 +1,69 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
3
|
+
if (mod && mod.__esModule) return mod;
|
4
|
+
var result = {};
|
5
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
6
|
+
result["default"] = mod;
|
7
|
+
return result;
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
const convert = __importStar(require("../converter/index.js"));
|
11
|
+
const tools_js_1 = require("../converter/tools.js");
|
12
|
+
const tools = __importStar(require("uint8array-tools"));
|
13
|
+
function psbtToBuffer({ globalMap, inputs, outputs, }) {
|
14
|
+
const { globalKeyVals, inputKeyVals, outputKeyVals } = psbtToKeyVals({
|
15
|
+
globalMap,
|
16
|
+
inputs,
|
17
|
+
outputs,
|
18
|
+
});
|
19
|
+
const globalBuffer = tools_js_1.keyValsToBuffer(globalKeyVals);
|
20
|
+
const keyValsOrEmptyToBuffer = (keyVals) => keyVals.length === 0
|
21
|
+
? [Uint8Array.from([0])]
|
22
|
+
: keyVals.map(tools_js_1.keyValsToBuffer);
|
23
|
+
const inputBuffers = keyValsOrEmptyToBuffer(inputKeyVals);
|
24
|
+
const outputBuffers = keyValsOrEmptyToBuffer(outputKeyVals);
|
25
|
+
const header = new Uint8Array(5);
|
26
|
+
header.set([0x70, 0x73, 0x62, 0x74, 0xff], 0);
|
27
|
+
return tools.concat([header, globalBuffer].concat(inputBuffers, outputBuffers));
|
28
|
+
}
|
29
|
+
exports.psbtToBuffer = psbtToBuffer;
|
30
|
+
const sortKeyVals = (a, b) => {
|
31
|
+
return tools.compare(a.key, b.key);
|
32
|
+
};
|
33
|
+
function keyValsFromMap(keyValMap, converterFactory) {
|
34
|
+
const keyHexSet = new Set();
|
35
|
+
const keyVals = Object.entries(keyValMap).reduce((result, [key, value]) => {
|
36
|
+
if (key === 'unknownKeyVals')
|
37
|
+
return result;
|
38
|
+
// We are checking for undefined anyways. So ignore TS error
|
39
|
+
// @ts-ignore
|
40
|
+
const converter = converterFactory[key];
|
41
|
+
if (converter === undefined)
|
42
|
+
return result;
|
43
|
+
const encodedKeyVals = (Array.isArray(value) ? value : [value]).map(converter.encode);
|
44
|
+
const keyHexes = encodedKeyVals.map(kv => tools.toHex(kv.key));
|
45
|
+
keyHexes.forEach(hex => {
|
46
|
+
if (keyHexSet.has(hex))
|
47
|
+
throw new Error('Serialize Error: Duplicate key: ' + hex);
|
48
|
+
keyHexSet.add(hex);
|
49
|
+
});
|
50
|
+
return result.concat(encodedKeyVals);
|
51
|
+
}, []);
|
52
|
+
// Get other keyVals that have not yet been gotten
|
53
|
+
const otherKeyVals = keyValMap.unknownKeyVals
|
54
|
+
? keyValMap.unknownKeyVals.filter((keyVal) => {
|
55
|
+
return !keyHexSet.has(tools.toHex(keyVal.key));
|
56
|
+
})
|
57
|
+
: [];
|
58
|
+
return keyVals.concat(otherKeyVals).sort(sortKeyVals);
|
59
|
+
}
|
60
|
+
function psbtToKeyVals({ globalMap, inputs, outputs, }) {
|
61
|
+
// First parse the global keyVals
|
62
|
+
// Get any extra keyvals to pass along
|
63
|
+
return {
|
64
|
+
globalKeyVals: keyValsFromMap(globalMap, convert.globals),
|
65
|
+
inputKeyVals: inputs.map(i => keyValsFromMap(i, convert.inputs)),
|
66
|
+
outputKeyVals: outputs.map(o => keyValsFromMap(o, convert.outputs)),
|
67
|
+
};
|
68
|
+
}
|
69
|
+
exports.psbtToKeyVals = psbtToKeyVals;
|
@@ -0,0 +1,145 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
3
|
+
if (mod && mod.__esModule) return mod;
|
4
|
+
var result = {};
|
5
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
6
|
+
result["default"] = mod;
|
7
|
+
return result;
|
8
|
+
};
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
10
|
+
const index_js_1 = require("./combiner/index.js");
|
11
|
+
const index_js_2 = require("./parser/index.js");
|
12
|
+
const typeFields_js_1 = require("./typeFields.js");
|
13
|
+
const utils_js_1 = require("./utils.js");
|
14
|
+
const tools = __importStar(require("uint8array-tools"));
|
15
|
+
class Psbt {
|
16
|
+
constructor(tx) {
|
17
|
+
this.inputs = [];
|
18
|
+
this.outputs = [];
|
19
|
+
this.globalMap = {
|
20
|
+
unsignedTx: tx,
|
21
|
+
};
|
22
|
+
}
|
23
|
+
static fromBase64(data, txFromBuffer) {
|
24
|
+
const buffer = tools.fromBase64(data);
|
25
|
+
return this.fromBuffer(buffer, txFromBuffer);
|
26
|
+
}
|
27
|
+
static fromHex(data, txFromBuffer) {
|
28
|
+
const buffer = tools.fromHex(data);
|
29
|
+
return this.fromBuffer(buffer, txFromBuffer);
|
30
|
+
}
|
31
|
+
static fromBuffer(buffer, txFromBuffer) {
|
32
|
+
const results = index_js_2.psbtFromBuffer(buffer, txFromBuffer);
|
33
|
+
const psbt = new this(results.globalMap.unsignedTx);
|
34
|
+
Object.assign(psbt, results);
|
35
|
+
return psbt;
|
36
|
+
}
|
37
|
+
toBase64() {
|
38
|
+
const buffer = this.toBuffer();
|
39
|
+
return tools.toBase64(buffer);
|
40
|
+
}
|
41
|
+
toHex() {
|
42
|
+
const buffer = this.toBuffer();
|
43
|
+
return tools.toHex(buffer);
|
44
|
+
}
|
45
|
+
toBuffer() {
|
46
|
+
return index_js_2.psbtToBuffer(this);
|
47
|
+
}
|
48
|
+
updateGlobal(updateData) {
|
49
|
+
utils_js_1.updateGlobal(updateData, this.globalMap);
|
50
|
+
return this;
|
51
|
+
}
|
52
|
+
updateInput(inputIndex, updateData) {
|
53
|
+
const input = utils_js_1.checkForInput(this.inputs, inputIndex);
|
54
|
+
utils_js_1.updateInput(updateData, input);
|
55
|
+
return this;
|
56
|
+
}
|
57
|
+
updateOutput(outputIndex, updateData) {
|
58
|
+
const output = utils_js_1.checkForOutput(this.outputs, outputIndex);
|
59
|
+
utils_js_1.updateOutput(updateData, output);
|
60
|
+
return this;
|
61
|
+
}
|
62
|
+
addUnknownKeyValToGlobal(keyVal) {
|
63
|
+
utils_js_1.checkHasKey(keyVal, this.globalMap.unknownKeyVals, utils_js_1.getEnumLength(typeFields_js_1.GlobalTypes));
|
64
|
+
if (!this.globalMap.unknownKeyVals)
|
65
|
+
this.globalMap.unknownKeyVals = [];
|
66
|
+
this.globalMap.unknownKeyVals.push(keyVal);
|
67
|
+
return this;
|
68
|
+
}
|
69
|
+
addUnknownKeyValToInput(inputIndex, keyVal) {
|
70
|
+
const input = utils_js_1.checkForInput(this.inputs, inputIndex);
|
71
|
+
utils_js_1.checkHasKey(keyVal, input.unknownKeyVals, utils_js_1.getEnumLength(typeFields_js_1.InputTypes));
|
72
|
+
if (!input.unknownKeyVals)
|
73
|
+
input.unknownKeyVals = [];
|
74
|
+
input.unknownKeyVals.push(keyVal);
|
75
|
+
return this;
|
76
|
+
}
|
77
|
+
addUnknownKeyValToOutput(outputIndex, keyVal) {
|
78
|
+
const output = utils_js_1.checkForOutput(this.outputs, outputIndex);
|
79
|
+
utils_js_1.checkHasKey(keyVal, output.unknownKeyVals, utils_js_1.getEnumLength(typeFields_js_1.OutputTypes));
|
80
|
+
if (!output.unknownKeyVals)
|
81
|
+
output.unknownKeyVals = [];
|
82
|
+
output.unknownKeyVals.push(keyVal);
|
83
|
+
return this;
|
84
|
+
}
|
85
|
+
addInput(inputData) {
|
86
|
+
this.globalMap.unsignedTx.addInput(inputData);
|
87
|
+
this.inputs.push({
|
88
|
+
unknownKeyVals: [],
|
89
|
+
});
|
90
|
+
const addKeyVals = inputData.unknownKeyVals || [];
|
91
|
+
const inputIndex = this.inputs.length - 1;
|
92
|
+
if (!Array.isArray(addKeyVals)) {
|
93
|
+
throw new Error('unknownKeyVals must be an Array');
|
94
|
+
}
|
95
|
+
addKeyVals.forEach((keyVal) => this.addUnknownKeyValToInput(inputIndex, keyVal));
|
96
|
+
utils_js_1.addInputAttributes(this.inputs, inputData);
|
97
|
+
return this;
|
98
|
+
}
|
99
|
+
addOutput(outputData) {
|
100
|
+
this.globalMap.unsignedTx.addOutput(outputData);
|
101
|
+
this.outputs.push({
|
102
|
+
unknownKeyVals: [],
|
103
|
+
});
|
104
|
+
const addKeyVals = outputData.unknownKeyVals || [];
|
105
|
+
const outputIndex = this.outputs.length - 1;
|
106
|
+
if (!Array.isArray(addKeyVals)) {
|
107
|
+
throw new Error('unknownKeyVals must be an Array');
|
108
|
+
}
|
109
|
+
addKeyVals.forEach((keyVal) => this.addUnknownKeyValToOutput(outputIndex, keyVal));
|
110
|
+
utils_js_1.addOutputAttributes(this.outputs, outputData);
|
111
|
+
return this;
|
112
|
+
}
|
113
|
+
clearFinalizedInput(inputIndex) {
|
114
|
+
const input = utils_js_1.checkForInput(this.inputs, inputIndex);
|
115
|
+
utils_js_1.inputCheckUncleanFinalized(inputIndex, input);
|
116
|
+
for (const key of Object.keys(input)) {
|
117
|
+
if (![
|
118
|
+
'witnessUtxo',
|
119
|
+
'opcatUtxo',
|
120
|
+
'nonWitnessUtxo',
|
121
|
+
'finalScriptSig',
|
122
|
+
'finalScriptWitness',
|
123
|
+
'unknownKeyVals',
|
124
|
+
].includes(key)) {
|
125
|
+
// @ts-ignore
|
126
|
+
delete input[key];
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return this;
|
130
|
+
}
|
131
|
+
combine(...those) {
|
132
|
+
// Combine this with those.
|
133
|
+
// Return self for chaining.
|
134
|
+
const result = index_js_1.combine([this].concat(those));
|
135
|
+
Object.assign(this, result);
|
136
|
+
return this;
|
137
|
+
}
|
138
|
+
getTransaction() {
|
139
|
+
return this.globalMap.unsignedTx.toBuffer();
|
140
|
+
}
|
141
|
+
}
|
142
|
+
exports.Psbt = Psbt;
|
143
|
+
var utils_js_2 = require("./utils.js");
|
144
|
+
exports.checkForInput = utils_js_2.checkForInput;
|
145
|
+
exports.checkForOutput = utils_js_2.checkForOutput;
|