cashscript 0.7.6 → 0.8.0-next.1
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/README.md +2 -6
- package/dist/{main/Argument.d.ts → Argument.d.ts} +1 -1
- package/dist/{module/Argument.js → Argument.js} +1 -1
- package/dist/{module/Contract.d.ts → Contract.d.ts} +8 -6
- package/dist/{module/Contract.js → Contract.js} +15 -25
- package/dist/{main/Errors.d.ts → Errors.d.ts} +4 -1
- package/dist/{module/Errors.js → Errors.js} +7 -3
- package/dist/{main/SignatureTemplate.d.ts → SignatureTemplate.d.ts} +2 -3
- package/dist/{module/SignatureTemplate.js → SignatureTemplate.js} +4 -5
- package/dist/{module/Transaction.d.ts → Transaction.d.ts} +7 -5
- package/dist/Transaction.js +352 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +3 -0
- package/dist/{main/index.d.ts → index.d.ts} +1 -1
- package/dist/{module/index.js → index.js} +2 -3
- package/dist/{module/interfaces.d.ts → interfaces.d.ts} +33 -6
- package/dist/{module/interfaces.js → interfaces.js} +0 -2
- package/dist/{module/network → network}/BitcoinRpcNetworkProvider.d.ts +2 -3
- package/dist/network/BitcoinRpcNetworkProvider.js +29 -0
- package/dist/{module/network → network}/ElectrumNetworkProvider.js +53 -72
- package/dist/network/FullStackNetworkProvider.js +33 -0
- package/dist/{main/network → network}/index.d.ts +0 -1
- package/dist/{module/network → network}/index.js +0 -1
- package/dist/{main/utils.d.ts → utils.d.ts} +10 -6
- package/dist/{module/utils.js → utils.js} +90 -46
- package/package.json +18 -16
- package/dist/main/Argument.js +0 -60
- package/dist/main/Contract.d.ts +0 -23
- package/dist/main/Contract.js +0 -87
- package/dist/main/Errors.js +0 -84
- package/dist/main/SignatureTemplate.js +0 -45
- package/dist/main/Transaction.d.ts +0 -39
- package/dist/main/Transaction.js +0 -258
- package/dist/main/constants.d.ts +0 -5
- package/dist/main/constants.js +0 -9
- package/dist/main/index.js +0 -50
- package/dist/main/interfaces.d.ts +0 -43
- package/dist/main/interfaces.js +0 -32
- package/dist/main/network/BitboxNetworkProvider.d.ts +0 -26
- package/dist/main/network/BitboxNetworkProvider.js +0 -40
- package/dist/main/network/BitcoinRpcNetworkProvider.d.ts +0 -41
- package/dist/main/network/BitcoinRpcNetworkProvider.js +0 -49
- package/dist/main/network/ElectrumNetworkProvider.js +0 -162
- package/dist/main/network/FullStackNetworkProvider.js +0 -55
- package/dist/main/network/NetworkProvider.js +0 -3
- package/dist/main/network/index.js +0 -15
- package/dist/main/utils.js +0 -205
- package/dist/module/Argument.d.ts +0 -3
- package/dist/module/Errors.d.ts +0 -66
- package/dist/module/SignatureTemplate.d.ts +0 -15
- package/dist/module/Transaction.js +0 -251
- package/dist/module/constants.d.ts +0 -5
- package/dist/module/constants.js +0 -6
- package/dist/module/index.d.ts +0 -10
- package/dist/module/network/BitboxNetworkProvider.d.ts +0 -26
- package/dist/module/network/BitboxNetworkProvider.js +0 -37
- package/dist/module/network/BitcoinRpcNetworkProvider.js +0 -46
- package/dist/module/network/ElectrumNetworkProvider.d.ts +0 -19
- package/dist/module/network/FullStackNetworkProvider.d.ts +0 -40
- package/dist/module/network/FullStackNetworkProvider.js +0 -52
- package/dist/module/network/NetworkProvider.d.ts +0 -31
- package/dist/module/network/index.d.ts +0 -5
- package/dist/module/utils.d.ts +0 -26
- /package/dist/{main/network → network}/ElectrumNetworkProvider.d.ts +0 -0
- /package/dist/{main/network → network}/FullStackNetworkProvider.d.ts +0 -0
- /package/dist/{main/network → network}/NetworkProvider.d.ts +0 -0
- /package/dist/{module/network → network}/NetworkProvider.js +0 -0
package/dist/main/utils.js
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getNetworkPrefix = exports.addressToLockScript = exports.scriptToLockingBytecode = exports.scriptToAddress = exports.meep = exports.buildError = exports.createSighashPreimage = exports.createOpReturnOutput = exports.createInputScript = exports.getTxSizeWithoutInputs = exports.getPreimageSize = exports.getInputSize = exports.validateRecipient = void 0;
|
|
4
|
-
const libauth_1 = require("@bitauth/libauth");
|
|
5
|
-
const utils_1 = require("@cashscript/utils");
|
|
6
|
-
const interfaces_js_1 = require("./interfaces.js");
|
|
7
|
-
const constants_js_1 = require("./constants.js");
|
|
8
|
-
const Errors_js_1 = require("./Errors.js");
|
|
9
|
-
// ////////// PARAMETER VALIDATION ////////////////////////////////////////////
|
|
10
|
-
function validateRecipient(recipient) {
|
|
11
|
-
if (recipient.amount < constants_js_1.DUST_LIMIT) {
|
|
12
|
-
throw new Errors_js_1.OutputSatoshisTooSmallError(recipient.amount);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
exports.validateRecipient = validateRecipient;
|
|
16
|
-
// ////////// SIZE CALCULATIONS ///////////////////////////////////////////////
|
|
17
|
-
function getInputSize(inputScript) {
|
|
18
|
-
const scriptSize = inputScript.byteLength;
|
|
19
|
-
const varIntSize = scriptSize > 252 ? 3 : 1;
|
|
20
|
-
return 32 + 4 + varIntSize + scriptSize + 4;
|
|
21
|
-
}
|
|
22
|
-
exports.getInputSize = getInputSize;
|
|
23
|
-
function getPreimageSize(script) {
|
|
24
|
-
const scriptSize = script.byteLength;
|
|
25
|
-
const varIntSize = scriptSize > 252 ? 3 : 1;
|
|
26
|
-
return 4 + 32 + 32 + 36 + varIntSize + scriptSize + 8 + 4 + 32 + 4 + 4;
|
|
27
|
-
}
|
|
28
|
-
exports.getPreimageSize = getPreimageSize;
|
|
29
|
-
function getTxSizeWithoutInputs(outputs) {
|
|
30
|
-
// Transaction format:
|
|
31
|
-
// Version (4 Bytes)
|
|
32
|
-
// TxIn Count (1 ~ 9B)
|
|
33
|
-
// For each TxIn:
|
|
34
|
-
// Outpoint (36B)
|
|
35
|
-
// Script Length (1 ~ 9B)
|
|
36
|
-
// ScriptSig(?)
|
|
37
|
-
// Sequence (4B)
|
|
38
|
-
// TxOut Count (1 ~ 9B)
|
|
39
|
-
// For each TxOut:
|
|
40
|
-
// Value (8B)
|
|
41
|
-
// Script Length(1 ~ 9B)*
|
|
42
|
-
// Script (?)*
|
|
43
|
-
// LockTime (4B)
|
|
44
|
-
let size = constants_js_1.VERSION_SIZE + constants_js_1.LOCKTIME_SIZE;
|
|
45
|
-
size += outputs.reduce((acc, output) => {
|
|
46
|
-
if (typeof output.to === 'string') {
|
|
47
|
-
return acc + constants_js_1.P2PKH_OUTPUT_SIZE;
|
|
48
|
-
}
|
|
49
|
-
// Size of an OP_RETURN output = byteLength + 8 (amount) + 2 (scriptSize)
|
|
50
|
-
return acc + output.to.byteLength + 8 + 2;
|
|
51
|
-
}, 0);
|
|
52
|
-
// Add tx-out count (accounting for a potential change output)
|
|
53
|
-
size += (0, utils_1.encodeInt)(outputs.length + 1).byteLength;
|
|
54
|
-
return size;
|
|
55
|
-
}
|
|
56
|
-
exports.getTxSizeWithoutInputs = getTxSizeWithoutInputs;
|
|
57
|
-
// ////////// BUILD OBJECTS ///////////////////////////////////////////////////
|
|
58
|
-
function createInputScript(redeemScript, encodedArgs, selector, preimage) {
|
|
59
|
-
// Create unlock script / redeemScriptSig (add potential preimage and selector)
|
|
60
|
-
const unlockScript = encodedArgs.reverse();
|
|
61
|
-
if (preimage !== undefined)
|
|
62
|
-
unlockScript.push(preimage);
|
|
63
|
-
if (selector !== undefined)
|
|
64
|
-
unlockScript.push((0, utils_1.encodeInt)(selector));
|
|
65
|
-
// Create input script and compile it to bytecode
|
|
66
|
-
const inputScript = [...unlockScript, (0, utils_1.scriptToBytecode)(redeemScript)];
|
|
67
|
-
return (0, utils_1.scriptToBytecode)(inputScript);
|
|
68
|
-
}
|
|
69
|
-
exports.createInputScript = createInputScript;
|
|
70
|
-
function createOpReturnOutput(opReturnData) {
|
|
71
|
-
const script = [
|
|
72
|
-
utils_1.Op.OP_RETURN,
|
|
73
|
-
...opReturnData.map((output) => toBin(output)),
|
|
74
|
-
];
|
|
75
|
-
return { to: encodeNullDataScript(script), amount: 0 };
|
|
76
|
-
}
|
|
77
|
-
exports.createOpReturnOutput = createOpReturnOutput;
|
|
78
|
-
function toBin(output) {
|
|
79
|
-
const data = output.replace(/^0x/, '');
|
|
80
|
-
const encode = data === output ? libauth_1.utf8ToBin : libauth_1.hexToBin;
|
|
81
|
-
return encode(data);
|
|
82
|
-
}
|
|
83
|
-
function createSighashPreimage(transaction, input, inputIndex, coveredBytecode, hashtype) {
|
|
84
|
-
const state = (0, libauth_1.createTransactionContextCommon)({
|
|
85
|
-
inputIndex,
|
|
86
|
-
sourceOutput: { satoshis: (0, libauth_1.bigIntToBinUint64LE)(BigInt(input.satoshis)) },
|
|
87
|
-
spendingTransaction: transaction,
|
|
88
|
-
});
|
|
89
|
-
const sighashPreimage = (0, libauth_1.generateSigningSerializationBCH)({
|
|
90
|
-
correspondingOutput: state.correspondingOutput,
|
|
91
|
-
coveredBytecode,
|
|
92
|
-
forkId: new Uint8Array([0, 0, 0]),
|
|
93
|
-
locktime: state.locktime,
|
|
94
|
-
outpointIndex: state.outpointIndex,
|
|
95
|
-
outpointTransactionHash: state.outpointTransactionHash,
|
|
96
|
-
outputValue: state.outputValue,
|
|
97
|
-
sequenceNumber: state.sequenceNumber,
|
|
98
|
-
sha256: { hash: utils_1.sha256 },
|
|
99
|
-
signingSerializationType: new Uint8Array([hashtype]),
|
|
100
|
-
transactionOutpoints: state.transactionOutpoints,
|
|
101
|
-
transactionOutputs: state.transactionOutputs,
|
|
102
|
-
transactionSequenceNumbers: state.transactionSequenceNumbers,
|
|
103
|
-
version: 2,
|
|
104
|
-
});
|
|
105
|
-
return sighashPreimage;
|
|
106
|
-
}
|
|
107
|
-
exports.createSighashPreimage = createSighashPreimage;
|
|
108
|
-
function buildError(reason, meepStr) {
|
|
109
|
-
const require = [
|
|
110
|
-
Errors_js_1.Reason.EVAL_FALSE, Errors_js_1.Reason.VERIFY, Errors_js_1.Reason.EQUALVERIFY, Errors_js_1.Reason.CHECKMULTISIGVERIFY,
|
|
111
|
-
Errors_js_1.Reason.CHECKSIGVERIFY, Errors_js_1.Reason.CHECKDATASIGVERIFY, Errors_js_1.Reason.NUMEQUALVERIFY,
|
|
112
|
-
];
|
|
113
|
-
const timeCheck = [Errors_js_1.Reason.NEGATIVE_LOCKTIME, Errors_js_1.Reason.UNSATISFIED_LOCKTIME];
|
|
114
|
-
const sigCheck = [
|
|
115
|
-
Errors_js_1.Reason.SIG_COUNT, Errors_js_1.Reason.PUBKEY_COUNT, Errors_js_1.Reason.SIG_HASHTYPE, Errors_js_1.Reason.SIG_DER,
|
|
116
|
-
Errors_js_1.Reason.SIG_HIGH_S, Errors_js_1.Reason.SIG_NULLFAIL, Errors_js_1.Reason.SIG_BADLENGTH, Errors_js_1.Reason.SIG_NONSCHNORR,
|
|
117
|
-
];
|
|
118
|
-
if (toRegExp(require).test(reason)) {
|
|
119
|
-
return new Errors_js_1.FailedRequireError(reason, meepStr);
|
|
120
|
-
}
|
|
121
|
-
if (toRegExp(timeCheck).test(reason)) {
|
|
122
|
-
return new Errors_js_1.FailedTimeCheckError(reason, meepStr);
|
|
123
|
-
}
|
|
124
|
-
if (toRegExp(sigCheck).test(reason)) {
|
|
125
|
-
return new Errors_js_1.FailedSigCheckError(reason, meepStr);
|
|
126
|
-
}
|
|
127
|
-
return new Errors_js_1.FailedTransactionError(reason, meepStr);
|
|
128
|
-
}
|
|
129
|
-
exports.buildError = buildError;
|
|
130
|
-
function toRegExp(reasons) {
|
|
131
|
-
return new RegExp(reasons.join('|').replace(/\(/g, '\\(').replace(/\)/g, '\\)'));
|
|
132
|
-
}
|
|
133
|
-
// ////////// MISC ////////////////////////////////////////////////////////////
|
|
134
|
-
function meep(tx, utxos, script) {
|
|
135
|
-
const scriptPubkey = (0, libauth_1.binToHex)(scriptToLockingBytecode(script));
|
|
136
|
-
return `meep debug --tx=${tx} --idx=0 --amt=${utxos[0].satoshis} --pkscript=${scriptPubkey}`;
|
|
137
|
-
}
|
|
138
|
-
exports.meep = meep;
|
|
139
|
-
function scriptToAddress(script, network) {
|
|
140
|
-
const lockingBytecode = scriptToLockingBytecode(script);
|
|
141
|
-
const prefix = getNetworkPrefix(network);
|
|
142
|
-
const address = (0, libauth_1.lockingBytecodeToCashAddress)(lockingBytecode, prefix);
|
|
143
|
-
return address;
|
|
144
|
-
}
|
|
145
|
-
exports.scriptToAddress = scriptToAddress;
|
|
146
|
-
function scriptToLockingBytecode(script) {
|
|
147
|
-
const scriptHash = (0, utils_1.hash160)((0, utils_1.scriptToBytecode)(script));
|
|
148
|
-
const addressContents = { payload: scriptHash, type: libauth_1.AddressType.p2sh };
|
|
149
|
-
const lockingBytecode = (0, libauth_1.addressContentsToLockingBytecode)(addressContents);
|
|
150
|
-
return lockingBytecode;
|
|
151
|
-
}
|
|
152
|
-
exports.scriptToLockingBytecode = scriptToLockingBytecode;
|
|
153
|
-
/**
|
|
154
|
-
* Helper function to convert an address to a locking script
|
|
155
|
-
*
|
|
156
|
-
* @param address Address to convert to locking script
|
|
157
|
-
*
|
|
158
|
-
* @returns a locking script corresponding to the passed address
|
|
159
|
-
*/
|
|
160
|
-
function addressToLockScript(address) {
|
|
161
|
-
const result = (0, libauth_1.cashAddressToLockingBytecode)(address);
|
|
162
|
-
if (typeof result === 'string')
|
|
163
|
-
throw new Error(result);
|
|
164
|
-
return result.bytecode;
|
|
165
|
-
}
|
|
166
|
-
exports.addressToLockScript = addressToLockScript;
|
|
167
|
-
function getNetworkPrefix(network) {
|
|
168
|
-
switch (network) {
|
|
169
|
-
case interfaces_js_1.Network.MAINNET:
|
|
170
|
-
return 'bitcoincash';
|
|
171
|
-
case interfaces_js_1.Network.STAGING:
|
|
172
|
-
case interfaces_js_1.Network.TESTNET4:
|
|
173
|
-
case interfaces_js_1.Network.TESTNET:
|
|
174
|
-
case interfaces_js_1.Network.TESTNET3:
|
|
175
|
-
case interfaces_js_1.Network.CHIPNET:
|
|
176
|
-
return 'bchtest';
|
|
177
|
-
case interfaces_js_1.Network.REGTEST:
|
|
178
|
-
return 'bchreg';
|
|
179
|
-
default:
|
|
180
|
-
return 'bitcoincash';
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
exports.getNetworkPrefix = getNetworkPrefix;
|
|
184
|
-
// ////////////////////////////////////////////////////////////////////////////
|
|
185
|
-
// For encoding OP_RETURN data (doesn't require BIP62.3 / MINIMALDATA)
|
|
186
|
-
function encodeNullDataScript(chunks) {
|
|
187
|
-
return (0, libauth_1.flattenBinArray)(chunks.map((chunk) => {
|
|
188
|
-
if (typeof chunk === 'number') {
|
|
189
|
-
return new Uint8Array([chunk]);
|
|
190
|
-
}
|
|
191
|
-
const pushdataOpcode = getPushDataOpcode(chunk);
|
|
192
|
-
return new Uint8Array([...pushdataOpcode, ...chunk]);
|
|
193
|
-
}));
|
|
194
|
-
}
|
|
195
|
-
function getPushDataOpcode(data) {
|
|
196
|
-
const { byteLength } = data;
|
|
197
|
-
if (byteLength === 0)
|
|
198
|
-
return Uint8Array.from([0x4c, 0x00]);
|
|
199
|
-
if (byteLength < 76)
|
|
200
|
-
return Uint8Array.from([byteLength]);
|
|
201
|
-
if (byteLength < 256)
|
|
202
|
-
return Uint8Array.from([0x4c, byteLength]);
|
|
203
|
-
throw Error('Pushdata too large');
|
|
204
|
-
}
|
|
205
|
-
//# sourceMappingURL=utils.js.map
|
package/dist/module/Errors.d.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { Type } from '@cashscript/utils';
|
|
2
|
-
export declare class TypeError extends Error {
|
|
3
|
-
constructor(actual: string, expected: Type);
|
|
4
|
-
}
|
|
5
|
-
export declare class OutputSatoshisTooSmallError extends Error {
|
|
6
|
-
constructor(satoshis: number);
|
|
7
|
-
}
|
|
8
|
-
export declare class FailedTransactionError extends Error {
|
|
9
|
-
reason: string;
|
|
10
|
-
meep: string;
|
|
11
|
-
constructor(reason: string, meep: string);
|
|
12
|
-
}
|
|
13
|
-
export declare class FailedRequireError extends FailedTransactionError {
|
|
14
|
-
}
|
|
15
|
-
export declare class FailedTimeCheckError extends FailedTransactionError {
|
|
16
|
-
}
|
|
17
|
-
export declare class FailedSigCheckError extends FailedTransactionError {
|
|
18
|
-
}
|
|
19
|
-
export declare enum Reason {
|
|
20
|
-
EVAL_FALSE = "Script evaluated without error but finished with a false/empty top stack element",
|
|
21
|
-
VERIFY = "Script failed an OP_VERIFY operation",
|
|
22
|
-
EQUALVERIFY = "Script failed an OP_EQUALVERIFY operation",
|
|
23
|
-
CHECKMULTISIGVERIFY = "Script failed an OP_CHECKMULTISIGVERIFY operation",
|
|
24
|
-
CHECKSIGVERIFY = "Script failed an OP_CHECKSIGVERIFY operation",
|
|
25
|
-
CHECKDATASIGVERIFY = "Script failed an OP_CHECKDATASIGVERIFY operation",
|
|
26
|
-
NUMEQUALVERIFY = "Script failed an OP_NUMEQUALVERIFY operation",
|
|
27
|
-
SCRIPT_SIZE = "Script is too big",
|
|
28
|
-
PUSH_SIZE = "Push value size limit exceeded",
|
|
29
|
-
OP_COUNT = "Operation limit exceeded",
|
|
30
|
-
STACK_SIZE = "Stack size limit exceeded",
|
|
31
|
-
SIG_COUNT = "Signature count negative or greater than pubkey count",
|
|
32
|
-
PUBKEY_COUNT = "Pubkey count negative or limit exceeded",
|
|
33
|
-
INVALID_OPERAND_SIZE = "Invalid operand size",
|
|
34
|
-
INVALID_NUMBER_RANGE = "Given operand is not a number within the valid range",
|
|
35
|
-
IMPOSSIBLE_ENCODING = "The requested encoding is impossible to satisfy",
|
|
36
|
-
INVALID_SPLIT_RANGE = "Invalid OP_SPLIT range",
|
|
37
|
-
INVALID_BIT_COUNT = "Invalid number of bit set in OP_CHECKMULTISIG",
|
|
38
|
-
BAD_OPCODE = "Opcode missing or not understood",
|
|
39
|
-
DISABLED_OPCODE = "Attempted to use a disabled opcode",
|
|
40
|
-
INVALID_STACK_OPERATION = "Operation not valid with the current stack size",
|
|
41
|
-
INVALID_ALTSTACK_OPERATION = "Operation not valid with the current altstack size",
|
|
42
|
-
OP_RETURN = "OP_RETURN was encountered",
|
|
43
|
-
UNBALANCED_CONDITIONAL = "Invalid OP_IF construction",
|
|
44
|
-
DIV_BY_ZERO = "Division by zero error",
|
|
45
|
-
MOD_BY_ZERO = "Modulo by zero error",
|
|
46
|
-
INVALID_BITFIELD_SIZE = "Bitfield of unexpected size error",
|
|
47
|
-
INVALID_BIT_RANGE = "Bitfield's bit out of the expected range",
|
|
48
|
-
NEGATIVE_LOCKTIME = "Negative locktime",
|
|
49
|
-
UNSATISFIED_LOCKTIME = "Locktime requirement not satisfied",
|
|
50
|
-
SIG_HASHTYPE = "Signature hash type missing or not understood",
|
|
51
|
-
SIG_DER = "Non-canonical DER signature",
|
|
52
|
-
MINIMALDATA = "Data push larger than necessary",
|
|
53
|
-
SIG_PUSHONLY = "Only push operators allowed in signature scripts",
|
|
54
|
-
SIG_HIGH_S = "Non-canonical signature: S value is unnecessarily high",
|
|
55
|
-
MINIMALIF = "OP_IF/NOTIF argument must be minimal",
|
|
56
|
-
SIG_NULLFAIL = "Signature must be zero for failed CHECK(MULTI)SIG operation",
|
|
57
|
-
SIG_BADLENGTH = "Signature cannot be 65 bytes in CHECKMULTISIG",
|
|
58
|
-
SIG_NONSCHNORR = "Only Schnorr signatures allowed in this operation",
|
|
59
|
-
DISCOURAGE_UPGRADABLE_NOPS = "NOPx reserved for soft-fork upgrades",
|
|
60
|
-
PUBKEYTYPE = "Public key is neither compressed or uncompressed",
|
|
61
|
-
CLEANSTACK = "Script did not clean its stack",
|
|
62
|
-
NONCOMPRESSED_PUBKEY = "Using non-compressed public key",
|
|
63
|
-
ILLEGAL_FORKID = "Illegal use of SIGHASH_FORKID",
|
|
64
|
-
MUST_USE_FORKID = "Signature must use SIGHASH_FORKID",
|
|
65
|
-
UNKNOWN = "unknown error"
|
|
66
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Secp256k1 } from '@bitauth/libauth';
|
|
2
|
-
import { HashType, SignatureAlgorithm } from './interfaces.js';
|
|
3
|
-
export default class SignatureTemplate {
|
|
4
|
-
private hashtype;
|
|
5
|
-
private signatureAlgorithm;
|
|
6
|
-
private privateKey;
|
|
7
|
-
constructor(signer: Keypair | Uint8Array | string, hashtype?: HashType, signatureAlgorithm?: SignatureAlgorithm);
|
|
8
|
-
generateSignature(payload: Uint8Array, secp256k1: Secp256k1, bchForkId?: boolean): Uint8Array;
|
|
9
|
-
getHashType(bchForkId?: boolean): number;
|
|
10
|
-
getPublicKey(secp256k1: Secp256k1): Uint8Array;
|
|
11
|
-
}
|
|
12
|
-
interface Keypair {
|
|
13
|
-
toWIF(): string;
|
|
14
|
-
}
|
|
15
|
-
export {};
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { bigIntToBinUint64LE, hexToBin, binToHex, encodeTransaction, addressContentsToLockingBytecode, AddressType, decodeTransaction, instantiateSecp256k1, } from '@bitauth/libauth';
|
|
11
|
-
import delay from 'delay';
|
|
12
|
-
import { hash160, hash256, placeholder, scriptToBytecode, } from '@cashscript/utils';
|
|
13
|
-
import { isSignableUtxo, } from './interfaces.js';
|
|
14
|
-
import { meep, createInputScript, getInputSize, createOpReturnOutput, getTxSizeWithoutInputs, getPreimageSize, buildError, addressToLockScript, createSighashPreimage, validateRecipient, } from './utils.js';
|
|
15
|
-
import { P2SH_OUTPUT_SIZE, DUST_LIMIT } from './constants.js';
|
|
16
|
-
import SignatureTemplate from './SignatureTemplate.js';
|
|
17
|
-
const bip68 = require('bip68');
|
|
18
|
-
export class Transaction {
|
|
19
|
-
constructor(address, provider, redeemScript, abiFunction, args, selector) {
|
|
20
|
-
this.address = address;
|
|
21
|
-
this.provider = provider;
|
|
22
|
-
this.redeemScript = redeemScript;
|
|
23
|
-
this.abiFunction = abiFunction;
|
|
24
|
-
this.args = args;
|
|
25
|
-
this.selector = selector;
|
|
26
|
-
this.inputs = [];
|
|
27
|
-
this.outputs = [];
|
|
28
|
-
this.sequence = 0xfffffffe;
|
|
29
|
-
this.feePerByte = 1.0;
|
|
30
|
-
this.minChange = DUST_LIMIT;
|
|
31
|
-
}
|
|
32
|
-
from(inputOrInputs) {
|
|
33
|
-
if (!Array.isArray(inputOrInputs)) {
|
|
34
|
-
inputOrInputs = [inputOrInputs];
|
|
35
|
-
}
|
|
36
|
-
this.inputs = this.inputs.concat(inputOrInputs);
|
|
37
|
-
return this;
|
|
38
|
-
}
|
|
39
|
-
experimentalFromP2PKH(inputOrInputs, template) {
|
|
40
|
-
if (!Array.isArray(inputOrInputs)) {
|
|
41
|
-
inputOrInputs = [inputOrInputs];
|
|
42
|
-
}
|
|
43
|
-
inputOrInputs = inputOrInputs.map((input) => (Object.assign(Object.assign({}, input), { template })));
|
|
44
|
-
this.inputs = this.inputs.concat(inputOrInputs);
|
|
45
|
-
return this;
|
|
46
|
-
}
|
|
47
|
-
to(toOrOutputs, amount) {
|
|
48
|
-
if (typeof toOrOutputs === 'string' && typeof amount === 'number') {
|
|
49
|
-
return this.to([{ to: toOrOutputs, amount }]);
|
|
50
|
-
}
|
|
51
|
-
if (Array.isArray(toOrOutputs) && amount === undefined) {
|
|
52
|
-
toOrOutputs.forEach(validateRecipient);
|
|
53
|
-
this.outputs = this.outputs.concat(toOrOutputs);
|
|
54
|
-
return this;
|
|
55
|
-
}
|
|
56
|
-
throw new Error('Incorrect arguments passed to function \'to\'');
|
|
57
|
-
}
|
|
58
|
-
withOpReturn(chunks) {
|
|
59
|
-
this.outputs.push(createOpReturnOutput(chunks));
|
|
60
|
-
return this;
|
|
61
|
-
}
|
|
62
|
-
withAge(age) {
|
|
63
|
-
this.sequence = bip68.encode({ blocks: age });
|
|
64
|
-
return this;
|
|
65
|
-
}
|
|
66
|
-
withTime(time) {
|
|
67
|
-
this.locktime = time;
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
withHardcodedFee(hardcodedFee) {
|
|
71
|
-
this.hardcodedFee = hardcodedFee;
|
|
72
|
-
return this;
|
|
73
|
-
}
|
|
74
|
-
withFeePerByte(feePerByte) {
|
|
75
|
-
this.feePerByte = feePerByte;
|
|
76
|
-
return this;
|
|
77
|
-
}
|
|
78
|
-
withMinChange(minChange) {
|
|
79
|
-
this.minChange = minChange;
|
|
80
|
-
return this;
|
|
81
|
-
}
|
|
82
|
-
withoutChange() {
|
|
83
|
-
return this.withMinChange(Number.MAX_VALUE);
|
|
84
|
-
}
|
|
85
|
-
build() {
|
|
86
|
-
var _a;
|
|
87
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
88
|
-
this.locktime = (_a = this.locktime) !== null && _a !== void 0 ? _a : yield this.provider.getBlockHeight();
|
|
89
|
-
yield this.setInputsAndOutputs();
|
|
90
|
-
const secp256k1 = yield instantiateSecp256k1();
|
|
91
|
-
const bytecode = scriptToBytecode(this.redeemScript);
|
|
92
|
-
const inputs = this.inputs.map((utxo) => ({
|
|
93
|
-
outpointIndex: utxo.vout,
|
|
94
|
-
outpointTransactionHash: hexToBin(utxo.txid),
|
|
95
|
-
sequenceNumber: this.sequence,
|
|
96
|
-
unlockingBytecode: new Uint8Array(),
|
|
97
|
-
}));
|
|
98
|
-
const outputs = this.outputs.map((output) => {
|
|
99
|
-
const lockingBytecode = typeof output.to === 'string'
|
|
100
|
-
? addressToLockScript(output.to)
|
|
101
|
-
: output.to;
|
|
102
|
-
const satoshis = bigIntToBinUint64LE(BigInt(output.amount));
|
|
103
|
-
return { lockingBytecode, satoshis };
|
|
104
|
-
});
|
|
105
|
-
const transaction = {
|
|
106
|
-
inputs,
|
|
107
|
-
locktime: this.locktime,
|
|
108
|
-
outputs,
|
|
109
|
-
version: 2,
|
|
110
|
-
};
|
|
111
|
-
const inputScripts = [];
|
|
112
|
-
this.inputs.forEach((utxo, i) => {
|
|
113
|
-
// UTXO's with signature templates are signed using P2PKH
|
|
114
|
-
if (isSignableUtxo(utxo)) {
|
|
115
|
-
const pubkey = utxo.template.getPublicKey(secp256k1);
|
|
116
|
-
const pubkeyHash = hash160(pubkey);
|
|
117
|
-
const addressContents = { payload: pubkeyHash, type: AddressType.p2pkh };
|
|
118
|
-
const prevOutScript = addressContentsToLockingBytecode(addressContents);
|
|
119
|
-
const hashtype = utxo.template.getHashType();
|
|
120
|
-
const preimage = createSighashPreimage(transaction, utxo, i, prevOutScript, hashtype);
|
|
121
|
-
const sighash = hash256(preimage);
|
|
122
|
-
const signature = utxo.template.generateSignature(sighash, secp256k1);
|
|
123
|
-
const inputScript = scriptToBytecode([signature, pubkey]);
|
|
124
|
-
inputScripts.push(inputScript);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
let covenantHashType = -1;
|
|
128
|
-
const completeArgs = this.args.map((arg) => {
|
|
129
|
-
if (!(arg instanceof SignatureTemplate))
|
|
130
|
-
return arg;
|
|
131
|
-
// First signature is used for sighash preimage (maybe not the best way)
|
|
132
|
-
if (covenantHashType < 0)
|
|
133
|
-
covenantHashType = arg.getHashType();
|
|
134
|
-
const preimage = createSighashPreimage(transaction, utxo, i, bytecode, arg.getHashType());
|
|
135
|
-
const sighash = hash256(preimage);
|
|
136
|
-
return arg.generateSignature(sighash, secp256k1);
|
|
137
|
-
});
|
|
138
|
-
const preimage = this.abiFunction.covenant
|
|
139
|
-
? createSighashPreimage(transaction, utxo, i, bytecode, covenantHashType)
|
|
140
|
-
: undefined;
|
|
141
|
-
const inputScript = createInputScript(this.redeemScript, completeArgs, this.selector, preimage);
|
|
142
|
-
inputScripts.push(inputScript);
|
|
143
|
-
});
|
|
144
|
-
inputScripts.forEach((script, i) => {
|
|
145
|
-
transaction.inputs[i].unlockingBytecode = script;
|
|
146
|
-
});
|
|
147
|
-
return binToHex(encodeTransaction(transaction));
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
send(raw) {
|
|
151
|
-
var _a;
|
|
152
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
-
const tx = yield this.build();
|
|
154
|
-
try {
|
|
155
|
-
const txid = yield this.provider.sendRawTransaction(tx);
|
|
156
|
-
return raw ? yield this.getTxDetails(txid, raw) : yield this.getTxDetails(txid);
|
|
157
|
-
}
|
|
158
|
-
catch (e) {
|
|
159
|
-
const reason = (_a = e.error) !== null && _a !== void 0 ? _a : e.message;
|
|
160
|
-
throw buildError(reason, meep(tx, this.inputs, this.redeemScript));
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
getTxDetails(txid, raw) {
|
|
165
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
166
|
-
for (let retries = 0; retries < 1200; retries += 1) {
|
|
167
|
-
yield delay(500);
|
|
168
|
-
try {
|
|
169
|
-
const hex = yield this.provider.getRawTransaction(txid);
|
|
170
|
-
if (raw)
|
|
171
|
-
return hex;
|
|
172
|
-
const libauthTransaction = decodeTransaction(hexToBin(hex));
|
|
173
|
-
return Object.assign(Object.assign({}, libauthTransaction), { txid, hex });
|
|
174
|
-
}
|
|
175
|
-
catch (ignored) {
|
|
176
|
-
// ignored
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
// Should not happen
|
|
180
|
-
throw new Error('Could not retrieve transaction details for over 10 minutes');
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
meep() {
|
|
184
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
185
|
-
const tx = yield this.build();
|
|
186
|
-
return meep(tx, this.inputs, this.redeemScript);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
setInputsAndOutputs() {
|
|
190
|
-
var _a;
|
|
191
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
192
|
-
if (this.outputs.length === 0) {
|
|
193
|
-
throw Error('Attempted to build a transaction without outputs');
|
|
194
|
-
}
|
|
195
|
-
// Replace all SignatureTemplate with 65-length placeholder Uint8Arrays
|
|
196
|
-
const placeholderArgs = this.args.map((arg) => (arg instanceof SignatureTemplate ? placeholder(65) : arg));
|
|
197
|
-
// Create a placeholder preimage of the correct size
|
|
198
|
-
const placeholderPreimage = this.abiFunction.covenant
|
|
199
|
-
? placeholder(getPreimageSize(scriptToBytecode(this.redeemScript)))
|
|
200
|
-
: undefined;
|
|
201
|
-
// Create a placeholder input script for size calculation using the placeholder
|
|
202
|
-
// arguments and correctly sized placeholder preimage
|
|
203
|
-
const placeholderScript = createInputScript(this.redeemScript, placeholderArgs, this.selector, placeholderPreimage);
|
|
204
|
-
// Add one extra byte per input to over-estimate tx-in count
|
|
205
|
-
const inputSize = getInputSize(placeholderScript) + 1;
|
|
206
|
-
// Calculate amount to send and base fee (excluding additional fees per UTXO)
|
|
207
|
-
const amount = this.outputs.reduce((acc, output) => acc + output.amount, 0);
|
|
208
|
-
let fee = (_a = this.hardcodedFee) !== null && _a !== void 0 ? _a : getTxSizeWithoutInputs(this.outputs) * this.feePerByte;
|
|
209
|
-
// Select and gather UTXOs and calculate fees and available funds
|
|
210
|
-
let satsAvailable = 0;
|
|
211
|
-
if (this.inputs.length > 0) {
|
|
212
|
-
// If inputs are already defined, the user provided the UTXOs
|
|
213
|
-
// and we perform no further UTXO selection
|
|
214
|
-
if (!this.hardcodedFee)
|
|
215
|
-
fee += this.inputs.length * inputSize * this.feePerByte;
|
|
216
|
-
satsAvailable = this.inputs.reduce((acc, input) => acc + input.satoshis, 0);
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
// If inputs are not defined yet, we retrieve the contract's UTXOs and perform selection
|
|
220
|
-
const utxos = yield this.provider.getUtxos(this.address);
|
|
221
|
-
// We sort the UTXOs mainly so there is consistent behaviour between network providers
|
|
222
|
-
// even if they report UTXOs in a different order
|
|
223
|
-
utxos.sort((a, b) => b.satoshis - a.satoshis);
|
|
224
|
-
for (const utxo of utxos) {
|
|
225
|
-
this.inputs.push(utxo);
|
|
226
|
-
satsAvailable += utxo.satoshis;
|
|
227
|
-
if (!this.hardcodedFee)
|
|
228
|
-
fee += inputSize * this.feePerByte;
|
|
229
|
-
if (satsAvailable > amount + fee)
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
// Fee per byte can be a decimal number, but we need the total fee to be an integer
|
|
234
|
-
fee = Math.ceil(fee);
|
|
235
|
-
// Calculate change and check available funds
|
|
236
|
-
let change = satsAvailable - amount - fee;
|
|
237
|
-
if (change < 0) {
|
|
238
|
-
throw new Error(`Insufficient funds: available (${satsAvailable}) < needed (${amount + fee}).`);
|
|
239
|
-
}
|
|
240
|
-
// Account for the fee of a change output
|
|
241
|
-
if (!this.hardcodedFee) {
|
|
242
|
-
change -= P2SH_OUTPUT_SIZE;
|
|
243
|
-
}
|
|
244
|
-
// Add a change output if applicable
|
|
245
|
-
if (change >= DUST_LIMIT && change >= this.minChange) {
|
|
246
|
-
this.outputs.push({ to: this.address, amount: change });
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
//# sourceMappingURL=Transaction.js.map
|
package/dist/module/constants.js
DELETED
package/dist/module/index.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import SignatureTemplate from './SignatureTemplate.js';
|
|
2
|
-
export { SignatureTemplate };
|
|
3
|
-
export { Contract, ContractFunction } from './Contract.js';
|
|
4
|
-
export { Transaction } from './Transaction.js';
|
|
5
|
-
export { Argument } from './Argument.js';
|
|
6
|
-
export { Artifact, AbiFunction, AbiInput } from '@cashscript/utils';
|
|
7
|
-
export * as utils from '@cashscript/utils';
|
|
8
|
-
export { Utxo, Recipient, SignatureAlgorithm, HashType, Network, } from './interfaces.js';
|
|
9
|
-
export * from './Errors.js';
|
|
10
|
-
export { NetworkProvider, BitboxNetworkProvider, BitcoinRpcNetworkProvider, ElectrumNetworkProvider, FullStackNetworkProvider, } from './network/index.js';
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { Utxo, Network } from '../interfaces.js';
|
|
2
|
-
import NetworkProvider from './NetworkProvider.js';
|
|
3
|
-
export default class BitboxNetworkProvider implements NetworkProvider {
|
|
4
|
-
network: Network;
|
|
5
|
-
private bitbox;
|
|
6
|
-
constructor(network: Network, bitbox: BITBOX);
|
|
7
|
-
getUtxos(address: string): Promise<Utxo[]>;
|
|
8
|
-
getBlockHeight(): Promise<number>;
|
|
9
|
-
getRawTransaction(txid: string): Promise<string>;
|
|
10
|
-
sendRawTransaction(txHex: string): Promise<string>;
|
|
11
|
-
}
|
|
12
|
-
interface BITBOX {
|
|
13
|
-
Address: {
|
|
14
|
-
utxo(address: string): Promise<{
|
|
15
|
-
utxos: Utxo[];
|
|
16
|
-
}>;
|
|
17
|
-
};
|
|
18
|
-
Blockchain: {
|
|
19
|
-
getBlockCount(): Promise<number>;
|
|
20
|
-
};
|
|
21
|
-
RawTransactions: {
|
|
22
|
-
getRawTransaction(txid: string): Promise<string>;
|
|
23
|
-
sendRawTransaction(txHex: string): Promise<string>;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
export {};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
export default class BitboxNetworkProvider {
|
|
11
|
-
constructor(network, bitbox) {
|
|
12
|
-
this.network = network;
|
|
13
|
-
this.bitbox = bitbox;
|
|
14
|
-
}
|
|
15
|
-
getUtxos(address) {
|
|
16
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
-
const { utxos } = yield this.bitbox.Address.utxo(address);
|
|
18
|
-
return utxos;
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
getBlockHeight() {
|
|
22
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
-
return this.bitbox.Blockchain.getBlockCount();
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
getRawTransaction(txid) {
|
|
27
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
return this.bitbox.RawTransactions.getRawTransaction(txid);
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
sendRawTransaction(txHex) {
|
|
32
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
-
return this.bitbox.RawTransactions.sendRawTransaction(txHex);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=BitboxNetworkProvider.js.map
|