cashscript 0.9.1 → 0.9.3
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/dist/Contract.d.ts +4 -3
- package/dist/Contract.js +11 -2
- package/dist/Transaction.d.ts +6 -7
- package/dist/Transaction.js +32 -76
- package/dist/TransactionBuilder.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +21 -11
- package/package.json +3 -3
package/dist/Contract.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Artifact } from '@cashscript/utils';
|
|
1
|
+
import { Artifact, Script } from '@cashscript/utils';
|
|
2
2
|
import { Transaction } from './Transaction.js';
|
|
3
3
|
import { Argument } from './Argument.js';
|
|
4
4
|
import { Unlocker, ContractOptions, Utxo } from './interfaces.js';
|
|
5
|
+
import NetworkProvider from './network/NetworkProvider.js';
|
|
5
6
|
export declare class Contract {
|
|
6
7
|
private artifact;
|
|
7
8
|
private options?;
|
|
@@ -13,8 +14,8 @@ export declare class Contract {
|
|
|
13
14
|
opcount: number;
|
|
14
15
|
functions: Record<string, ContractFunction>;
|
|
15
16
|
unlock: Record<string, ContractUnlocker>;
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
redeemScript: Script;
|
|
18
|
+
provider: NetworkProvider;
|
|
18
19
|
private addressType;
|
|
19
20
|
constructor(artifact: Artifact, constructorArgs: Argument[], options?: ContractOptions | undefined);
|
|
20
21
|
getBalance(): Promise<bigint>;
|
package/dist/Contract.js
CHANGED
|
@@ -73,7 +73,8 @@ export class Contract {
|
|
|
73
73
|
// Encode passed args (this also performs type checking)
|
|
74
74
|
const encodedArgs = args
|
|
75
75
|
.map((arg, i) => encodeArgument(arg, abiFunction.inputs[i].type));
|
|
76
|
-
|
|
76
|
+
const unlocker = this.createUnlocker(abiFunction, selector)(...args);
|
|
77
|
+
return new Transaction(this, unlocker, abiFunction, encodedArgs, selector);
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
createUnlocker(abiFunction, selector) {
|
|
@@ -82,14 +83,22 @@ export class Contract {
|
|
|
82
83
|
const encodedArgs = args
|
|
83
84
|
.map((arg, i) => encodeArgument(arg, abiFunction.inputs[i].type));
|
|
84
85
|
const generateUnlockingBytecode = ({ transaction, sourceOutputs, inputIndex }) => {
|
|
86
|
+
// TODO: Remove old-style covenant code for v1.0 release
|
|
87
|
+
let covenantHashType = -1;
|
|
85
88
|
const completeArgs = encodedArgs.map((arg) => {
|
|
86
89
|
if (!(arg instanceof SignatureTemplate))
|
|
87
90
|
return arg;
|
|
91
|
+
// First signature is used for sighash preimage (maybe not the best way)
|
|
92
|
+
if (covenantHashType < 0)
|
|
93
|
+
covenantHashType = arg.getHashType();
|
|
88
94
|
const preimage = createSighashPreimage(transaction, sourceOutputs, inputIndex, bytecode, arg.getHashType());
|
|
89
95
|
const sighash = hash256(preimage);
|
|
90
96
|
return arg.generateSignature(sighash);
|
|
91
97
|
});
|
|
92
|
-
const
|
|
98
|
+
const preimage = abiFunction.covenant
|
|
99
|
+
? createSighashPreimage(transaction, sourceOutputs, inputIndex, bytecode, covenantHashType)
|
|
100
|
+
: undefined;
|
|
101
|
+
const unlockingBytecode = createInputScript(this.redeemScript, completeArgs, selector, preimage);
|
|
93
102
|
return unlockingBytecode;
|
|
94
103
|
};
|
|
95
104
|
const generateLockingBytecode = () => addressToLockScript(this.address);
|
package/dist/Transaction.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { AbiFunction
|
|
2
|
-
import { Utxo, Recipient, TokenDetails, TransactionDetails } from './interfaces.js';
|
|
3
|
-
import NetworkProvider from './network/NetworkProvider.js';
|
|
1
|
+
import { AbiFunction } from '@cashscript/utils';
|
|
2
|
+
import { Utxo, Recipient, TokenDetails, TransactionDetails, Unlocker } from './interfaces.js';
|
|
4
3
|
import SignatureTemplate from './SignatureTemplate.js';
|
|
4
|
+
import { Contract } from './Contract.js';
|
|
5
5
|
export declare class Transaction {
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private redeemScript;
|
|
6
|
+
private contract;
|
|
7
|
+
private unlocker;
|
|
9
8
|
private abiFunction;
|
|
10
9
|
private args;
|
|
11
10
|
private selector?;
|
|
@@ -17,7 +16,7 @@ export declare class Transaction {
|
|
|
17
16
|
private hardcodedFee;
|
|
18
17
|
private minChange;
|
|
19
18
|
private tokenChange;
|
|
20
|
-
constructor(
|
|
19
|
+
constructor(contract: Contract, unlocker: Unlocker, abiFunction: AbiFunction, args: (Uint8Array | SignatureTemplate)[], selector?: number | undefined);
|
|
21
20
|
from(input: Utxo): this;
|
|
22
21
|
from(inputs: Utxo[]): this;
|
|
23
22
|
fromP2PKH(input: Utxo, template: SignatureTemplate): this;
|
package/dist/Transaction.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import bip68 from 'bip68';
|
|
2
|
-
import { hexToBin,
|
|
2
|
+
import { hexToBin, decodeTransaction, } from '@bitauth/libauth';
|
|
3
3
|
import delay from 'delay';
|
|
4
|
-
import {
|
|
4
|
+
import { placeholder, scriptToBytecode, } from '@cashscript/utils';
|
|
5
5
|
import deepEqual from 'fast-deep-equal';
|
|
6
6
|
import { isUtxoP2PKH, } from './interfaces.js';
|
|
7
|
-
import { meep, createInputScript, getInputSize, createOpReturnOutput, getTxSizeWithoutInputs, getPreimageSize, buildError,
|
|
7
|
+
import { meep, createInputScript, getInputSize, createOpReturnOutput, getTxSizeWithoutInputs, getPreimageSize, buildError, validateOutput, utxoComparator, calculateDust, getOutputSize, utxoTokenComparator, } from './utils.js';
|
|
8
8
|
import SignatureTemplate from './SignatureTemplate.js';
|
|
9
9
|
import { P2PKH_INPUT_SIZE } from './constants.js';
|
|
10
|
+
import { TransactionBuilder } from './TransactionBuilder.js';
|
|
10
11
|
export class Transaction {
|
|
11
|
-
constructor(
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
14
|
-
this.redeemScript = redeemScript;
|
|
12
|
+
constructor(contract, unlocker, abiFunction, args, selector) {
|
|
13
|
+
this.contract = contract;
|
|
14
|
+
this.unlocker = unlocker;
|
|
15
15
|
this.abiFunction = abiFunction;
|
|
16
16
|
this.args = args;
|
|
17
17
|
this.selector = selector;
|
|
@@ -43,7 +43,7 @@ export class Transaction {
|
|
|
43
43
|
return this.to([recipient]);
|
|
44
44
|
}
|
|
45
45
|
if (Array.isArray(toOrOutputs) && amount === undefined) {
|
|
46
|
-
toOrOutputs.forEach(
|
|
46
|
+
toOrOutputs.forEach(validateOutput);
|
|
47
47
|
this.outputs = this.outputs.concat(toOrOutputs);
|
|
48
48
|
return this;
|
|
49
49
|
}
|
|
@@ -81,84 +81,37 @@ export class Transaction {
|
|
|
81
81
|
return this;
|
|
82
82
|
}
|
|
83
83
|
async build() {
|
|
84
|
-
this.locktime = this.locktime ?? await this.provider.getBlockHeight();
|
|
84
|
+
this.locktime = this.locktime ?? await this.contract.provider.getBlockHeight();
|
|
85
85
|
await this.setInputsAndOutputs();
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const inputs = this.inputs.map((utxo) => ({
|
|
89
|
-
outpointIndex: utxo.vout,
|
|
90
|
-
outpointTransactionHash: hexToBin(utxo.txid),
|
|
91
|
-
sequenceNumber: this.sequence,
|
|
92
|
-
unlockingBytecode: new Uint8Array(),
|
|
93
|
-
}));
|
|
94
|
-
// Generate source outputs from inputs (for signing with SIGHASH_UTXOS)
|
|
95
|
-
const sourceOutputs = this.inputs.map((input) => {
|
|
96
|
-
const sourceOutput = {
|
|
97
|
-
amount: input.satoshis,
|
|
98
|
-
to: isUtxoP2PKH(input) ? publicKeyToP2PKHLockingBytecode(input.template.getPublicKey()) : lockingBytecode,
|
|
99
|
-
token: input.token,
|
|
100
|
-
};
|
|
101
|
-
return cashScriptOutputToLibauthOutput(sourceOutput);
|
|
102
|
-
});
|
|
103
|
-
const outputs = this.outputs.map(cashScriptOutputToLibauthOutput);
|
|
104
|
-
const transaction = {
|
|
105
|
-
inputs,
|
|
106
|
-
locktime: this.locktime,
|
|
107
|
-
outputs,
|
|
108
|
-
version: 2,
|
|
109
|
-
};
|
|
110
|
-
const inputScripts = [];
|
|
111
|
-
this.inputs.forEach((utxo, i) => {
|
|
112
|
-
// UTXO's with signature templates are signed using P2PKH
|
|
86
|
+
const builder = new TransactionBuilder({ provider: this.contract.provider });
|
|
87
|
+
this.inputs.forEach((utxo) => {
|
|
113
88
|
if (isUtxoP2PKH(utxo)) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const sighash = hash256(preimage);
|
|
119
|
-
const signature = utxo.template.generateSignature(sighash);
|
|
120
|
-
const inputScript = scriptToBytecode([signature, pubkey]);
|
|
121
|
-
inputScripts.push(inputScript);
|
|
122
|
-
return;
|
|
89
|
+
builder.addInput(utxo, utxo.template.unlockP2PKH(), { sequence: this.sequence });
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
builder.addInput(utxo, this.unlocker, { sequence: this.sequence });
|
|
123
93
|
}
|
|
124
|
-
let covenantHashType = -1;
|
|
125
|
-
const completeArgs = this.args.map((arg) => {
|
|
126
|
-
if (!(arg instanceof SignatureTemplate))
|
|
127
|
-
return arg;
|
|
128
|
-
// First signature is used for sighash preimage (maybe not the best way)
|
|
129
|
-
if (covenantHashType < 0)
|
|
130
|
-
covenantHashType = arg.getHashType();
|
|
131
|
-
const preimage = createSighashPreimage(transaction, sourceOutputs, i, bytecode, arg.getHashType());
|
|
132
|
-
const sighash = hash256(preimage);
|
|
133
|
-
return arg.generateSignature(sighash);
|
|
134
|
-
});
|
|
135
|
-
const preimage = this.abiFunction.covenant
|
|
136
|
-
? createSighashPreimage(transaction, sourceOutputs, i, bytecode, covenantHashType)
|
|
137
|
-
: undefined;
|
|
138
|
-
const inputScript = createInputScript(this.redeemScript, completeArgs, this.selector, preimage);
|
|
139
|
-
inputScripts.push(inputScript);
|
|
140
|
-
});
|
|
141
|
-
inputScripts.forEach((script, i) => {
|
|
142
|
-
transaction.inputs[i].unlockingBytecode = script;
|
|
143
94
|
});
|
|
144
|
-
|
|
95
|
+
builder.addOutputs(this.outputs);
|
|
96
|
+
builder.setLocktime(this.locktime);
|
|
97
|
+
return builder.build();
|
|
145
98
|
}
|
|
146
99
|
async send(raw) {
|
|
147
100
|
const tx = await this.build();
|
|
148
101
|
try {
|
|
149
|
-
const txid = await this.provider.sendRawTransaction(tx);
|
|
102
|
+
const txid = await this.contract.provider.sendRawTransaction(tx);
|
|
150
103
|
return raw ? await this.getTxDetails(txid, raw) : await this.getTxDetails(txid);
|
|
151
104
|
}
|
|
152
105
|
catch (e) {
|
|
153
106
|
const reason = e.error ?? e.message;
|
|
154
|
-
throw buildError(reason, meep(tx, this.inputs, this.redeemScript));
|
|
107
|
+
throw buildError(reason, meep(tx, this.inputs, this.contract.redeemScript));
|
|
155
108
|
}
|
|
156
109
|
}
|
|
157
110
|
async getTxDetails(txid, raw) {
|
|
158
111
|
for (let retries = 0; retries < 1200; retries += 1) {
|
|
159
112
|
await delay(500);
|
|
160
113
|
try {
|
|
161
|
-
const hex = await this.provider.getRawTransaction(txid);
|
|
114
|
+
const hex = await this.contract.provider.getRawTransaction(txid);
|
|
162
115
|
if (raw)
|
|
163
116
|
return hex;
|
|
164
117
|
const libauthTransaction = decodeTransaction(hexToBin(hex));
|
|
@@ -173,13 +126,16 @@ export class Transaction {
|
|
|
173
126
|
}
|
|
174
127
|
async meep() {
|
|
175
128
|
const tx = await this.build();
|
|
176
|
-
return meep(tx, this.inputs, this.redeemScript);
|
|
129
|
+
return meep(tx, this.inputs, this.contract.redeemScript);
|
|
177
130
|
}
|
|
178
131
|
async setInputsAndOutputs() {
|
|
179
132
|
if (this.outputs.length === 0) {
|
|
180
133
|
throw Error('Attempted to build a transaction without outputs');
|
|
181
134
|
}
|
|
182
|
-
|
|
135
|
+
// Fetched utxos are only used when no inputs are available, so only fetch in that case.
|
|
136
|
+
const allUtxos = this.inputs.length === 0
|
|
137
|
+
? await this.contract.provider.getUtxos(this.contract.address)
|
|
138
|
+
: [];
|
|
183
139
|
const tokenInputs = this.inputs.length > 0
|
|
184
140
|
? this.inputs.filter((input) => input.token)
|
|
185
141
|
: selectAllTokenUtxos(allUtxos, this.outputs);
|
|
@@ -188,7 +144,7 @@ export class Transaction {
|
|
|
188
144
|
selectAllTokenUtxos(this.inputs, this.outputs);
|
|
189
145
|
}
|
|
190
146
|
if (this.tokenChange) {
|
|
191
|
-
const tokenChangeOutputs = createFungibleTokenChangeOutputs(tokenInputs, this.outputs, this.
|
|
147
|
+
const tokenChangeOutputs = createFungibleTokenChangeOutputs(tokenInputs, this.outputs, this.contract.tokenAddress);
|
|
192
148
|
this.outputs.push(...tokenChangeOutputs);
|
|
193
149
|
}
|
|
194
150
|
// Construct list with all nfts in inputs
|
|
@@ -268,7 +224,7 @@ export class Transaction {
|
|
|
268
224
|
commitment: unusedNft.commitment,
|
|
269
225
|
},
|
|
270
226
|
};
|
|
271
|
-
const nftChangeOutput = { to: this.
|
|
227
|
+
const nftChangeOutput = { to: this.contract.tokenAddress, amount: BigInt(1000), token: tokenDetails };
|
|
272
228
|
this.outputs.push(nftChangeOutput);
|
|
273
229
|
}
|
|
274
230
|
}
|
|
@@ -277,11 +233,11 @@ export class Transaction {
|
|
|
277
233
|
const placeholderArgs = this.args.map((arg) => (arg instanceof SignatureTemplate ? placeholder(65) : arg));
|
|
278
234
|
// Create a placeholder preimage of the correct size
|
|
279
235
|
const placeholderPreimage = this.abiFunction.covenant
|
|
280
|
-
? placeholder(getPreimageSize(scriptToBytecode(this.redeemScript)))
|
|
236
|
+
? placeholder(getPreimageSize(scriptToBytecode(this.contract.redeemScript)))
|
|
281
237
|
: undefined;
|
|
282
238
|
// Create a placeholder input script for size calculation using the placeholder
|
|
283
239
|
// arguments and correctly sized placeholder preimage
|
|
284
|
-
const placeholderScript = createInputScript(this.redeemScript, placeholderArgs, this.selector, placeholderPreimage);
|
|
240
|
+
const placeholderScript = createInputScript(this.contract.redeemScript, placeholderArgs, this.selector, placeholderPreimage);
|
|
285
241
|
// Add one extra byte per input to over-estimate tx-in count
|
|
286
242
|
const contractInputSize = getInputSize(placeholderScript) + 1;
|
|
287
243
|
// Note that we use the addPrecision function to add "decimal points" to BigInt numbers
|
|
@@ -331,11 +287,11 @@ export class Transaction {
|
|
|
331
287
|
}
|
|
332
288
|
// Account for the fee of adding a change output
|
|
333
289
|
if (!this.hardcodedFee) {
|
|
334
|
-
const changeOutputSize = getOutputSize({ to: this.address, amount: 0n });
|
|
290
|
+
const changeOutputSize = getOutputSize({ to: this.contract.address, amount: 0n });
|
|
335
291
|
change -= BigInt(changeOutputSize * this.feePerByte);
|
|
336
292
|
}
|
|
337
293
|
// Add a change output if applicable
|
|
338
|
-
const changeOutput = { to: this.address, amount: change };
|
|
294
|
+
const changeOutput = { to: this.contract.address, amount: change };
|
|
339
295
|
if (change >= this.minChange && change >= calculateDust(changeOutput)) {
|
|
340
296
|
this.outputs.push(changeOutput);
|
|
341
297
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { binToHex, decodeTransaction, encodeTransaction, hexToBin, } from '@bitauth/libauth';
|
|
2
2
|
import delay from 'delay';
|
|
3
3
|
import { isUnlockableUtxo, } from './interfaces.js';
|
|
4
|
-
import { buildError, cashScriptOutputToLibauthOutput, createOpReturnOutput } from './utils.js';
|
|
4
|
+
import { buildError, cashScriptOutputToLibauthOutput, createOpReturnOutput, validateOutput, } from './utils.js';
|
|
5
5
|
const DEFAULT_SEQUENCE = 0xfffffffe;
|
|
6
6
|
export class TransactionBuilder {
|
|
7
7
|
constructor(options) {
|
|
@@ -26,10 +26,10 @@ export class TransactionBuilder {
|
|
|
26
26
|
return this;
|
|
27
27
|
}
|
|
28
28
|
addOutput(output) {
|
|
29
|
-
this.
|
|
30
|
-
return this;
|
|
29
|
+
return this.addOutputs([output]);
|
|
31
30
|
}
|
|
32
31
|
addOutputs(outputs) {
|
|
32
|
+
outputs.forEach(validateOutput);
|
|
33
33
|
this.outputs = this.outputs.concat(outputs);
|
|
34
34
|
return this;
|
|
35
35
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,6 @@ export { TransactionBuilder } from './TransactionBuilder.js';
|
|
|
6
6
|
export { Argument, encodeArgument } from './Argument.js';
|
|
7
7
|
export { Artifact, AbiFunction, AbiInput } from '@cashscript/utils';
|
|
8
8
|
export * as utils from '@cashscript/utils';
|
|
9
|
-
export
|
|
9
|
+
export * from './interfaces.js';
|
|
10
10
|
export * from './Errors.js';
|
|
11
11
|
export { NetworkProvider, BitcoinRpcNetworkProvider, ElectrumNetworkProvider, FullStackNetworkProvider, } from './network/index.js';
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { Transaction } from './Transaction.js';
|
|
|
5
5
|
export { TransactionBuilder } from './TransactionBuilder.js';
|
|
6
6
|
export { encodeArgument } from './Argument.js';
|
|
7
7
|
export * as utils from '@cashscript/utils';
|
|
8
|
-
export
|
|
8
|
+
export * from './interfaces.js';
|
|
9
9
|
export * from './Errors.js';
|
|
10
10
|
export { BitcoinRpcNetworkProvider, ElectrumNetworkProvider, FullStackNetworkProvider, } from './network/index.js';
|
|
11
11
|
//# sourceMappingURL=index.js.map
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Transaction } from '@bitauth/libauth';
|
|
2
2
|
import { Script } from '@cashscript/utils';
|
|
3
|
-
import { Utxo, Output,
|
|
3
|
+
import { Utxo, Output, LibauthOutput } from './interfaces.js';
|
|
4
4
|
import { FailedTransactionError } from './Errors.js';
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function calculateDust(
|
|
5
|
+
export declare function validateOutput(output: Output): void;
|
|
6
|
+
export declare function calculateDust(output: Output): number;
|
|
7
7
|
export declare function getOutputSize(output: Output): number;
|
|
8
8
|
export declare function encodeOutput(output: Output): Uint8Array;
|
|
9
9
|
export declare function cashScriptOutputToLibauthOutput(output: Output): LibauthOutput;
|
package/dist/utils.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import { cashAddressToLockingBytecode, decodeCashAddress, addressContentsToLockingBytecode, lockingBytecodeToCashAddress, binToHex, generateSigningSerializationBCH, utf8ToBin, hexToBin, flattenBinArray, LockingBytecodeType, encodeTransactionOutput, } from '@bitauth/libauth';
|
|
1
|
+
import { cashAddressToLockingBytecode, decodeCashAddress, addressContentsToLockingBytecode, lockingBytecodeToCashAddress, binToHex, generateSigningSerializationBCH, utf8ToBin, hexToBin, flattenBinArray, LockingBytecodeType, encodeTransactionOutput, isHex, bigIntToCompactSize, } from '@bitauth/libauth';
|
|
2
2
|
import { encodeInt, hash160, hash256, Op, scriptToBytecode, } from '@cashscript/utils';
|
|
3
3
|
import { Network, } from './interfaces.js';
|
|
4
4
|
import { VERSION_SIZE, LOCKTIME_SIZE } from './constants.js';
|
|
5
5
|
import { OutputSatoshisTooSmallError, TokensToNonTokenAddressError, Reason, FailedTransactionError, FailedRequireError, FailedTimeCheckError, FailedSigCheckError, } from './Errors.js';
|
|
6
6
|
// ////////// PARAMETER VALIDATION ////////////////////////////////////////////
|
|
7
|
-
export function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
export function validateOutput(output) {
|
|
8
|
+
if (typeof output.to !== 'string')
|
|
9
|
+
return;
|
|
10
|
+
const minimumAmount = calculateDust(output);
|
|
11
|
+
if (output.amount < minimumAmount) {
|
|
12
|
+
throw new OutputSatoshisTooSmallError(output.amount, BigInt(minimumAmount));
|
|
11
13
|
}
|
|
12
|
-
if (
|
|
13
|
-
if (!isTokenAddress(
|
|
14
|
-
throw new TokensToNonTokenAddressError(
|
|
14
|
+
if (output.token) {
|
|
15
|
+
if (!isTokenAddress(output.to)) {
|
|
16
|
+
throw new TokensToNonTokenAddressError(output.to);
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
|
-
export function calculateDust(
|
|
19
|
-
const outputSize = getOutputSize(
|
|
20
|
+
export function calculateDust(output) {
|
|
21
|
+
const outputSize = getOutputSize(output);
|
|
20
22
|
// Formula used to calculate the minimum allowed output
|
|
21
23
|
const dustAmount = 444 + outputSize * 3;
|
|
22
24
|
return dustAmount;
|
|
@@ -29,6 +31,14 @@ export function encodeOutput(output) {
|
|
|
29
31
|
return encodeTransactionOutput(cashScriptOutputToLibauthOutput(output));
|
|
30
32
|
}
|
|
31
33
|
export function cashScriptOutputToLibauthOutput(output) {
|
|
34
|
+
if (output.token) {
|
|
35
|
+
if (typeof output.token.category !== 'string' || !isHex(output.token.category)) {
|
|
36
|
+
throw new Error(`Provided token category ${output.token?.category} is not a hex string`);
|
|
37
|
+
}
|
|
38
|
+
if (output.token.nft && (typeof output.token.nft.commitment !== 'string' || !isHex(output.token.nft.commitment))) {
|
|
39
|
+
throw new Error(`Provided token commitment ${output.token.nft?.commitment} is not a hex string`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
32
42
|
return {
|
|
33
43
|
lockingBytecode: typeof output.to === 'string' ? addressToLockScript(output.to) : output.to,
|
|
34
44
|
valueSatoshis: output.amount,
|
|
@@ -92,7 +102,7 @@ export function getTxSizeWithoutInputs(outputs) {
|
|
|
92
102
|
let size = VERSION_SIZE + LOCKTIME_SIZE;
|
|
93
103
|
size += outputs.reduce((acc, output) => acc + getOutputSize(output), 0);
|
|
94
104
|
// Add tx-out count (accounting for a potential change output)
|
|
95
|
-
size +=
|
|
105
|
+
size += bigIntToCompactSize(BigInt(outputs.length + 1)).byteLength;
|
|
96
106
|
return size;
|
|
97
107
|
}
|
|
98
108
|
// ////////// BUILD OBJECTS ///////////////////////////////////////////////////
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cashscript",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"description": "Easily write and interact with Bitcoin Cash contracts",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bitcoin cash",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@bitauth/libauth": "^2.0.0-alpha.8",
|
|
47
|
-
"@cashscript/utils": "^0.9.
|
|
47
|
+
"@cashscript/utils": "^0.9.3",
|
|
48
48
|
"bip68": "^1.0.4",
|
|
49
49
|
"bitcoin-rpc-promise-retry": "^1.3.0",
|
|
50
50
|
"delay": "^5.0.0",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"jest": "^29.4.1",
|
|
60
60
|
"typescript": "^4.1.5"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "01f9b9bb552c3c4d63b0c7c8f065a0e23b536ca6"
|
|
63
63
|
}
|