Skip to content

Commit 47a9dbc

Browse files
authored
Merge pull request #311 from CashScript/next
2 parents 78100b2 + 24bab8f commit 47a9dbc

File tree

168 files changed

+13501
-5415
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

168 files changed

+13501
-5415
lines changed

.cspell.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"bitcore",
2424
"bitfield",
2525
"bitfield's",
26+
"bitshift",
2627
"blackie",
2728
"blockbook",
2829
"booland",
@@ -82,6 +83,8 @@
8283
"INPUTINDEX",
8384
"INPUTSEQUENCENUMBER",
8485
"ints",
86+
"introspected",
87+
"introspecting",
8588
"kalis",
8689
"keypair",
8790
"keypairs",
@@ -138,6 +141,7 @@
138141
"prevouts",
139142
"priv",
140143
"pubkey",
144+
"pubkeys",
141145
"pubkeytype",
142146
"pushbytes",
143147
"pushdata",
@@ -155,6 +159,7 @@
155159
"scripthash",
156160
"sdks",
157161
"secp",
162+
"segwit",
158163
"setup",
159164
"sig",
160165
"sighash",
@@ -185,6 +190,7 @@
185190
"unary",
186191
"unlocker",
187192
"unlockers",
193+
"unreached",
188194
"utxo",
189195
"utxo's",
190196
"UTXOBYTECODE",
@@ -199,11 +205,13 @@
199205
"workdir"
200206
],
201207
"ignoreWords": [
208+
"addinput",
202209
"bitcats",
203210
"bitcoincashjs",
204211
"branchup",
205212
"bchguru",
206213
"bchn",
214+
"c0ffee",
207215
"cashcompiler",
208216
"cashninjas",
209217
"chaingraph",
@@ -215,6 +223,7 @@
215223
"getrawtransaction",
216224
"hardhat",
217225
"hodlvault",
226+
"incl",
218227
"infima",
219228
"jedex",
220229
"lichos",
@@ -225,10 +234,12 @@
225234
"outputnulldata",
226235
"outputp",
227236
"pako",
237+
"paytaca",
228238
"popd",
229239
"pushd",
230240
"sendrawtransaction",
231241
"setfiletype",
242+
"setlocktime",
232243
"tada",
233244
"tapswap",
234245
"tokenaut",
@@ -245,6 +256,7 @@
245256
"withopreturn",
246257
"withtime",
247258
"XBVJRKV",
259+
"zapit",
248260
"zwets"
249261
],
250262
"ignorePaths": [
@@ -271,5 +283,10 @@
271283
"**/grammar/**",
272284
// Do not spellcheck vendor code
273285
"**/node_modules/**",
286+
],
287+
"ignoreRegExpList": [
288+
"bitcoincash:.*",
289+
"bchreg:.*",
290+
"bchtest:.*"
274291
]
275292
}

Dockerfile

Lines changed: 0 additions & 30 deletions
This file was deleted.

README.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,33 @@ Using the CashScript SDK, you can import contract artifact files, create new ins
6464
import P2PKH from './p2pkh-artifact.json' with { type: 'json' };
6565

6666
// Instantiate a network provider for CashScript's network operations
67-
const provider = new ElectrumNetworkProvider('mainnet');
67+
const provider = new ElectrumNetworkProvider('chipnet');
6868

6969
// Create a new P2PKH contract with constructor arguments: { pkh: pkh }
70-
const contract = new Contract(P2PKH, [pkh], provider);
70+
const contract = new Contract(P2PKH, [pkh], {provider});
7171

72-
// Get contract balance & output address + balance
72+
// Fetch contract utxos
73+
const contractUtxos = await contract.getUtxos();
74+
75+
// Log contract output address + contract utxos
7376
console.log('contract address:', contract.address);
74-
console.log('contract balance:', await contract.getBalance());
77+
console.log('contract utxos', contractUtxos);
78+
79+
// Specify the contract UTXO
80+
const selectedContractUtxo = contractUtxos[0]
7581

82+
// Start building the transaction
7683
// Call the spend function with the owner's signature
7784
// And use it to send 0. 000 100 00 BCH back to the contract's address
78-
const txDetails = await contract.functions
79-
.spend(pk, new SignatureTemplate(keypair))
80-
.to(contract.address, 10000)
85+
const txDetails = await new TransactionBuilder({ provider })
86+
.addInput(selectedContractUtxo, contract.unlock.spend(new SignatureTemplate(keypair)))
87+
.addOutput({
88+
to: contract.address,
89+
amount: 10000n
90+
})
8191
.send();
8292

