{"id":18204637,"url":"https://github.com/shesek/minsc","last_synced_at":"2025-04-02T13:32:02.016Z","repository":{"id":38330288,"uuid":"281962010","full_name":"shesek/minsc","owner":"shesek","description":"A mini scripting language for all things Bitcoin","archived":false,"fork":false,"pushed_at":"2024-10-24T12:47:36.000Z","size":20933,"stargazers_count":192,"open_issues_count":6,"forks_count":19,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-25T00:02:48.952Z","etag":null,"topics":["bitcoin","bitcoin-script","miniscript"],"latest_commit_sha":null,"homepage":"https://min.sc","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shesek.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-23T13:40:41.000Z","updated_at":"2024-10-24T01:45:24.000Z","dependencies_parsed_at":"2024-10-26T02:57:11.943Z","dependency_job_id":"6094e7bf-43aa-424d-ac50-51af64737b6e","html_url":"https://github.com/shesek/minsc","commit_stats":{"total_commits":269,"total_committers":1,"mean_commits":269.0,"dds":0.0,"last_synced_commit":"a28412f2da02c9952881c36f01b1b5027c7520bd"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shesek%2Fminsc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shesek%2Fminsc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shesek%2Fminsc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shesek%2Fminsc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shesek","download_url":"https://codeload.github.com/shesek/minsc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246823859,"owners_count":20839786,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","bitcoin-script","miniscript"],"created_at":"2024-11-03T11:05:01.221Z","updated_at":"2025-04-02T13:32:01.439Z","avatar_url":"https://github.com/shesek.png","language":"Rust","readme":"[![Build Status](https://travis-ci.org/shesek/minsc.svg?branch=master)](https://travis-ci.org/shesek/minsc)\n[![crates.io](https://img.shields.io/crates/v/minsc.svg)](https://crates.io/crates/minsc)\n[![npm](https://img.shields.io/npm/v/minsc.svg?color=blue)](https://www.npmjs.com/package/minsc)\n[![MIT license](https://img.shields.io/github/license/shesek/minsc.svg?color=yellow)](https://github.com/shesek/minsc/blob/master/LICENSE)\n![Pull Requests Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)\n\n# Minsc\n\n### A Miniscript-based scripting language for Bitcoin contracts\n\nMinsc is a high-level scripting language for expressing Bitcoin Script spending conditions.\nIt is based on the [Miniscript](http://bitcoin.sipa.be/miniscript/) Policy language,\nwith additional features and syntactic sugar sprinkled on top, including variables, functions, infix notation, human-readable times and more.\n\nDocumentation \u0026 live playground are available on the website: https://min.sc\n\nSupport development: [⛓️ on-chain or ⚡ lightning via BTCPay](https://btcpay.shesek.info/)\n\n## Examples\n\n- A user and a 2FA service need to sign off, but after 90 days the user alone is enough\n  ```hack\n  pk(user_pk) \u0026\u0026 (pk(service_pk) || older(90 days))\n  ```\n  [:arrow_forward: Try it live](https://min.sc/#c=%2F%2F%20A%20user%20and%20a%202FA%20service%20need%20to%20sign%20off%2C%20but%20after%2090%20days%20the%20user%20alone%20is%20enough%0A%0Apk%28user_pk%29%20%26%26%20%28pk%28service_pk%29%20%7C%7C%20older%2890%20days%29%29)\n\n- Traditional preimage-based HTLC\n  ```hack\n  $redeem = pk(A) \u0026\u0026 sha256(H);\n  $refund = pk(B) \u0026\u0026 older(10);\n\n  $redeem || $refund\n  ```\n  [:arrow_forward: Try it live](https://min.sc/#c=%2F%2F%20Traditional%20preimage-based%20HTLC%0A%0A%24redeem%20%3D%20pk%28A%29%20%26%26%20sha256%28H%29%3B%0A%24refund%20%3D%20pk%28B%29%20%26%26%20older%2810%29%3B%0A%0A%24redeem%20%7C%7C%20%24refund)\n\n- Liquid-like federated pegin, with emergency recovery keys that become active after a timeout\n  ```hack\n  $federation = 4 of [ pk(A), pk(B), pk(C), pk(D), pk(E) ];\n  $recovery = 2 of [ pk(F), pk(G), pk(I) ];\n  $timeout = older(3 months);\n\n  likely@$federation || ($timeout \u0026\u0026 $recovery)\n  ```\n  [:arrow_forward: Try it live](https://min.sc/#c=%2F%2F%20Liquid-like%20federated%20pegin%2C%20with%20emergency%20recovery%20keys%0A%0A%24federation%20%3D%204%20of%20%5B%20pk%28A%29%2C%20pk%28B%29%2C%20pk%28C%29%2C%20pk%28D%29%2C%20pk%28E%29%20%5D%3B%20%0A%24recovery%20%3D%202%20of%20%5B%20pk%28F%29%2C%20pk%28G%29%2C%20pk%28I%29%20%5D%3B%0A%24timeout%20%3D%20older%283%20months%29%3B%0A%0Alikely%40%24federation%20%7C%7C%20%28%24timeout%20%26%26%20%24recovery%29)\n\n- The BOLT #3 received HTLC policy\n  ```hack\n  fn bolt3_htlc_received($revoke_pk, $local_pk, $remote_pk, $secret, $delay) {\n    $success = pk($local_pk) \u0026\u0026 hash160($secret);\n    $timeout = older($delay);\n\n    pk($revoke_pk) || (pk($remote_pk) \u0026\u0026 ($success || $timeout))\n  }\n\n  bolt3_htlc_received(A, B, C, H1, 2 hours)\n  ```\n  [:arrow_forward: Try it live](https://min.sc/#c=%2F%2F%20The%20BOLT%20%233%20received%20HTLC%20policy%0A%0Afn%20bolt3_htlc_received%28%24revoke_pk%2C%20%24local_pk%2C%20%24remote_pk%2C%20%24secret%2C%20%24delay%29%20%7B%0A%20%20%24success%20%3D%20pk%28%24local_pk%29%20%26%26%20hash160%28%24secret%29%3B%0A%20%20%24timeout%20%3D%20older%28%24delay%29%3B%0A%0A%20%20pk%28%24revoke_pk%29%20%7C%7C%20%28pk%28%24remote_pk%29%20%26%26%20%28%24success%20%7C%7C%20%24timeout%29%29%0A%7D%0A%0Abolt3_htlc_received%28A%2C%20B%2C%20C%2C%20H1%2C%202%20hours%29)\n\n- Advanced 2FA where the user has a 2-of-2 setup and the service provider is a 3-of-4 federation\n  ```hack\n  fn two_factor($user, $provider, $delay) =\n    $user \u0026\u0026 (likely@$provider || older($delay));\n\n  $user = pk(desktop_pk) \u0026\u0026 pk(mobile_pk);\n  $providers = [ pk(A), pk(B), pk(C), pk(D) ];\n\n  two_factor($user, 3 of $providers, 4 months)\n  ```\n  [:arrow_forward: Try it live](https://min.sc/#c=%2F%2F%20Two%20factor%20authentication%20with%20a%20timeout%20recovery%20clause%0Afn%20two_factor%28%24user%2C%20%24provider%2C%20%24delay%29%20%3D%20%0A%20%20%24user%20%26%26%20%28likely%40%24provider%20%7C%7C%20older%28%24delay%29%29%3B%0A%0A%2F%2F%202FA%20where%20the%20user%20has%20a%202-of-2%20setup%20and%20the%20provider%20is%20a%203-of-4%20federation%0A%0A%24user%20%3D%20pk%28desktop_pk%29%20%26%26%20pk%28mobile_pk%29%3B%0A%24providers%20%3D%20%5B%20pk%28A%29%2C%20pk%28B%29%2C%20pk%28C%29%2C%20pk%28D%29%20%5D%3B%0A%0Atwo_factor%28%24user%2C%203%20of%20%24providers%2C%204%20months%29)\n\nMore examples are available on https://min.sc.\n\n## Local installation\n\n[Install Rust](https://rustup.rs/) and:\n\n```bash\n$ cargo install minsc\n\n# Compile a minsc file\n$ minsc examples/htlc.minsc\n\n# Compile from stdin\n$ echo 'pk(A) \u0026\u0026 older(1 week)' | minsc -\n\n# Dump AST\n$ minsc examples/htlc.minsc --ast\n```\n\nUsing the Rust API:\n```rust\nuse minsc::{parse, run, eval};\n\nlet code = \"pk(A) \u0026\u0026 older(1 week)\";\nlet ast = parse(\u0026code).unwrap();\nlet result = eval(ast).unwrap();\n// or parse+eval in one go with `run(\u0026code)`\n\nlet policy = result.into_policy().unwrap();\nprintln!(\"{}\", policy);\n\n// also available: into_miniscript() and into_desc()\n```\n\nFull documentation for the Rust API is [available here](https://docs.rs/minsc/).\n\n## JavaScript WASM package\n\nInstall with `npm install minsc` and:\n\n```js\nimport { run } from 'minsc'\n\nconst policy = run('pk(A) \u0026\u0026 older(1 week)')\nconst miniscript = run('miniscript(pk(A) \u0026\u0026 older(1 week))')\nconst descriptor = run('wsh(miniscript(pk(A) \u0026\u0026 older(1 week)))')\nconst address = run('address(wsh(miniscript(pk(A) \u0026\u0026 older(1 week))))')\nconst address2 = run('address(pk(A) \u0026\u0026 older(1 week))')\n\nconsole.log({ policy, miniscript, descriptor, address, address2 })\n```\n\n\n## License\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshesek%2Fminsc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshesek%2Fminsc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshesek%2Fminsc/lists"}