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.
Files changed (67) hide show
  1. package/README.md +2 -6
  2. package/dist/{main/Argument.d.ts → Argument.d.ts} +1 -1
  3. package/dist/{module/Argument.js → Argument.js} +1 -1
  4. package/dist/{module/Contract.d.ts → Contract.d.ts} +8 -6
  5. package/dist/{module/Contract.js → Contract.js} +15 -25
  6. package/dist/{main/Errors.d.ts → Errors.d.ts} +4 -1
  7. package/dist/{module/Errors.js → Errors.js} +7 -3
  8. package/dist/{main/SignatureTemplate.d.ts → SignatureTemplate.d.ts} +2 -3
  9. package/dist/{module/SignatureTemplate.js → SignatureTemplate.js} +4 -5
  10. package/dist/{module/Transaction.d.ts → Transaction.d.ts} +7 -5
  11. package/dist/Transaction.js +352 -0
  12. package/dist/constants.d.ts +2 -0
  13. package/dist/constants.js +3 -0
  14. package/dist/{main/index.d.ts → index.d.ts} +1 -1
  15. package/dist/{module/index.js → index.js} +2 -3
  16. package/dist/{module/interfaces.d.ts → interfaces.d.ts} +33 -6
  17. package/dist/{module/interfaces.js → interfaces.js} +0 -2
  18. package/dist/{module/network → network}/BitcoinRpcNetworkProvider.d.ts +2 -3
  19. package/dist/network/BitcoinRpcNetworkProvider.js +29 -0
  20. package/dist/{module/network → network}/ElectrumNetworkProvider.js +53 -72
  21. package/dist/network/FullStackNetworkProvider.js +33 -0
  22. package/dist/{main/network → network}/index.d.ts +0 -1
  23. package/dist/{module/network → network}/index.js +0 -1
  24. package/dist/{main/utils.d.ts → utils.d.ts} +10 -6
  25. package/dist/{module/utils.js → utils.js} +90 -46
  26. package/package.json +18 -16
  27. package/dist/main/Argument.js +0 -60
  28. package/dist/main/Contract.d.ts +0 -23
  29. package/dist/main/Contract.js +0 -87
  30. package/dist/main/Errors.js +0 -84
  31. package/dist/main/SignatureTemplate.js +0 -45
  32. package/dist/main/Transaction.d.ts +0 -39
  33. package/dist/main/Transaction.js +0 -258
  34. package/dist/main/constants.d.ts +0 -5
  35. package/dist/main/constants.js +0 -9
  36. package/dist/main/index.js +0 -50
  37. package/dist/main/interfaces.d.ts +0 -43
  38. package/dist/main/interfaces.js +0 -32
  39. package/dist/main/network/BitboxNetworkProvider.d.ts +0 -26
  40. package/dist/main/network/BitboxNetworkProvider.js +0 -40
  41. package/dist/main/network/BitcoinRpcNetworkProvider.d.ts +0 -41
  42. package/dist/main/network/BitcoinRpcNetworkProvider.js +0 -49
  43. package/dist/main/network/ElectrumNetworkProvider.js +0 -162
  44. package/dist/main/network/FullStackNetworkProvider.js +0 -55
  45. package/dist/main/network/NetworkProvider.js +0 -3
  46. package/dist/main/network/index.js +0 -15
  47. package/dist/main/utils.js +0 -205
  48. package/dist/module/Argument.d.ts +0 -3
  49. package/dist/module/Errors.d.ts +0 -66
  50. package/dist/module/SignatureTemplate.d.ts +0 -15
  51. package/dist/module/Transaction.js +0 -251
  52. package/dist/module/constants.d.ts +0 -5
  53. package/dist/module/constants.js +0 -6
  54. package/dist/module/index.d.ts +0 -10
  55. package/dist/module/network/BitboxNetworkProvider.d.ts +0 -26
  56. package/dist/module/network/BitboxNetworkProvider.js +0 -37
  57. package/dist/module/network/BitcoinRpcNetworkProvider.js +0 -46
  58. package/dist/module/network/ElectrumNetworkProvider.d.ts +0 -19
  59. package/dist/module/network/FullStackNetworkProvider.d.ts +0 -40
  60. package/dist/module/network/FullStackNetworkProvider.js +0 -52
  61. package/dist/module/network/NetworkProvider.d.ts +0 -31
  62. package/dist/module/network/index.d.ts +0 -5
  63. package/dist/module/utils.d.ts +0 -26
  64. /package/dist/{main/network → network}/ElectrumNetworkProvider.d.ts +0 -0
  65. /package/dist/{main/network → network}/FullStackNetworkProvider.d.ts +0 -0
  66. /package/dist/{main/network → network}/NetworkProvider.d.ts +0 -0
  67. /package/dist/{module/network → network}/NetworkProvider.js +0 -0
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.encodeArgument = void 0;
7
- const libauth_1 = require("@bitauth/libauth");
8
- const utils_1 = require("@cashscript/utils");
9
- const Errors_js_1 = require("./Errors.js");
10
- const SignatureTemplate_js_1 = __importDefault(require("./SignatureTemplate.js"));
11
- function encodeArgument(argument, typeStr) {
12
- let type = (0, utils_1.parseType)(typeStr);
13
- if (type === utils_1.PrimitiveType.BOOL) {
14
- if (typeof argument !== 'boolean') {
15
- throw new Errors_js_1.TypeError(typeof argument, type);
16
- }
17
- return (0, utils_1.encodeBool)(argument);
18
- }
19
- if (type === utils_1.PrimitiveType.INT) {
20
- if (typeof argument !== 'number' && typeof argument !== 'bigint') {
21
- throw new Errors_js_1.TypeError(typeof argument, type);
22
- }
23
- return (0, utils_1.encodeInt)(argument);
24
- }
25
- if (type === utils_1.PrimitiveType.STRING) {
26
- if (typeof argument !== 'string') {
27
- throw new Errors_js_1.TypeError(typeof argument, type);
28
- }
29
- return (0, utils_1.encodeString)(argument);
30
- }
31
- if (type === utils_1.PrimitiveType.SIG && argument instanceof SignatureTemplate_js_1.default)
32
- return argument;
33
- // Convert hex string to Uint8Array
34
- if (typeof argument === 'string') {
35
- if (argument.startsWith('0x')) {
36
- argument = argument.slice(2);
37
- }
38
- argument = (0, libauth_1.hexToBin)(argument);
39
- }
40
- if (!(argument instanceof Uint8Array)) {
41
- throw Error(`Value for type ${type} should be a Uint8Array or hex string`);
42
- }
43
- // Redefine SIG as a bytes65 so it is included in the size checks below
44
- // Note that ONLY Schnorr signatures are accepted
45
- if (type === utils_1.PrimitiveType.SIG && argument.byteLength !== 0) {
46
- type = new utils_1.BytesType(65);
47
- }
48
- // Redefine SIG as a bytes64 so it is included in the size checks below
49
- // Note that ONLY Schnorr signatures are accepted
50
- if (type === utils_1.PrimitiveType.DATASIG && argument.byteLength !== 0) {
51
- type = new utils_1.BytesType(64);
52
- }
53
- // Bounded bytes types require a correctly sized argument
54
- if (type instanceof utils_1.BytesType && type.bound && argument.byteLength !== type.bound) {
55
- throw new Errors_js_1.TypeError(`bytes${argument.byteLength}`, type);
56
- }
57
- return argument;
58
- }
59
- exports.encodeArgument = encodeArgument;
60
- //# sourceMappingURL=Argument.js.map
@@ -1,23 +0,0 @@
1
- import { Artifact } from '@cashscript/utils';
2
- import { Transaction } from './Transaction.js';
3
- import { Argument } from './Argument.js';
4
- import { Utxo } from './interfaces.js';
5
- import NetworkProvider from './network/NetworkProvider.js';
6
- export declare class Contract {
7
- private artifact;
8
- private provider;
9
- name: string;
10
- address: string;
11
- bytesize: number;
12
- opcount: number;
13
- functions: {
14
- [name: string]: ContractFunction;
15
- };
16
- private redeemScript;
17
- constructor(artifact: Artifact, constructorArgs: Argument[], provider?: NetworkProvider);
18
- getBalance(): Promise<number>;
19
- getUtxos(): Promise<Utxo[]>;
20
- getRedeemScriptHex(): string;
21
- private createFunction;
22
- }
23
- export declare type ContractFunction = (...args: Argument[]) => Transaction;
@@ -1,87 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.Contract = void 0;
16
- const libauth_1 = require("@bitauth/libauth");
17
- const utils_1 = require("@cashscript/utils");
18
- const Transaction_js_1 = require("./Transaction.js");
19
- const Argument_js_1 = require("./Argument.js");
20
- const utils_js_1 = require("./utils.js");
21
- const SignatureTemplate_js_1 = __importDefault(require("./SignatureTemplate.js"));
22
- const index_js_1 = require("./network/index.js");
23
- class Contract {
24
- constructor(artifact, constructorArgs, provider = new index_js_1.ElectrumNetworkProvider()) {
25
- this.artifact = artifact;
26
- this.provider = provider;
27
- const expectedProperties = ['abi', 'bytecode', 'constructorInputs', 'contractName'];
28
- if (!expectedProperties.every((property) => property in artifact)) {
29
- throw new Error('Invalid or incomplete artifact provided');
30
- }
31
- if (artifact.constructorInputs.length !== constructorArgs.length) {
32
- throw new Error(`Incorrect number of arguments passed to ${artifact.contractName} constructor`);
33
- }
34
- // Encode arguments (this also performs type checking)
35
- const encodedArgs = constructorArgs
36
- .map((arg, i) => (0, Argument_js_1.encodeArgument)(arg, artifact.constructorInputs[i].type))
37
- .reverse();
38
- // Check there's no signature templates in the constructor
39
- if (encodedArgs.some((arg) => arg instanceof SignatureTemplate_js_1.default)) {
40
- throw new Error('Cannot use signatures in constructor');
41
- }
42
- this.redeemScript = (0, utils_1.generateRedeemScript)((0, utils_1.asmToScript)(this.artifact.bytecode), encodedArgs);
43
- // Populate the functions object with the contract's functions
44
- // (with a special case for single function, which has no "function selector")
45
- this.functions = {};
46
- if (artifact.abi.length === 1) {
47
- const f = artifact.abi[0];
48
- this.functions[f.name] = this.createFunction(f);
49
- }
50
- else {
51
- artifact.abi.forEach((f, i) => {
52
- this.functions[f.name] = this.createFunction(f, i);
53
- });
54
- }
55
- this.name = artifact.contractName;
56
- this.address = (0, utils_js_1.scriptToAddress)(this.redeemScript, this.provider.network);
57
- this.bytesize = (0, utils_1.calculateBytesize)(this.redeemScript);
58
- this.opcount = (0, utils_1.countOpcodes)(this.redeemScript);
59
- }
60
- getBalance() {
61
- return __awaiter(this, void 0, void 0, function* () {
62
- const utxos = yield this.getUtxos();
63
- return utxos.reduce((acc, utxo) => acc + utxo.satoshis, 0);
64
- });
65
- }
66
- getUtxos() {
67
- return __awaiter(this, void 0, void 0, function* () {
68
- return this.provider.getUtxos(this.address);
69
- });
70
- }
71
- getRedeemScriptHex() {
72
- return (0, libauth_1.binToHex)((0, utils_1.scriptToBytecode)(this.redeemScript));
73
- }
74
- createFunction(abiFunction, selector) {
75
- return (...args) => {
76
- if (abiFunction.inputs.length !== args.length) {
77
- throw new Error(`Incorrect number of arguments passed to function ${abiFunction.name}`);
78
- }
79
- // Encode passed args (this also performs type checking)
80
- const encodedArgs = args
81
- .map((arg, i) => (0, Argument_js_1.encodeArgument)(arg, abiFunction.inputs[i].type));
82
- return new Transaction_js_1.Transaction(this.address, this.provider, this.redeemScript, abiFunction, encodedArgs, selector);
83
- };
84
- }
85
- }
86
- exports.Contract = Contract;
87
- //# sourceMappingURL=Contract.js.map
@@ -1,84 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Reason = exports.FailedSigCheckError = exports.FailedTimeCheckError = exports.FailedRequireError = exports.FailedTransactionError = exports.OutputSatoshisTooSmallError = exports.TypeError = void 0;
4
- const constants_js_1 = require("./constants.js");
5
- class TypeError extends Error {
6
- constructor(actual, expected) {
7
- super(`Found type '${actual}' where type '${expected.toString()}' was expected`);
8
- }
9
- }
10
- exports.TypeError = TypeError;
11
- class OutputSatoshisTooSmallError extends Error {
12
- constructor(satoshis) {
13
- super(`Tried to add an output with ${satoshis} satoshis, which is less than the DUST limit (${constants_js_1.DUST_LIMIT})`);
14
- }
15
- }
16
- exports.OutputSatoshisTooSmallError = OutputSatoshisTooSmallError;
17
- class FailedTransactionError extends Error {
18
- constructor(reason, meep) {
19
- super(`Transaction failed with reason: ${reason}\n${meep}`);
20
- this.reason = reason;
21
- this.meep = meep;
22
- }
23
- }
24
- exports.FailedTransactionError = FailedTransactionError;
25
- class FailedRequireError extends FailedTransactionError {
26
- }
27
- exports.FailedRequireError = FailedRequireError;
28
- class FailedTimeCheckError extends FailedTransactionError {
29
- }
30
- exports.FailedTimeCheckError = FailedTimeCheckError;
31
- class FailedSigCheckError extends FailedTransactionError {
32
- }
33
- exports.FailedSigCheckError = FailedSigCheckError;
34
- // TODO: Expand these reasons with non-script failures (like tx-mempool-conflict)
35
- var Reason;
36
- (function (Reason) {
37
- Reason["EVAL_FALSE"] = "Script evaluated without error but finished with a false/empty top stack element";
38
- Reason["VERIFY"] = "Script failed an OP_VERIFY operation";
39
- Reason["EQUALVERIFY"] = "Script failed an OP_EQUALVERIFY operation";
40
- Reason["CHECKMULTISIGVERIFY"] = "Script failed an OP_CHECKMULTISIGVERIFY operation";
41
- Reason["CHECKSIGVERIFY"] = "Script failed an OP_CHECKSIGVERIFY operation";
42
- Reason["CHECKDATASIGVERIFY"] = "Script failed an OP_CHECKDATASIGVERIFY operation";
43
- Reason["NUMEQUALVERIFY"] = "Script failed an OP_NUMEQUALVERIFY operation";
44
- Reason["SCRIPT_SIZE"] = "Script is too big";
45
- Reason["PUSH_SIZE"] = "Push value size limit exceeded";
46
- Reason["OP_COUNT"] = "Operation limit exceeded";
47
- Reason["STACK_SIZE"] = "Stack size limit exceeded";
48
- Reason["SIG_COUNT"] = "Signature count negative or greater than pubkey count";
49
- Reason["PUBKEY_COUNT"] = "Pubkey count negative or limit exceeded";
50
- Reason["INVALID_OPERAND_SIZE"] = "Invalid operand size";
51
- Reason["INVALID_NUMBER_RANGE"] = "Given operand is not a number within the valid range";
52
- Reason["IMPOSSIBLE_ENCODING"] = "The requested encoding is impossible to satisfy";
53
- Reason["INVALID_SPLIT_RANGE"] = "Invalid OP_SPLIT range";
54
- Reason["INVALID_BIT_COUNT"] = "Invalid number of bit set in OP_CHECKMULTISIG";
55
- Reason["BAD_OPCODE"] = "Opcode missing or not understood";
56
- Reason["DISABLED_OPCODE"] = "Attempted to use a disabled opcode";
57
- Reason["INVALID_STACK_OPERATION"] = "Operation not valid with the current stack size";
58
- Reason["INVALID_ALTSTACK_OPERATION"] = "Operation not valid with the current altstack size";
59
- Reason["OP_RETURN"] = "OP_RETURN was encountered";
60
- Reason["UNBALANCED_CONDITIONAL"] = "Invalid OP_IF construction";
61
- Reason["DIV_BY_ZERO"] = "Division by zero error";
62
- Reason["MOD_BY_ZERO"] = "Modulo by zero error";
63
- Reason["INVALID_BITFIELD_SIZE"] = "Bitfield of unexpected size error";
64
- Reason["INVALID_BIT_RANGE"] = "Bitfield's bit out of the expected range";
65
- Reason["NEGATIVE_LOCKTIME"] = "Negative locktime";
66
- Reason["UNSATISFIED_LOCKTIME"] = "Locktime requirement not satisfied";
67
- Reason["SIG_HASHTYPE"] = "Signature hash type missing or not understood";
68
- Reason["SIG_DER"] = "Non-canonical DER signature";
69
- Reason["MINIMALDATA"] = "Data push larger than necessary";
70
- Reason["SIG_PUSHONLY"] = "Only push operators allowed in signature scripts";
71
- Reason["SIG_HIGH_S"] = "Non-canonical signature: S value is unnecessarily high";
72
- Reason["MINIMALIF"] = "OP_IF/NOTIF argument must be minimal";
73
- Reason["SIG_NULLFAIL"] = "Signature must be zero for failed CHECK(MULTI)SIG operation";
74
- Reason["SIG_BADLENGTH"] = "Signature cannot be 65 bytes in CHECKMULTISIG";
75
- Reason["SIG_NONSCHNORR"] = "Only Schnorr signatures allowed in this operation";
76
- Reason["DISCOURAGE_UPGRADABLE_NOPS"] = "NOPx reserved for soft-fork upgrades";
77
- Reason["PUBKEYTYPE"] = "Public key is neither compressed or uncompressed";
78
- Reason["CLEANSTACK"] = "Script did not clean its stack";
79
- Reason["NONCOMPRESSED_PUBKEY"] = "Using non-compressed public key";
80
- Reason["ILLEGAL_FORKID"] = "Illegal use of SIGHASH_FORKID";
81
- Reason["MUST_USE_FORKID"] = "Signature must use SIGHASH_FORKID";
82
- Reason["UNKNOWN"] = "unknown error";
83
- })(Reason = exports.Reason || (exports.Reason = {}));
84
- //# sourceMappingURL=Errors.js.map
@@ -1,45 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const libauth_1 = require("@bitauth/libauth");
4
- const utils_1 = require("@cashscript/utils");
5
- const interfaces_js_1 = require("./interfaces.js");
6
- class SignatureTemplate {
7
- constructor(signer, hashtype = interfaces_js_1.HashType.SIGHASH_ALL, signatureAlgorithm = interfaces_js_1.SignatureAlgorithm.SCHNORR) {
8
- this.hashtype = hashtype;
9
- this.signatureAlgorithm = signatureAlgorithm;
10
- if (isKeypair(signer)) {
11
- const wif = signer.toWIF();
12
- this.privateKey = decodeWif(wif);
13
- }
14
- else if (typeof signer === 'string') {
15
- this.privateKey = decodeWif(signer);
16
- }
17
- else {
18
- this.privateKey = signer;
19
- }
20
- }
21
- generateSignature(payload, secp256k1, bchForkId) {
22
- const signature = this.signatureAlgorithm === interfaces_js_1.SignatureAlgorithm.SCHNORR
23
- ? secp256k1.signMessageHashSchnorr(this.privateKey, payload)
24
- : secp256k1.signMessageHashDER(this.privateKey, payload);
25
- return Uint8Array.from([...signature, this.getHashType(bchForkId)]);
26
- }
27
- getHashType(bchForkId = true) {
28
- return bchForkId ? (this.hashtype | libauth_1.SigningSerializationFlag.forkId) : this.hashtype;
29
- }
30
- getPublicKey(secp256k1) {
31
- return secp256k1.derivePublicKeyCompressed(this.privateKey);
32
- }
33
- }
34
- exports.default = SignatureTemplate;
35
- function isKeypair(obj) {
36
- return typeof obj.toWIF === 'function';
37
- }
38
- function decodeWif(wif) {
39
- const result = (0, libauth_1.decodePrivateKeyWif)({ hash: utils_1.sha256 }, wif);
40
- if (typeof result === 'string') {
41
- throw new Error(result);
42
- }
43
- return result.privateKey;
44
- }
45
- //# sourceMappingURL=SignatureTemplate.js.map
@@ -1,39 +0,0 @@
1
- import { AbiFunction, Script } from '@cashscript/utils';
2
- import { Utxo, Recipient, TransactionDetails } from './interfaces.js';
3
- import NetworkProvider from './network/NetworkProvider.js';
4
- import SignatureTemplate from './SignatureTemplate.js';
5
- export declare class Transaction {
6
- private address;
7
- private provider;
8
- private redeemScript;
9
- private abiFunction;
10
- private args;
11
- private selector?;
12
- private inputs;
13
- private outputs;
14
- private sequence;
15
- private locktime;
16
- private hardcodedFee;
17
- private feePerByte;
18
- private minChange;
19
- constructor(address: string, provider: NetworkProvider, redeemScript: Script, abiFunction: AbiFunction, args: (Uint8Array | SignatureTemplate)[], selector?: number | undefined);
20
- from(input: Utxo): this;
21
- from(inputs: Utxo[]): this;
22
- experimentalFromP2PKH(input: Utxo, template: SignatureTemplate): this;
23
- experimentalFromP2PKH(inputs: Utxo[], template: SignatureTemplate): this;
24
- to(to: string, amount: number): this;
25
- to(outputs: Recipient[]): this;
26
- withOpReturn(chunks: string[]): this;
27
- withAge(age: number): this;
28
- withTime(time: number): this;
29
- withHardcodedFee(hardcodedFee: number): this;
30
- withFeePerByte(feePerByte: number): this;
31
- withMinChange(minChange: number): this;
32
- withoutChange(): this;
33
- build(): Promise<string>;
34
- send(): Promise<TransactionDetails>;
35
- send(raw: true): Promise<string>;
36
- private getTxDetails;
37
- meep(): Promise<string>;
38
- private setInputsAndOutputs;
39
- }
@@ -1,258 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.Transaction = void 0;
16
- const libauth_1 = require("@bitauth/libauth");
17
- const delay_1 = __importDefault(require("delay"));
18
- const utils_1 = require("@cashscript/utils");
19
- const interfaces_js_1 = require("./interfaces.js");
20
- const utils_js_1 = require("./utils.js");
21
- const constants_js_1 = require("./constants.js");
22
- const SignatureTemplate_js_1 = __importDefault(require("./SignatureTemplate.js"));
23
- const bip68 = require('bip68');
24
- class Transaction {
25
- constructor(address, provider, redeemScript, abiFunction, args, selector) {
26
- this.address = address;
27
- this.provider = provider;
28
- this.redeemScript = redeemScript;
29
- this.abiFunction = abiFunction;
30
- this.args = args;
31
- this.selector = selector;
32
- this.inputs = [];
33
- this.outputs = [];
34
- this.sequence = 0xfffffffe;
35
- this.feePerByte = 1.0;
36
- this.minChange = constants_js_1.DUST_LIMIT;
37
- }
38
- from(inputOrInputs) {
39
- if (!Array.isArray(inputOrInputs)) {
40
- inputOrInputs = [inputOrInputs];
41
- }
42
- this.inputs = this.inputs.concat(inputOrInputs);
43
- return this;
44
- }
45
- experimentalFromP2PKH(inputOrInputs, template) {
46
- if (!Array.isArray(inputOrInputs)) {
47
- inputOrInputs = [inputOrInputs];
48
- }
49
- inputOrInputs = inputOrInputs.map((input) => (Object.assign(Object.assign({}, input), { template })));
50
- this.inputs = this.inputs.concat(inputOrInputs);
51
- return this;
52
- }
53
- to(toOrOutputs, amount) {
54
- if (typeof toOrOutputs === 'string' && typeof amount === 'number') {
55
- return this.to([{ to: toOrOutputs, amount }]);
56
- }
57
- if (Array.isArray(toOrOutputs) && amount === undefined) {
58
- toOrOutputs.forEach(utils_js_1.validateRecipient);
59
- this.outputs = this.outputs.concat(toOrOutputs);
60
- return this;
61
- }
62
- throw new Error('Incorrect arguments passed to function \'to\'');
63
- }
64
- withOpReturn(chunks) {
65
- this.outputs.push((0, utils_js_1.createOpReturnOutput)(chunks));
66
- return this;
67
- }
68
- withAge(age) {
69
- this.sequence = bip68.encode({ blocks: age });
70
- return this;
71
- }
72
- withTime(time) {
73
- this.locktime = time;
74
- return this;
75
- }
76
- withHardcodedFee(hardcodedFee) {
77
- this.hardcodedFee = hardcodedFee;
78
- return this;
79
- }
80
- withFeePerByte(feePerByte) {
81
- this.feePerByte = feePerByte;
82
- return this;
83
- }
84
- withMinChange(minChange) {
85
- this.minChange = minChange;
86
- return this;
87
- }
88
- withoutChange() {
89
- return this.withMinChange(Number.MAX_VALUE);
90
- }
91
- build() {
92
- var _a;
93
- return __awaiter(this, void 0, void 0, function* () {
94
- this.locktime = (_a = this.locktime) !== null && _a !== void 0 ? _a : yield this.provider.getBlockHeight();
95
- yield this.setInputsAndOutputs();
96
- const secp256k1 = yield (0, libauth_1.instantiateSecp256k1)();
97
- const bytecode = (0, utils_1.scriptToBytecode)(this.redeemScript);
98
- const inputs = this.inputs.map((utxo) => ({
99
- outpointIndex: utxo.vout,
100
- outpointTransactionHash: (0, libauth_1.hexToBin)(utxo.txid),
101
- sequenceNumber: this.sequence,
102
- unlockingBytecode: new Uint8Array(),
103
- }));
104
- const outputs = this.outputs.map((output) => {
105
- const lockingBytecode = typeof output.to === 'string'
106
- ? (0, utils_js_1.addressToLockScript)(output.to)
107
- : output.to;
108
- const satoshis = (0, libauth_1.bigIntToBinUint64LE)(BigInt(output.amount));
109
- return { lockingBytecode, satoshis };
110
- });
111
- const transaction = {
112
- inputs,
113
- locktime: this.locktime,
114
- outputs,
115
- version: 2,
116
- };
117
- const inputScripts = [];
118
- this.inputs.forEach((utxo, i) => {
119
- // UTXO's with signature templates are signed using P2PKH
120
- if ((0, interfaces_js_1.isSignableUtxo)(utxo)) {
121
- const pubkey = utxo.template.getPublicKey(secp256k1);
122
- const pubkeyHash = (0, utils_1.hash160)(pubkey);
123
- const addressContents = { payload: pubkeyHash, type: libauth_1.AddressType.p2pkh };
124
- const prevOutScript = (0, libauth_1.addressContentsToLockingBytecode)(addressContents);
125
- const hashtype = utxo.template.getHashType();
126
- const preimage = (0, utils_js_1.createSighashPreimage)(transaction, utxo, i, prevOutScript, hashtype);
127
- const sighash = (0, utils_1.hash256)(preimage);
128
- const signature = utxo.template.generateSignature(sighash, secp256k1);
129
- const inputScript = (0, utils_1.scriptToBytecode)([signature, pubkey]);
130
- inputScripts.push(inputScript);
131
- return;
132
- }
133
- let covenantHashType = -1;
134
- const completeArgs = this.args.map((arg) => {
135
- if (!(arg instanceof SignatureTemplate_js_1.default))
136
- return arg;
137
- // First signature is used for sighash preimage (maybe not the best way)
138
- if (covenantHashType < 0)
139
- covenantHashType = arg.getHashType();
140
- const preimage = (0, utils_js_1.createSighashPreimage)(transaction, utxo, i, bytecode, arg.getHashType());
141
- const sighash = (0, utils_1.hash256)(preimage);
142
- return arg.generateSignature(sighash, secp256k1);
143
- });
144
- const preimage = this.abiFunction.covenant
145
- ? (0, utils_js_1.createSighashPreimage)(transaction, utxo, i, bytecode, covenantHashType)
146
- : undefined;
147
- const inputScript = (0, utils_js_1.createInputScript)(this.redeemScript, completeArgs, this.selector, preimage);
148
- inputScripts.push(inputScript);
149
- });
150
- inputScripts.forEach((script, i) => {
151
- transaction.inputs[i].unlockingBytecode = script;
152
- });
153
- return (0, libauth_1.binToHex)((0, libauth_1.encodeTransaction)(transaction));
154
- });
155
- }
156
- send(raw) {
157
- var _a;
158
- return __awaiter(this, void 0, void 0, function* () {
159
- const tx = yield this.build();
160
- try {
161
- const txid = yield this.provider.sendRawTransaction(tx);
162
- return raw ? yield this.getTxDetails(txid, raw) : yield this.getTxDetails(txid);
163
- }
164
- catch (e) {
165
- const reason = (_a = e.error) !== null && _a !== void 0 ? _a : e.message;
166
- throw (0, utils_js_1.buildError)(reason, (0, utils_js_1.meep)(tx, this.inputs, this.redeemScript));
167
- }
168
- });
169
- }
170
- getTxDetails(txid, raw) {
171
- return __awaiter(this, void 0, void 0, function* () {
172
- for (let retries = 0; retries < 1200; retries += 1) {
173
- yield (0, delay_1.default)(500);
174
- try {
175
- const hex = yield this.provider.getRawTransaction(txid);
176
- if (raw)
177
- return hex;
178
- const libauthTransaction = (0, libauth_1.decodeTransaction)((0, libauth_1.hexToBin)(hex));
179
- return Object.assign(Object.assign({}, libauthTransaction), { txid, hex });
180
- }
181
- catch (ignored) {
182
- // ignored
183
- }
184
- }
185
- // Should not happen
186
- throw new Error('Could not retrieve transaction details for over 10 minutes');
187
- });
188
- }
189
- meep() {
190
- return __awaiter(this, void 0, void 0, function* () {
191
- const tx = yield this.build();
192
- return (0, utils_js_1.meep)(tx, this.inputs, this.redeemScript);
193
- });
194
- }
195
- setInputsAndOutputs() {
196
- var _a;
197
- return __awaiter(this, void 0, void 0, function* () {
198
- if (this.outputs.length === 0) {
199
- throw Error('Attempted to build a transaction without outputs');
200
- }
201
- // Replace all SignatureTemplate with 65-length placeholder Uint8Arrays
202
- const placeholderArgs = this.args.map((arg) => (arg instanceof SignatureTemplate_js_1.default ? (0, utils_1.placeholder)(65) : arg));
203
- // Create a placeholder preimage of the correct size
204
- const placeholderPreimage = this.abiFunction.covenant
205
- ? (0, utils_1.placeholder)((0, utils_js_1.getPreimageSize)((0, utils_1.scriptToBytecode)(this.redeemScript)))
206
- : undefined;
207
- // Create a placeholder input script for size calculation using the placeholder
208
- // arguments and correctly sized placeholder preimage
209
- const placeholderScript = (0, utils_js_1.createInputScript)(this.redeemScript, placeholderArgs, this.selector, placeholderPreimage);
210
- // Add one extra byte per input to over-estimate tx-in count
211
- const inputSize = (0, utils_js_1.getInputSize)(placeholderScript) + 1;
212
- // Calculate amount to send and base fee (excluding additional fees per UTXO)
213
- const amount = this.outputs.reduce((acc, output) => acc + output.amount, 0);
214
- let fee = (_a = this.hardcodedFee) !== null && _a !== void 0 ? _a : (0, utils_js_1.getTxSizeWithoutInputs)(this.outputs) * this.feePerByte;
215
- // Select and gather UTXOs and calculate fees and available funds
216
- let satsAvailable = 0;
217
- if (this.inputs.length > 0) {
218
- // If inputs are already defined, the user provided the UTXOs
219
- // and we perform no further UTXO selection
220
- if (!this.hardcodedFee)
221
- fee += this.inputs.length * inputSize * this.feePerByte;
222
- satsAvailable = this.inputs.reduce((acc, input) => acc + input.satoshis, 0);
223
- }
224
- else {
225
- // If inputs are not defined yet, we retrieve the contract's UTXOs and perform selection
226
- const utxos = yield this.provider.getUtxos(this.address);
227
- // We sort the UTXOs mainly so there is consistent behaviour between network providers
228
- // even if they report UTXOs in a different order
229
- utxos.sort((a, b) => b.satoshis - a.satoshis);
230
- for (const utxo of utxos) {
231
- this.inputs.push(utxo);
232
- satsAvailable += utxo.satoshis;
233
- if (!this.hardcodedFee)
234
- fee += inputSize * this.feePerByte;
235
- if (satsAvailable > amount + fee)
236
- break;
237
- }
238
- }
239
- // Fee per byte can be a decimal number, but we need the total fee to be an integer
240
- fee = Math.ceil(fee);
241
- // Calculate change and check available funds
242
- let change = satsAvailable - amount - fee;
243
- if (change < 0) {
244
- throw new Error(`Insufficient funds: available (${satsAvailable}) < needed (${amount + fee}).`);
245
- }
246
- // Account for the fee of a change output
247
- if (!this.hardcodedFee) {
248
- change -= constants_js_1.P2SH_OUTPUT_SIZE;
249
- }
250
- // Add a change output if applicable
251
- if (change >= constants_js_1.DUST_LIMIT && change >= this.minChange) {
252
- this.outputs.push({ to: this.address, amount: change });
253
- }
254
- });
255
- }
256
- }
257
- exports.Transaction = Transaction;
258
- //# sourceMappingURL=Transaction.js.map
@@ -1,5 +0,0 @@
1
- export declare const DUST_LIMIT = 546;
2
- export declare const P2PKH_OUTPUT_SIZE = 34;
3
- export declare const P2SH_OUTPUT_SIZE = 32;
4
- export declare const VERSION_SIZE = 4;
5
- export declare const LOCKTIME_SIZE = 4;
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LOCKTIME_SIZE = exports.VERSION_SIZE = exports.P2SH_OUTPUT_SIZE = exports.P2PKH_OUTPUT_SIZE = exports.DUST_LIMIT = void 0;
4
- exports.DUST_LIMIT = 546;
5
- exports.P2PKH_OUTPUT_SIZE = 34;
6
- exports.P2SH_OUTPUT_SIZE = 32;
7
- exports.VERSION_SIZE = 4;
8
- exports.LOCKTIME_SIZE = 4;
9
- //# sourceMappingURL=constants.js.map