Skip to content

shesek/minsc

Folders and files

NameName
Last commit message
Last commit date
Dec 29, 2024
Mar 17, 2025
Sep 25, 2024
Mar 22, 2025
Mar 10, 2025
Mar 17, 2025
Jul 26, 2020
Jul 28, 2020
May 6, 2024
Dec 29, 2024
Dec 29, 2024
Jul 22, 2020
Mar 17, 2025
Sep 13, 2024

Repository files navigation

Build Status crates.io npm MIT license Pull Requests Welcome

Minsc

A mini scripting language for all things Bitcoin

Minsc is a high-level, domain-specific, embeddable language for Bitcoin scripting that simplifies the creation and fulfillment of complex spending conditions using an expressive pseudo-code-like syntax.

It features built-in support for Descriptors, Miniscript, Script, Transactions, PSBT, Taproot, BIP32, CTV and more.

The language is dynamically typed, functional and immutable.

Note

The documentation and playground on the min.sc website are currently outdated.

To explore some of Minsc's new abilities, check out the min.sc/v0.3 playground and the following examples:

Descriptors, Miniscript & PSBT

One Liners

Manual Scripting

Without Descriptors, Miniscript or PSBT

Advanced Scripting

Elements/Liquid Introspection

To learn more about the language internals, you can also check out the Minsc standard library parts implemented in Minsc:

Local installation

Install Rust and:

$ cargo install minsc

# Execute a minsc file
$ minsc examples/htlc.minsc

# Execute from stdin
$ echo 'pk(d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c) && older(1 week)' | minsc -

# Dump AST
$ minsc examples/htlc.minsc --ast

Using the Rust API:

use minsc::eval;

let code = "pk(d0de0aaeaefad02b8bdc8a01a1b8b11c696bd3d66a2c5f10780d95b7df42645c) && older(1 week)";
let res = eval(&code).unwrap(); // a minsc::Value
println!("{}", res);

// Extract the miniscript::Policy
let policy = res.into_policy().unwrap();

Full documentation for the Rust API is available here.

JavaScript WASM package

Install with npm install minsc and:

import m from 'minsc'

// A multisig between Alice and Bob
const alice_pk = 'xpub661MyMwAqRbcFjVEmr9dDxeGKJznf41v5bEd83wMwu7CJ6PFeqJk3cSECPTh6wzsh32xceVsPvBgJ1q3Cqqie2dvH9nMFdL5865WrtRNhiB'
    , bob_pk = 'xpub661MyMwAqRbcFG1mzmcbw7oZss2Fn9y3d27D1KVjyKQdYGqNsZ8nSvLSexZAtkCNwvhFrAkTWAixvN9wjmnLNR22EsQczTiKccAJoLYW8CK'

const multisig = m`wsh(${alice_pk}/0/* && ${bob_pk}/0/*)`

// Generate receive address #0
const address = m`address(${multisig}/0)`
console.log(`Address: ${address}`)

// An output funding address #0
const prevout = '72877bd944be3433d5030ef102922e52f7c40de8b5ca26fa8b7c724d341e936e:1'
    , amount = '0.5 BTC'

// Create PSBT
const psbt = m`psbt[
  "input": [
    "prevout": ${prevout},
    "utxo": ${multisig}/0:${amount},
  ],
  "outputs": [
    bcrt1ql8nqx3q3v7napchr6ewy4tpyq5y08ywat84pen: 0.4 BTC,
    (${multisig}/1): 0.099 BTC, // change back to multisig
  ],
]`

// Export PSBT for external signing
const psbt_base64 = m.base64(psbt)

// Or sign with Minsc:
const alice_sk = 'xprv9s21ZrQH143K3FQmfpccrphXmHAJFbJ4iNK2KfXkPZaDRJ477HzVVp7kM7RV3ihdLh4Wy163wJahwXcdcrpu4R6xSu6CUvKYwftQYCbowYM'
    , bob_sk = 'xprv9s21ZrQH143K2mwJtk5bZyrqKqBmNhFCFoBcCw68QysefUWEL1pXu81xoeva2ZWpCjsJzzmYqph6vw6FjCMjg3q8obNzxYY9bCVgt9bKoHQ'

const signed = m`psbt::sign(${psbt}, ${[ alice_sk, bob_sk ]})`

// Finalize & Extract
const tx = m`psbt::extract(psbt::finalize(${signed}))`
console.log(m.pretty(tx))
console.log(m.bytes(tx).toString('hex'))

// Alternative style, with Minsc functions as JavaScript methods (translated into the same as above)
const address = m.address(m.wsh(m.and(m`${alice_pk}/0/1`, m`${bob_pk}/0/1`)))
const psbt = m.psbt({ inputs: [ ... ], outputs: [ ... ] })
const signed = m.psbt.sign(psbt, [ alice_sk, bob_sk ])
const tx = m.psbt.extract(m.psbt.finalize(signed))

License

MIT