
<div align="center">

<img  src="https://raw.githubusercontent.com/OpShin/opshin/main/opshin.png" width="240" />
<h1 style="text-align: center;">opshin</h1></br>


<a href="https://github.com/OpShin/opshin/actions/workflows/tests.yml"><img alt="Tests & QA" src="https://github.com/OpShin/opshin/actions/workflows/tests.yml/badge.svg?branch=main"/></a>
<a href="https://pypi.org/project/opshin/"><img alt="PyPI version" src="https://badge.fury.io/py/opshin.svg"/></a>
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/opshin.svg" />
<a href="https://pypi.org/project/opshin/"><img alt="PyPI - Status" src="https://img.shields.io/pypi/status/opshin.svg" /></a>
<a href="https://coveralls.io/github/OpShin/opshin?branch=main"><img alt="Coverage Status" src="https://coveralls.io/repos/github/OpShin/opshin/badge.svg?branch=main" /></a>
<a href="https://github.com/OpShin/awesome-opshin"><img src="https://img.shields.io/badge/awesome-opshin-blue?logo=data:image/png;base64, "></a>
</div>

> You are building what you want. Why not also build **how** you want?

This is an implementation of smart contracts for Cardano which are written in a strict subset of valid Python.
The general philosophy of this project is to write a compiler that 
ensure the following:

If the program compiles then:

1. it is a valid Python program
2. the output running it with python is the same as running it on-chain.

## Why opshin?
- 100% valid Python. Leverage the existing tool stack for Python, syntax highlighting, linting, debugging, unit-testing, [property-based testing](https://hypothesis.readthedocs.io/), [verification](https://github.com/marcoeilers/nagini)
- Intuitive. Just like Python.
- Flexible. Imperative, functional, the way you want it.
- Efficient & Secure. Static type inference ensures strict typing and optimized code


## Getting Started

Check out the [OpShin Book](https://book.opshin.dev) for an introduction to this tool and details into writing smart contracts.
This document will just outline the basic usage of the tool.

### Installation

Install any of the supported Python versions. Then run 

```bash
python -m pip install opshin
```

### Writing a Smart Contract

Check out the [OpShin Book](https://book.opshin.dev) for an introduction to this tool and details into writing smart contracts.

### Compiling

Write your program in python. You may start with the content of `examples`.
Arguments to scripts are passed in as Plutus Data objects in JSON notation.

You can run any of the following commands
```bash
# Evaluate script in Python - this can be used to make sure there are no obvious errors
# The parameter for smart contracts is the ScriptContext, which defines the entire transaction
opshin eval examples/smart_contracts/assert_sum.py  

# Compile script to 'uplc', the Cardano Smart Contract assembly
opshin compile examples/smart_contracts/assert_sum.py
```

Furthermore, you can add a shebang to the first line of the python file to indicate that it represents an opshin smart contract.
You can choose from the following options:

- a general shebang: `#!opshin`, which represents `opshin eval`
- or a more specific purpose: `#!/usr/bin/env -S opshin eval`

By doing so, you can transform your python file to an executable: `chmod +x your_file.py` and execute it with `./your_file.py`, which will run `opshin eval any ./your_file.py` under the hood.


### Deploying

The deploy process generates all artifacts required for usage with common libraries like [pycardano](https://github.com/Python-Cardano/pycardano), [lucid](https://github.com/spacebudz/lucid) and the [cardano-cli](https://github.com/input-output-hk/cardano-node).

```bash
# Automatically generate all artifacts needed for using this contract
opshin build examples/smart_contracts/assert_sum.py
```

See the [tutorial by `pycardano`](https://pycardano.readthedocs.io/en/latest/guides/plutus.html) for explanations how to build transactions with `opshin` contracts.

## API for Smart Contracts

The python interface offers a simple API to compile, load, apply parameters and evaluate smart contracts.

```python3
from opshin.builder import *

# Build a validator script from a python file that contains a validator function
contract = build("path/to/contract.py")

# You can apply parameters to the contract during compilation
contract = build("path/to/contract.py", arg1, arg2, arg3)

# Store the compilation artifacts in a folder
contract.dump("path/to/store")

# You can also load a compiled contract from a path
contract = load("path/to/store")

# And apply parameters after loading a contract
contract = contract.apply_parameters(arg1, arg2, arg3)

# The artifacts contain the compiled script, the policy ID and the addresses and blueprint
contract_addr = contract.mainnet_addr
contract_blueprint = contract.blueprint
```

## Debugging artefacts

For debugging purposes, you can also run the `eval_uplc` and `compile_pluto` commands to see the intermediate representations of your smart contract.

```bash
# Compile script to 'uplc', and evaluate the script in UPLC (for debugging purposes)
opshin eval_uplc examples/smart_contracts/assert_sum.py  

# Compile script to 'pluto', an intermediate language (for debugging purposes)
opshin compile_pluto examples/smart_contracts/assert_sum.py
```


## Contributing

### Developing and Technical Documentation

Generally, all contributions on the code side are very welcome.
To get an overview over the architecture and idea behind OpShin, check out [the Technical Documentation](./ARCHITECTURE.md).
A bug bounty has been set up and funded by Project Catalyst, which awards [Github issue](https://github.com/OpShin/opshin/labels/bug%20bounty) resolution with ADA rewards.
This is a great opportunity to get involved and earn some ADA.
Check out the [detailed introduction to the bounty program](./BUG_BOUNTY.md) for more information.

### Binary Size Tracking

OpShin includes tooling to track binary size changes across different optimization levels to help catch regressions:

```bash
# Check binary sizes against latest release
python scripts/check_binary_sizes.py
```

The binary size tracker automatically runs on pull requests and reports significant changes. See [Binary Size Tracker Documentation](docs/binary_size_tracker.md) for details.


### Sponsoring

You can sponsor the development of opshin through GitHub or [Patreon](https://patreon.com/OpShin) or just by sending ADA. Drop me a message on social media and let me know what it is for.

- **Patreon** Support OpShin at [Patreon](https://patreon.com/OpShin) to enjoy member benefits!
- **GitHub** Sponsor the developers of this project through the button "Sponsor" next to them
- **ADA** Donation in ADA can be submitted to `$opshin` or `addr1qyz3vgd5xxevjy2rvqevz9n7n7dney8n6hqggp23479fm6vwpj9clsvsf85cd4xc59zjztr5zwpummwckmzr2myjwjns74lhmr`.

### Supporters

<a href="https://github.com/inversion-dev"><img src="https://avatars.githubusercontent.com/u/127298233?s=200&v=4" width="50"></a>
<a href="https://github.com/MuesliSwapTeam/"><img  src="https://avatars.githubusercontent.com/u/91151317?v=4" width="50" /></a>
<a href="https://github.com/AadaFinance/"><img  src="https://avatars.githubusercontent.com/u/89693711?v=4" width="50" /></a>
<a href="https://github.com/kreate-community/"><img  src="https://avatars.githubusercontent.com/u/118675270?v=4" width="50" /></a>
