cashscript 0.8.0-next.3 → 0.8.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/dist/Transaction.js +25 -20
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/package.json +3 -3
package/dist/Transaction.js
CHANGED
|
@@ -4,6 +4,7 @@ import { hash256, placeholder, scriptToBytecode, } from '@cashscript/utils';
|
|
|
4
4
|
import { isSignableUtxo, } from './interfaces.js';
|
|
5
5
|
import { meep, createInputScript, getInputSize, createOpReturnOutput, getTxSizeWithoutInputs, getPreimageSize, buildError, createSighashPreimage, validateRecipient, utxoComparator, cashScriptOutputToLibauthOutput, calculateDust, getOutputSize, addressToLockScript, publicKeyToP2PKHLockingBytecode, utxoTokenComparator, } from './utils.js';
|
|
6
6
|
import SignatureTemplate from './SignatureTemplate.js';
|
|
7
|
+
import { P2PKH_INPUT_SIZE } from './constants.js';
|
|
7
8
|
const bip68 = await import('bip68');
|
|
8
9
|
export class Transaction {
|
|
9
10
|
constructor(address, provider, redeemScript, abiFunction, args, selector) {
|
|
@@ -178,15 +179,15 @@ export class Transaction {
|
|
|
178
179
|
throw Error('Attempted to build a transaction without outputs');
|
|
179
180
|
}
|
|
180
181
|
const allUtxos = await this.provider.getUtxos(this.address);
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
const tokenInputs = this.inputs.length > 0
|
|
183
|
+
? this.inputs.filter((input) => input.token)
|
|
184
|
+
: selectAllTokenUtxos(allUtxos, this.outputs);
|
|
185
|
+
// This throws if the manually selected inputs are not enough to cover the outputs
|
|
186
|
+
if (this.inputs.length > 0) {
|
|
187
|
+
selectAllTokenUtxos(this.inputs, this.outputs);
|
|
185
188
|
}
|
|
186
|
-
const automaticTokenInputs = selectAllTokenUtxos(allUtxos, this.outputs);
|
|
187
|
-
const tokenInputs = manualTokenInputs.length > 0 ? manualTokenInputs : automaticTokenInputs;
|
|
188
189
|
if (this.tokenChange) {
|
|
189
|
-
const tokenChangeOutputs =
|
|
190
|
+
const tokenChangeOutputs = createFungibleTokenChangeOutputs(tokenInputs, this.outputs, this.address);
|
|
190
191
|
this.outputs.push(...tokenChangeOutputs);
|
|
191
192
|
}
|
|
192
193
|
// Construct list with all nfts in inputs
|
|
@@ -281,7 +282,7 @@ export class Transaction {
|
|
|
281
282
|
// arguments and correctly sized placeholder preimage
|
|
282
283
|
const placeholderScript = createInputScript(this.redeemScript, placeholderArgs, this.selector, placeholderPreimage);
|
|
283
284
|
// Add one extra byte per input to over-estimate tx-in count
|
|
284
|
-
const
|
|
285
|
+
const contractInputSize = getInputSize(placeholderScript) + 1;
|
|
285
286
|
// Note that we use the addPrecision function to add "decimal points" to BigInt numbers
|
|
286
287
|
// Calculate amount to send and base fee (excluding additional fees per UTXO)
|
|
287
288
|
let amount = addPrecision(this.outputs.reduce((acc, output) => acc + output.amount, 0n));
|
|
@@ -290,8 +291,10 @@ export class Transaction {
|
|
|
290
291
|
let satsAvailable = 0n;
|
|
291
292
|
if (this.inputs.length > 0) {
|
|
292
293
|
// If inputs are already defined, the user provided the UTXOs and we perform no further UTXO selection
|
|
293
|
-
if (!this.hardcodedFee)
|
|
294
|
-
|
|
294
|
+
if (!this.hardcodedFee) {
|
|
295
|
+
const totalInputSize = this.inputs.reduce((acc, input) => acc + (isSignableUtxo(input) ? P2PKH_INPUT_SIZE : contractInputSize), 0);
|
|
296
|
+
fee += addPrecision(totalInputSize * this.feePerByte);
|
|
297
|
+
}
|
|
295
298
|
satsAvailable = addPrecision(this.inputs.reduce((acc, input) => acc + input.satoshis, 0n));
|
|
296
299
|
}
|
|
297
300
|
else {
|
|
@@ -301,11 +304,11 @@ export class Transaction {
|
|
|
301
304
|
// even if they report UTXOs in a different order
|
|
302
305
|
bchUtxos.sort(utxoComparator).reverse();
|
|
303
306
|
// Add all automatically added token inputs to the transaction
|
|
304
|
-
for (const utxo of
|
|
307
|
+
for (const utxo of tokenInputs) {
|
|
305
308
|
this.inputs.push(utxo);
|
|
306
309
|
satsAvailable += addPrecision(utxo.satoshis);
|
|
307
310
|
if (!this.hardcodedFee)
|
|
308
|
-
fee += addPrecision(
|
|
311
|
+
fee += addPrecision(contractInputSize * this.feePerByte);
|
|
309
312
|
}
|
|
310
313
|
for (const utxo of bchUtxos) {
|
|
311
314
|
if (satsAvailable > amount + fee)
|
|
@@ -313,7 +316,7 @@ export class Transaction {
|
|
|
313
316
|
this.inputs.push(utxo);
|
|
314
317
|
satsAvailable += addPrecision(utxo.satoshis);
|
|
315
318
|
if (!this.hardcodedFee)
|
|
316
|
-
fee += addPrecision(
|
|
319
|
+
fee += addPrecision(contractInputSize * this.feePerByte);
|
|
317
320
|
}
|
|
318
321
|
}
|
|
319
322
|
// Remove "decimal points" from BigInt numbers (rounding up for fee, down for others)
|
|
@@ -349,10 +352,9 @@ const calculateTotalTokenAmount = (outputs, tokenCategory) => (outputs
|
|
|
349
352
|
.reduce((acc, output) => acc + output.token.amount, 0n));
|
|
350
353
|
const selectTokenUtxos = (utxos, amountNeeded, tokenCategory) => {
|
|
351
354
|
const genesisUtxo = getTokenGenesisUtxo(utxos, tokenCategory);
|
|
352
|
-
if (genesisUtxo)
|
|
355
|
+
if (genesisUtxo)
|
|
353
356
|
return [genesisUtxo];
|
|
354
|
-
|
|
355
|
-
const tokenUtxos = utxos.filter((utxo) => utxo.token?.category === tokenCategory);
|
|
357
|
+
const tokenUtxos = utxos.filter((utxo) => utxo.token?.category === tokenCategory && utxo.token?.amount > 0n);
|
|
356
358
|
// We sort the UTXOs mainly so there is consistent behaviour between network providers
|
|
357
359
|
// even if they report UTXOs in a different order
|
|
358
360
|
tokenUtxos.sort(utxoTokenComparator).reverse();
|
|
@@ -360,10 +362,10 @@ const selectTokenUtxos = (utxos, amountNeeded, tokenCategory) => {
|
|
|
360
362
|
const selectedUtxos = [];
|
|
361
363
|
// Add token UTXOs until we have enough to cover the amount needed (no fee calculation because it's a token)
|
|
362
364
|
for (const utxo of tokenUtxos) {
|
|
363
|
-
selectedUtxos.push(utxo);
|
|
364
|
-
amountAvailable += utxo.token.amount;
|
|
365
365
|
if (amountAvailable >= amountNeeded)
|
|
366
366
|
break;
|
|
367
|
+
selectedUtxos.push(utxo);
|
|
368
|
+
amountAvailable += utxo.token.amount;
|
|
367
369
|
}
|
|
368
370
|
if (amountAvailable < amountNeeded) {
|
|
369
371
|
throw new Error(`Insufficient funds for token ${tokenCategory}: available (${amountAvailable}) < needed (${amountNeeded}).`);
|
|
@@ -374,14 +376,17 @@ const selectAllTokenUtxos = (utxos, outputs) => {
|
|
|
374
376
|
const tokenCategories = getTokenCategories(outputs);
|
|
375
377
|
return tokenCategories.flatMap((tokenCategory) => selectTokenUtxos(utxos, calculateTotalTokenAmount(outputs, tokenCategory), tokenCategory));
|
|
376
378
|
};
|
|
377
|
-
const
|
|
379
|
+
const createFungibleTokenChangeOutputs = (utxos, outputs, address) => {
|
|
378
380
|
const tokenCategories = getTokenCategories(utxos);
|
|
379
|
-
|
|
381
|
+
const changeOutputs = tokenCategories.map((tokenCategory) => {
|
|
380
382
|
const required = calculateTotalTokenAmount(outputs, tokenCategory);
|
|
381
383
|
const available = calculateTotalTokenAmount(utxos, tokenCategory);
|
|
382
384
|
const change = available - required;
|
|
385
|
+
if (change === 0n)
|
|
386
|
+
return undefined;
|
|
383
387
|
return { to: address, amount: BigInt(1000), token: { category: tokenCategory, amount: change } };
|
|
384
388
|
});
|
|
389
|
+
return changeOutputs.filter((output) => output !== undefined);
|
|
385
390
|
};
|
|
386
391
|
// Note: the below is a very simple implementation of a "decimal point" system for BigInt numbers
|
|
387
392
|
// It is safe to use for UTXO fee calculations due to its low numbers, but should not be used for other purposes
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import SignatureTemplate from './SignatureTemplate.js';
|
|
|
2
2
|
export { SignatureTemplate };
|
|
3
3
|
export { Contract, ContractFunction } from './Contract.js';
|
|
4
4
|
export { Transaction } from './Transaction.js';
|
|
5
|
-
export { Argument } from './Argument.js';
|
|
5
|
+
export { Argument, encodeArgument } from './Argument.js';
|
|
6
6
|
export { Artifact, AbiFunction, AbiInput } from '@cashscript/utils';
|
|
7
7
|
export * as utils from '@cashscript/utils';
|
|
8
|
-
export { Utxo, Recipient, SignatureAlgorithm, HashType, Network, } from './interfaces.js';
|
|
8
|
+
export { Utxo, Recipient, SignatureAlgorithm, HashType, Network, isSignableUtxo, } from './interfaces.js';
|
|
9
9
|
export * from './Errors.js';
|
|
10
10
|
export { NetworkProvider, BitcoinRpcNetworkProvider, ElectrumNetworkProvider, FullStackNetworkProvider, } from './network/index.js';
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,9 @@ import SignatureTemplate from './SignatureTemplate.js';
|
|
|
2
2
|
export { SignatureTemplate };
|
|
3
3
|
export { Contract } from './Contract.js';
|
|
4
4
|
export { Transaction } from './Transaction.js';
|
|
5
|
+
export { encodeArgument } from './Argument.js';
|
|
5
6
|
export * as utils from '@cashscript/utils';
|
|
6
|
-
export { SignatureAlgorithm, HashType, Network, } from './interfaces.js';
|
|
7
|
+
export { SignatureAlgorithm, HashType, Network, isSignableUtxo, } from './interfaces.js';
|
|
7
8
|
export * from './Errors.js';
|
|
8
9
|
export { BitcoinRpcNetworkProvider, ElectrumNetworkProvider, FullStackNetworkProvider, } from './network/index.js';
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cashscript",
|
|
3
|
-
"version": "0.8.0
|
|
3
|
+
"version": "0.8.0",
|
|
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.8.0
|
|
47
|
+
"@cashscript/utils": "^0.8.0",
|
|
48
48
|
"bip68": "^1.0.4",
|
|
49
49
|
"bitcoin-rpc-promise-retry": "^1.3.0",
|
|
50
50
|
"delay": "^5.0.0",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"jest": "^29.4.1",
|
|
59
59
|
"typescript": "^4.1.5"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "9864e23e5b7eb024cf4712a785a5a3fe09d6eee5"
|
|
62
62
|
}
|