Skip to content
Draft

v0.13 #370

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/announcement.cash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.12.0;
pragma cashscript ^0.13.0;

/* This is a contract showcasing covenants outside of regular transactional use.
* It enforces the contract to make an "announcement" on Memo.cash, and send the
Expand Down
11 changes: 9 additions & 2 deletions examples/announcement.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { Contract, ElectrumNetworkProvider, Output, TransactionBuilder } from 'cashscript';
import { Contract, Output, randomUtxo, TransactionBuilder } from 'cashscript';
import { compileFile } from 'cashc';
import { stringify } from '@bitauth/libauth';
import { URL } from 'url';
import { MockNetworkProvider } from 'cashscript/dist';

// Compile the Announcement contract to an artifact object
const artifact = compileFile(new URL('announcement.cash', import.meta.url));

// Initialise a network provider for network operations on MAINNET
const addressType = 'p2sh20';
const provider = new ElectrumNetworkProvider();

// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
// const provider = new ElectrumNetworkProvider();
const provider = new MockNetworkProvider();

// Instantiate a new contract using the compiled artifact and network provider
// AND providing the constructor parameters (none)
const contract = new Contract(artifact, [], { provider, addressType });

// Add a mock UTXO to the mock network provider
provider.addUtxo(contract.address, randomUtxo());

// Get contract balance & output address + balance
console.log('contract address:', contract.address);
const contractUtxos = await contract.getUtxos();
Expand Down
4 changes: 2 additions & 2 deletions examples/hodl_vault.cash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.12.0;
pragma cashscript ^0.13.0;

// This contract forces HODLing until a certain price target has been reached
// A minimum block is provided to ensure that oracle price entries from before this block are disregarded
Expand All @@ -11,7 +11,7 @@ contract HodlVault(
int minBlock,
int priceTarget
) {
function spend(sig ownerSig, datasig oracleSig, bytes oracleMessage) {
function spend(sig ownerSig, datasig oracleSig, bytes8 oracleMessage) {
// message: { blockHeight, price }
bytes4 blockHeightBin, bytes4 priceBin = oracleMessage.split(4);
int blockHeight = int(blockHeightBin);
Expand Down
10 changes: 7 additions & 3 deletions examples/hodl_vault.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { stringify } from '@bitauth/libauth';
import { Contract, SignatureTemplate, ElectrumNetworkProvider, TransactionBuilder, Output } from 'cashscript';
import { Contract, SignatureTemplate, TransactionBuilder, Output, MockNetworkProvider, randomUtxo } from 'cashscript';
import { compileFile } from 'cashc';
import { URL } from 'url';

Expand All @@ -14,14 +14,18 @@ import {
// Compile the HodlVault contract to an artifact object
const artifact = compileFile(new URL('hodl_vault.cash', import.meta.url));

// Initialise a network provider for network operations on CHIPNET
const provider = new ElectrumNetworkProvider('chipnet');
// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
// const provider = new ElectrumNetworkProvider();
const provider = new MockNetworkProvider();

// Instantiate a new contract using the compiled artifact and network provider
// AND providing the constructor parameters
const parameters = [alicePub, oraclePub, 100000n, 30000n];
const contract = new Contract(artifact, parameters, { provider });

// Add a mock UTXO to the mock network provider
provider.addUtxo(contract.address, randomUtxo());

// Get contract balance & output address + balance
console.log('contract address:', contract.address);
const contractUtxos = await contract.getUtxos();
Expand Down
2 changes: 1 addition & 1 deletion examples/mecenas.cash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.12.0;
pragma cashscript ^0.13.0;

/* This is an unofficial CashScript port of Licho's Mecenas contract. It is
* not compatible with Licho's EC plugin, but rather meant as a demonstration
Expand Down
10 changes: 7 additions & 3 deletions examples/mecenas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { stringify } from '@bitauth/libauth';
import { Contract, ElectrumNetworkProvider, Output, TransactionBuilder } from 'cashscript';
import { Contract, MockNetworkProvider, Output, randomUtxo, TransactionBuilder } from 'cashscript';
import { compileFile } from 'cashc';
import { URL } from 'url';

Expand All @@ -9,15 +9,19 @@ import { aliceAddress, alicePkh, bobPkh } from './common.js';
// Compile the Mecenas contract to an artifact object
const artifact = compileFile(new URL('mecenas.cash', import.meta.url));

// Initialise a network provider for network operations on CHIPNET
const provider = new ElectrumNetworkProvider('chipnet');
// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
// const provider = new ElectrumNetworkProvider();
const provider = new MockNetworkProvider();

// Instantiate a new contract using the compiled artifact and network provider
// AND providing the constructor parameters:
// (recipient: alicePkh, funder: bobPkh, pledge: 10000)
const pledgeAmount = 10_000n;
const contract = new Contract(artifact, [alicePkh, bobPkh, pledgeAmount], { provider });

// Add a mock UTXO to the mock network provider
provider.addUtxo(contract.address, randomUtxo());

// Get contract balance & output address + balance
console.log('contract address:', contract.address);
const contractUtxos = await contract.getUtxos();
Expand Down
2 changes: 1 addition & 1 deletion examples/mecenas_locktime.cash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.12.0;
pragma cashscript ^0.13.0;

// This is an experimental contract for a more "streaming" Mecenas experience
// Completely untested, just a concept
Expand Down
2 changes: 1 addition & 1 deletion examples/p2pkh.cash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.12.0;
pragma cashscript ^0.13.0;

contract P2PKH(bytes20 pkh) {
// Require pk to match stored pkh and signature to match
Expand Down
12 changes: 8 additions & 4 deletions examples/p2pkh.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { URL } from 'url';
import { compileFile } from 'cashc';
import { ElectrumNetworkProvider, Contract, SignatureTemplate, TransactionBuilder } from 'cashscript';
import { Contract, SignatureTemplate, TransactionBuilder, MockNetworkProvider, randomUtxo } from 'cashscript';
import { stringify } from '@bitauth/libauth';

// Import Alice's keys from common.ts
Expand All @@ -9,13 +9,17 @@ import { alicePkh, alicePriv, aliceAddress, alicePub } from './common.js';
// Compile the P2PKH contract to an artifact object
const artifact = compileFile(new URL('p2pkh.cash', import.meta.url));

// Initialise a network provider for network operations on CHIPNET
const provider = new ElectrumNetworkProvider('chipnet');
// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
// const provider = new ElectrumNetworkProvider();
const provider = new MockNetworkProvider();

// Instantiate a new contract using the compiled artifact and network provider
// AND providing the constructor parameters (pkh: alicePkh)
const contract = new Contract(artifact, [alicePkh], { provider });

// Add a mock UTXO to the mock network provider
provider.addUtxo(contract.address, randomUtxo());

// Get contract balance & output address + balance
console.log('contract address:', contract.address);
const contractUtxos = await contract.getUtxos();
Expand Down Expand Up @@ -52,4 +56,4 @@ if (changeAmount > 1000n) transactionBuilder.addOutput(changeOutput);

const tx = await transactionBuilder.send();

console.log('transaction details:', stringify(tx));
console.log('transaction details:', stringify(tx));
10 changes: 7 additions & 3 deletions examples/p2pkh.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { stringify } from '@bitauth/libauth';
import { compileFile } from 'cashc';
import { ElectrumNetworkProvider, SignatureTemplate, Contract, TransactionBuilder, Output } from 'cashscript';
import { SignatureTemplate, Contract, TransactionBuilder, Output, MockNetworkProvider, randomUtxo } from 'cashscript';
import { URL } from 'url';

// Import Alice's keys from common.ts
Expand All @@ -9,13 +9,17 @@ import { alicePkh, alicePriv, aliceAddress, alicePub } from './common.js';
// Compile the P2PKH contract to an artifact object
const artifact = compileFile(new URL('p2pkh.cash', import.meta.url));

// Initialise a network provider for network operations on CHIPNET
const provider = new ElectrumNetworkProvider('chipnet');
// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
// const provider = new ElectrumNetworkProvider();
const provider = new MockNetworkProvider();

// Instantiate a new contract using the compiled artifact and network provider
// AND providing the constructor parameters (pkh: alicePkh)
const contract = new Contract(artifact, [alicePkh], { provider });

// Add a mock UTXO to the mock network provider
provider.addUtxo(contract.address, randomUtxo());

// Get contract balance & output address + balance
console.log('contract address:', contract.address);
const contractUtxos = await contract.getUtxos();
Expand Down
6 changes: 3 additions & 3 deletions examples/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cashscript-examples",
"private": true,
"version": "0.12.0",
"version": "0.13.0-next.0",
"description": "Usage examples of the CashScript SDK",
"main": "p2pkh.js",
"type": "module",
Expand All @@ -13,8 +13,8 @@
"dependencies": {
"@bitauth/libauth": "^3.1.0-next.8",
"@types/node": "^22.17.0",
"cashc": "^0.12.0",
"cashscript": "^0.12.0",
"cashc": "^0.13.0-next.0",
"cashscript": "^0.13.0-next.0",
"eslint": "^8.56.0",
"typescript": "^5.9.2"
}
Expand Down
4 changes: 2 additions & 2 deletions examples/testing-suite/artifacts/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
"compiler": {
"name": "cashc",
"version": "0.12.0"
"version": "0.13.0"
},
"updatedAt": "2025-10-02T09:56:11.510Z"
}
}
6 changes: 3 additions & 3 deletions examples/testing-suite/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "testing-suite",
"version": "0.12.0",
"version": "0.13.0-next.0",
"description": "Example project to develop and test CashScript contracts",
"main": "index.js",
"type": "module",
Expand All @@ -26,8 +26,8 @@
},
"dependencies": {
"@bitauth/libauth": "^3.1.0-next.8",
"cashc": "^0.12.0",
"cashscript": "^0.12.0",
"cashc": "^0.13.0-next.0",
"cashscript": "^0.13.0-next.0",
"url-join": "^5.0.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/transfer_with_timeout.cash
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.12.0;
pragma cashscript ^0.13.0;

contract TransferWithTimeout(
pubkey sender,
Expand Down
10 changes: 7 additions & 3 deletions examples/transfer_with_timeout.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { stringify } from '@bitauth/libauth';
import { compileFile } from 'cashc';
import { Contract, ElectrumNetworkProvider, Output, SignatureTemplate, TransactionBuilder } from 'cashscript';
import { Contract, MockNetworkProvider, Output, randomUtxo, SignatureTemplate, TransactionBuilder } from 'cashscript';
import { URL } from 'url';

// Import Bob and Alice's keys from common.ts
Expand All @@ -14,14 +14,18 @@ import {
// Compile the TransferWithTimeout contract
const artifact = compileFile(new URL('transfer_with_timeout.cash', import.meta.url));

// Initialise a network provider for network operations on CHIPNET
const provider = new ElectrumNetworkProvider('chipnet');
// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
// const provider = new ElectrumNetworkProvider();
const provider = new MockNetworkProvider();

// Instantiate a new contract using the compiled artifact and network provider
// AND providing the constructor parameters:
// { sender: alicePk, recipient: bobPk, timeout: 1000000 } - timeout is a past block
const contract = new Contract(artifact, [alicePub, bobPub, 100000n], { provider });

// Add a mock UTXO to the mock network provider
provider.addUtxo(contract.address, randomUtxo());

// Get contract balance & output address + balance
console.log('contract address:', contract.address);
const contractUtxos = await contract.getUtxos();
Expand Down
4 changes: 2 additions & 2 deletions packages/cashc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cashc",
"version": "0.12.0",
"version": "0.13.0-next.0",
"description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts",
"keywords": [
"bitcoin",
Expand Down Expand Up @@ -52,7 +52,7 @@
},
"dependencies": {
"@bitauth/libauth": "^3.1.0-next.8",
"@cashscript/utils": "^0.12.0",
"@cashscript/utils": "^0.13.0-next.0",
"antlr4": "^4.13.2",
"commander": "^14.0.0",
"semver": "^7.7.2"
Expand Down
13 changes: 13 additions & 0 deletions packages/cashc/src/ast/AST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@ export class BranchNode extends StatementNode {
}
}

export class DoWhileNode extends StatementNode {
constructor(
public condition: ExpressionNode,
public block: BlockNode,
) {
super();
}

accept<T>(visitor: AstVisitor<T>): T {
return visitor.visitDoWhile(this);
}
}

export class BlockNode extends Node {
symbolTable?: SymbolTable;

Expand Down
15 changes: 15 additions & 0 deletions packages/cashc/src/ast/AstBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
ConsoleStatementNode,
ConsoleParameterNode,
SliceNode,
DoWhileNode,
} from './AST.js';
import { UnaryOperator, BinaryOperator, NullaryOperator } from './Operator.js';
import type {
Expand Down Expand Up @@ -68,6 +69,8 @@ import type {
StatementContext,
RequireMessageContext,
SliceContext,
DoWhileStatementContext,
LoopStatementContext,
} from '../grammar/CashScriptParser.js';
import CashScriptVisitor from '../grammar/CashScriptVisitor.js';
import { Location } from './Location.js';
Expand Down Expand Up @@ -214,6 +217,18 @@ export default class AstBuilder
return branch;
}

visitLoopStatement(ctx: LoopStatementContext): DoWhileNode {
return this.visit(ctx.doWhileStatement()) as DoWhileNode;
}

visitDoWhileStatement(ctx: DoWhileStatementContext): DoWhileNode {
const condition = this.visit(ctx.expression());
const block = this.visit(ctx.block()) as StatementNode;
const doWhile = new DoWhileNode(condition, block);
doWhile.location = Location.fromCtx(ctx);
return doWhile;
}

visitBlock(ctx: BlockContext): BlockNode {
const statements = ctx.statement_list().map((s) => this.visit(s) as StatementNode);
const block = new BlockNode(statements);
Expand Down
7 changes: 7 additions & 0 deletions packages/cashc/src/ast/AstTraversal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
ConsoleStatementNode,
ConsoleParameterNode,
SliceNode,
DoWhileNode,
} from './AST.js';
import AstVisitor from './AstVisitor.js';

Expand Down Expand Up @@ -86,6 +87,12 @@ export default class AstTraversal extends AstVisitor<Node> {
return node;
}

visitDoWhile(node: DoWhileNode): Node {
node.condition = this.visit(node.condition);
node.block = this.visit(node.block) as StatementNode;
return node;
}

visitBlock(node: BlockNode): Node {
node.statements = this.visitOptionalList(node.statements) as StatementNode[];
return node;
Expand Down
2 changes: 2 additions & 0 deletions packages/cashc/src/ast/AstVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
NullaryOpNode,
ConsoleStatementNode,
SliceNode,
DoWhileNode,
} from './AST.js';

export default abstract class AstVisitor<T> {
Expand All @@ -39,6 +40,7 @@ export default abstract class AstVisitor<T> {
abstract visitTimeOp(node: TimeOpNode): T;
abstract visitRequire(node: RequireNode): T;
abstract visitBranch(node: BranchNode): T;
abstract visitDoWhile(node: DoWhileNode): T;
abstract visitBlock(node: BlockNode): T;
abstract visitCast(node: CastNode): T;
abstract visitFunctionCall(node: FunctionCallNode): T;
Expand Down
2 changes: 1 addition & 1 deletion packages/cashc/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const MAX_INPUT_BYTESIZE = 1650;
export const MAX_INPUT_BYTESIZE = 10_000;
Loading