Simply CLI + Elements - Complete Workflow
Overview
This guide shows the complete command-line workflow for developing and deploying Simplicity contracts using simply and elements-cli.
Tools used:
simply- SimplicityHL development toolkitelements-cli- Liquid node clientcurl- API requests to Liquid testnet
Note: hal-simplicity is under active development. This guide uses simply which is production-ready.
Setup
Install Tools
simply:
Elements Core (includes elements-cli):
Download from https://github.com/ElementsProject/elements/releases and install.
Verify Installation
Complete Workflow
1. Create Contract
2. Compile Contract
Output:
3. Generate P2TR Address
Output:
4. Fund Address
Request from faucet:
curl "https://liquidtestnet.com/faucet?address=tex1p5m8j7r2qf9h8xvua5jk3n4l6p8r9t2s4v6w8x&action=lbtc"
Replace tex1p5m8j... with your actual address.
Check balance:
curl "https://blockstream.info/liquidtestnet/api/address/tex1p5m8j7r2qf9h8xvua5jk3n4l6p8r9t2s4v6w8x/utxo"
Response:
[{
"txid": "c2f44551601034af3cc0d004b5b486d558c867bd9bc4f97123e48e4ddd3b8d42",
"vout": 0,
"value": 100000
}]
5. Create Witness (If Required)
For contracts needing witness data:
For always_true: No witness needed (empty file or omit).
6. Build Spending Transaction
simply withdraw --entrypoint always_true.simf --txid c2f44551601034af3cc0d004b5b486d558c867bd9bc4f97123e48e4ddd3b8d42 --destination tex1qrecipient7r2qf9h8xvua5jk3n4l6p8r9t2s4v6w8x
Replace:
<txid>- From step 4<destination>- Where to send funds
What this does:
- Fetches UTXO from blockchain
- Builds complete transaction
- Encodes Simplicity program and witness
- Broadcasts to Liquid testnet
Output:
7. Verify Transaction
Check status:
Response:
P2PK Contract Example
Create P2PK Contract
fn main() {
let pk: Pubkey = 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798;
let msg: u256 = jet::sig_all_hash();
let sig: Signature = witness::signature;
jet::bip_0340_verify(pk, msg, sig)
}
Compile
Get Address
Output: tex1p7a8b9c...
Fund
Get UTXO Details
Understanding Sighash (Internal Process)
Note: When using simply withdraw, sighash computation is automatic. You don't manually compute it.
What simply does internally:
Code reference: simply/src/transaction.rs
// simply builds the transaction environment
let tx_env = ElementsEnv::new(
transaction,
vec![utxo],
input_index,
cmr,
control_block,
None,
genesis_hash // Liquid testnet: a771da8e...
);
// Computes sighash automatically
let sighash = tx_env.c_tx_env().sighash_all();
Sighash includes:
- All transaction inputs and outputs
- Genesis hash (network identifier)
- Spent UTXO data
- Locktime and sequence
For contracts needing signatures:
The contract code accesses sighash via:
This returns the sighash that signatures must commit to.
If you need to sign manually (advanced):
You would need to: 1. Build the transaction 2. Compute sighash using ElementsEnv 3. Sign with BIP-340 Schnorr 4. Provide signature in witness file
But simply handles this for you when you use withdraw with a witness file.
Creating Signatures (For P2PK Contracts)
For contracts requiring signatures, you need:
- A tool that computes transaction sighash
- A signing tool supporting BIP-340 Schnorr signatures
- Your private key
Signing options:
- Liquid wallet with signing capabilities
- Hardware wallet with Schnorr support
- Software cryptographic libraries
- External signing services
Once you have the 64-byte signature, create the witness file.
Create Witness File
Spend
simply withdraw --entrypoint p2pk.simf --txid abc123... --destination tex1qdest... --witness witness.wit
Working with Elements Node
Start Liquid Testnet Node
Create Wallet
Generate Address
Get Balance
Send Transaction
API Workflow (No Node Required)
Check Address Balance
Get Transaction
Get Transaction Hex
Broadcast Transaction
Check Confirmation
Response:
Complete Example: Deploy & Execute
Create Contract File
Compile
Get Address
Copy the address, e.g., tex1p5m8j7r2qf9h8xvua5jk3n4l6p8r9t2s4v6w8x
Fund
curl "https://liquidtestnet.com/faucet?address=tex1p5m8j7r2qf9h8xvua5jk3n4l6p8r9t2s4v6w8x&action=lbtc"
Wait & Check
sleep 60
curl "https://blockstream.info/liquidtestnet/api/address/tex1p5m8j7r2qf9h8xvua5jk3n4l6p8r9t2s4v6w8x/utxo" | jq '.[0]'
Spend
simply withdraw --entrypoint my_contract.simf --txid c2f44551601034af3cc0d004b5b486d558c867bd9bc4f97123e48e4ddd3b8d42 --destination tex1qrecipient7address
Verify
Development Workflow
Test Locally First
Shows execution trace:
- Each step
- Jet calls
- Debug output
Run Test Suite
Finds and runs all test_* functions in .simf files.
Build with Statistics
Shows:
- Cost bounds
- Memory usage
- Program size
Network Parameters
Liquid Testnet
Genesis Hash:
L-BTC Asset ID:
Explorer API:
Endpoints:
/address/<address>/utxo- Get UTXOs/tx/<txid>- Get transaction/tx/<txid>/status- Check confirmation/tx(POST) - Broadcast transaction
Common Commands Reference
simply Commands
simply build --entrypoint <file>
simply run --entrypoint <file> --logging <level>
simply test
simply deposit --entrypoint <file>
simply withdraw --entrypoint <file> --txid <txid> --destination <address>
Liquid Testnet API
# Fund address
curl "https://liquidtestnet.com/faucet?address=<address>&action=lbtc"
# Check UTXOs
curl "https://blockstream.info/liquidtestnet/api/address/<address>/utxo"
# Get transaction
curl "https://blockstream.info/liquidtestnet/api/tx/<txid>"
# Broadcast transaction
curl -X POST "https://blockstream.info/liquidtestnet/api/tx" -d "<tx_hex>"
# Check status
curl "https://blockstream.info/liquidtestnet/api/tx/<txid>/status"
elements-cli (If Running Node)
# Testnet operations
elements-cli -chain=liquidtestnet getblockchaininfo
elements-cli -chain=liquidtestnet getnewaddress
elements-cli -chain=liquidtestnet sendtoaddress <address> <amount>
elements-cli -chain=liquidtestnet sendrawtransaction <hex>
elements-cli -chain=liquidtestnet gettransaction <txid>
Troubleshooting
simply Command Not Found
# Check if installed
which simply
# Reinstall if needed
cargo install --git https://github.com/starkware-bitcoin/simply simply --force
Connection Errors
# Test API connectivity
curl "https://blockstream.info/liquidtestnet/api"
# Should return API documentation
Transaction Building Fails
# Verify UTXO exists
curl "https://blockstream.info/liquidtestnet/api/tx/<txid>/hex"
# Check if already spent
curl "https://blockstream.info/liquidtestnet/api/tx/<txid>/outspend/<vout>"
Next Steps
- Web IDE Guide - Browser-based development