8393
console.log(txDetails);
84-
...
8594
```
8695

8796
## Examples

examples/announcement.cash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma cashscript ^0.10.0;
1+
pragma cashscript ^0.11.0;
22

33
/* This is a contract showcasing covenants outside of regular transactional use.
44
* It enforces the contract to make an "announcement" on Memo.cash, and send the

examples/announcement.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Contract, ElectrumNetworkProvider } from 'cashscript';
1+
import { Contract, ElectrumNetworkProvider, Output, TransactionBuilder } from 'cashscript';
22
import { compileFile } from 'cashc';
33
import { stringify } from '@bitauth/libauth';
44
import { URL } from 'url';
@@ -16,20 +16,36 @@ const contract = new Contract(artifact, [], { provider, addressType });
1616

1717
// Get contract balance & output address + balance
1818
console.log('contract address:', contract.address);
19+
const contractUtxos = await contract.getUtxos();
20+
console.log('contract utxos:', contractUtxos);
1921
console.log('contract balance:', await contract.getBalance());
2022
console.log('contract opcount:', contract.opcount);
2123
console.log('contract bytesize:', contract.bytesize);
2224

23-
// Send the announcement. Trying to send any other announcement will fail because
24-
// the contract's covenant logic. Uses a hardcoded fee and minChange so that
25-
// change is only sent back to the contract if there's enough leftover
26-
// for another announcement.
25+
// Select a contract UTXO to spend from
26+
const contractInputUtxo = contractUtxos.find(utxo => utxo.satoshis > 10_000n);
27+
if (!contractInputUtxo) throw new Error('No contract UTXO with enough satoshis found');
28+
const inputAmount = contractInputUtxo.satoshis;
29+
30+
// Announcement string
2731
const str = 'A contract may not injure a human being or, through inaction, allow a human being to come to harm.';
28-
const tx = await contract.functions
29-
.announce()
30-
.withOpReturn(['0x6d02', str])
31-
.withHardcodedFee(1000n)
32-
.withMinChange(1000n)
33-
.send();
32+
33+
// Construct a changeOutput so the leftover BCH can be send back for another announcement
34+
const minerFee = 1000n;
35+
const changeAmount = inputAmount - minerFee;
36+
const contractChangeOutput: Output = {
37+
amount: changeAmount,
38+
to: contract.address,
39+
};
40+
41+
// Send the announcement. Trying to send any other announcement or other change output
42+
// will fail because of the contract's covenant logic
43+
const transactionBuilder = new TransactionBuilder({ provider });
44+
45+
transactionBuilder.addInput(contractInputUtxo, contract.unlock.announce());
46+
transactionBuilder.addOpReturnOutput(['0x6d02', str]);
47+
if (changeAmount > 1000n) transactionBuilder.addOutput(contractChangeOutput);
48+
49+
const tx = await transactionBuilder.send();
3450

3551
console.log('transaction details:', stringify(tx));

examples/common-js.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ export const alicePub = secp256k1.derivePublicKeyCompressed(aliceNode.privateKey
2121
export const alicePriv = aliceNode.privateKey;
2222
export const alicePkh = hash160(alicePub);
2323
export const aliceAddress = encodeCashAddress({ prefix: 'bchtest', type: 'p2pkh', payload: alicePkh, throwErrors: true }).address;
24+
export const aliceTokenAddress = encodeCashAddress({ prefix: 'bchtest', type: 'p2pkhWithTokens', payload: alicePkh, throwErrors: true }).address;

examples/hodl_vault.cash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma cashscript ^0.10.0;
1+
pragma cashscript ^0.11.0;
22

33
// This contract forces HODLing until a certain price target has been reached
44
// A minimum block is provided to ensure that oracle price entries from before this block are disregarded

examples/hodl_vault.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { stringify } from '@bitauth/libauth';
2-
import { Contract, SignatureTemplate, ElectrumNetworkProvider } from 'cashscript';
2+
import { Contract, SignatureTemplate, ElectrumNetworkProvider, TransactionBuilder, Output } from 'cashscript';
33
import { compileFile } from 'cashc';
44
import { URL } from 'url';
55

@@ -24,16 +24,44 @@ const contract = new Contract(artifact, parameters, { provider });
2424

2525
// Get contract balance & output address + balance
2626
console.log('contract address:', contract.address);
27+
const contractUtxos = await contract.getUtxos();
28+
console.log('contract utxos:', contractUtxos);
2729
console.log('contract balance:', await contract.getBalance());
2830

31+
const currentBlockHeight = await provider.getBlockHeight();
32+
console.log('current block height:', currentBlockHeight);
33+
34+
// Select a contract UTXO to spend from
35+
const contractInputUtxo = contractUtxos.find(utxo => utxo.satoshis > 10_000n);
36+
if (!contractInputUtxo) throw new Error('No contract UTXO with enough satoshis found');
37+
const inputAmount = contractInputUtxo.satoshis;
38+
2939
// Produce new oracle message and signature
3040
const oracleMessage = oracle.createMessage(100000n, 30000n);
3141
const oracleSignature = oracle.signMessage(oracleMessage);
3242

43+
// construct an output
44+
const outputAmount = 1000n;
45+
const output: Output = { amount: outputAmount, to: contract.address };
46+
47+
// Construct a changeOutput
48+
const minerFee = 1000n;
49+
const changeAmount = inputAmount - outputAmount - minerFee;
50+
const changeOutput: Output = {
51+
amount: changeAmount,
52+
to: contract.address,
53+
};
54+
55+
const aliceTemplate = new SignatureTemplate(alicePriv);
56+
3357
// Spend from the vault
34-
const tx = await contract.functions
35-
.spend(new SignatureTemplate(alicePriv), oracleSignature, oracleMessage)
36-
.to(contract.address, 1000n)
37-
.send();
58+
const transactionBuilder = new TransactionBuilder({ provider });
59+
60+
transactionBuilder.setLocktime(currentBlockHeight);
61+
transactionBuilder.addInput(contractInputUtxo, contract.unlock.spend(aliceTemplate, oracleSignature, oracleMessage));
62+
transactionBuilder.addOutput(output);
63+
if (changeAmount > 1000n) transactionBuilder.addOutput(changeOutput);
64+
65+
const tx = await transactionBuilder.send();
3866

3967
console.log(stringify(tx));

examples/mecenas.cash

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma cashscript ^0.10.0;
1+
pragma cashscript ^0.11.0;
22

33
/* This is an unofficial CashScript port of Licho's Mecenas contract. It is
44
* not compatible with Licho's EC plugin, but rather meant as a demonstration
@@ -7,7 +7,7 @@ pragma cashscript ^0.10.0;
77
*/
88
contract Mecenas(bytes20 recipient, bytes20 funder, int pledge/*, int period */) {
99
function receive() {
10-
// require(tx.age >= period);
10+
// require(this.age >= period);
1111

1212
// Check that the first output sends to the recipient
1313
require(tx.outputs[0].lockingBytecode == new LockingBytecodeP2PKH(recipient));

examples/mecenas.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { stringify } from '@bitauth/libauth';
2-
import { Contract, ElectrumNetworkProvider } from 'cashscript';
2+
import { Contract, ElectrumNetworkProvider, Output, TransactionBuilder } from 'cashscript';
33
import { compileFile } from 'cashc';
44
import { URL } from 'url';
55

@@ -15,21 +15,44 @@ const provider = new ElectrumNetworkProvider('chipnet');
1515
// Instantiate a new contract using the compiled artifact and network provider
1616
// AND providing the constructor parameters:
1717
// (recipient: alicePkh, funder: bobPkh, pledge: 10000)
18-
const contract = new Contract(artifact, [alicePkh, bobPkh, 10000n], { provider });
18+
const pledgeAmount = 10_000n;
19+
const contract = new Contract(artifact, [alicePkh, bobPkh, pledgeAmount], { provider });
1920

2021
// Get contract balance & output address + balance
2122
console.log('contract address:', contract.address);
23+
const contractUtxos = await contract.getUtxos();
24+
console.log('contract utxos:', contractUtxos);
2225
console.log('contract balance:', await contract.getBalance());
2326
console.log('contract opcount:', contract.opcount);
2427
console.log('contract bytesize:', contract.bytesize);
2528

29+
// Select a contract UTXO to spend from
30+
const contractInputUtxo = contractUtxos.find(utxo => utxo.satoshis > 10_000n);
31+
if (!contractInputUtxo) throw new Error('No contract UTXO with enough satoshis found');
32+
const inputAmount = contractInputUtxo.satoshis;
33+
34+
const receiverOutput: Output = {
35+
amount: 10_000n,
36+
to: aliceAddress,
37+
};
38+
39+
// Construct the changeOutput
40+
const minerFee = 1000n;
41+
const changeAmount = inputAmount - pledgeAmount - minerFee;
42+
const contractChangeOutput: Output = {
43+
amount: changeAmount,
44+
to: contract.address,
45+
};
46+
2647
// Call the transfer function with any signature
2748
// Will send one pledge amount to alice, and send change back to the contract
2849
// Manually set fee to 1000 because this is hardcoded in the contract
29-
const tx = await contract.functions
30-
.receive()
31-
.to(aliceAddress, 10000n)
32-
.withHardcodedFee(1000n)
33-
.send();
50+
const transactionBuilder = new TransactionBuilder({ provider });
51+
52+
transactionBuilder.addInput(contractInputUtxo, contract.unlock.receive());
53+
transactionBuilder.addOutput(receiverOutput);
54+
if (changeAmount > pledgeAmount + minerFee) transactionBuilder.addOutput(contractChangeOutput);
55+
56+
const tx = await transactionBuilder.send();
3457

3558
console.log('transaction details:', stringify(tx));

0 commit comments

Comments
 (0)