Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
439ff76
add initial readme
lolaaimar Mar 22, 2026
5fa07b2
aiken boilerplate
sofia-bobbiesi Mar 22, 2026
c0a7b11
initialize off-chain project with Bun setup
sofia-bobbiesi Mar 22, 2026
dfcf3bd
feat: update dependencies in package.json and bun.lock for off-chain …
sofia-bobbiesi Mar 22, 2026
0106885
feat: integrate dotenv for environment variable management and update…
sofia-bobbiesi Mar 22, 2026
80c542c
implement on-chain validator logic
sofia-bobbiesi Mar 22, 2026
720332f
update oracleSettled
sofia-bobbiesi Mar 22, 2026
9fe9a8c
fix cbor encoding
a-osiecki Mar 22, 2026
32638cd
feat: update README
sofia-bobbiesi Mar 22, 2026
08b7049
fix: simplify aiken build command in README
sofia-bobbiesi Mar 22, 2026
466109a
feat: enhance project description in README
sofia-bobbiesi Mar 22, 2026
cf9619b
added checks and modified types
lolaaimar Mar 22, 2026
3ac5d10
add double price fetch and handler onchain
a-osiecki Mar 22, 2026
eca4bcc
added checks and modified types
lolaaimar Mar 22, 2026
531112e
final tweaks on validator
a-osiecki Mar 22, 2026
650f24e
feat: initialize web UI with components, styles, and configuration files
sofia-bobbiesi Mar 22, 2026
6f378d3
Merge branch 'main' into ui
sofia-bobbiesi Mar 22, 2026
bb19aa3
refactor: update quote_price_multiplier to accept price and exponent …
sofia-bobbiesi Mar 22, 2026
a17f344
Merge pull request #1 from lolaaimar/ui
sofia-bobbiesi Mar 22, 2026
f9d9ad2
add offchain ops
a-osiecki Mar 22, 2026
ca5b345
improve CLI formatting
a-osiecki Mar 22, 2026
cad22d1
update readme
lolaaimar Mar 22, 2026
3dd12cd
rename project
lolaaimar Mar 22, 2026
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
123 changes: 123 additions & 0 deletions lazer/cardano/OSI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# OSI: Oracle-Settled Invoice

Oracle-Settled Invoice is a Cardano escrow that locks one asset and settles a liability indexed to another using Pyth prices.

This project is a practical blueprint for building oracle-driven settlement flows on Cardano with Pyth. It combines Aiken on-chain validators with a typeScript off-chain client, so you can go from contract logic to real transaction execution with minimal setup.

## Sections

- [Introduction](../OSI/README.md#introduction)
- [Project structure](../OSI/README.md#project-structure)
- [Setup](../OSI/README.md#setup)
- [Running instructions](../OSI/README.md#running-instructions)
- [CLI](../OSI/README.md#1-run-the-cli)
- [Web page](../OSI/README.md#2-run-the-webpage)

## Introduction

This project addresses a common payments challenge: obligations are often defined in one currency, while treasury and disbursement happen in another. In OSI (Oracle-Settled Invoice), the payable amount is denominated in a quote asset (USDT in this PoC), but settlement is executed in ADA using real-time oracle conversion.

For this proof-of-concept, we use the USDT/USD and ADA/USD feeds. At settlement time, the transaction consumes signed Pyth price updates and computes the ADA amount required to satisfy each USDT-denominated payout. This enables deterministic and transparent cross-currency settlement directly on-chain.

The `off-chain` component in OSI/off-chain/e2e.ts uses Pyth’s SDK to fetch signed price updates and Evolution SDK to construct the transaction. The `on-chain` validator in OSI/on-chain/validators/osi.ak, using Pyth’s Aiken library, verifies those updates at execution time (including authenticity and timing) before allowing payout. This ensures the ADA delivered matches the expected USDT value according to trusted oracle data, reducing exchange-rate dispute risk between payer and payee.

The same pattern can support many real use cases, such as:

- payroll where compensation is defined in USD but paid in ADA;
- vendor invoices denominated in fiat and settled in crypto;
- scheduled future payments indexed to a CNT pegged to an RWA, while settlement occurs in another on-chain asset.

## Project structure

```bash
lazer/cardano/OSI/
├── on-chain/
├── off-chain/
├── web-ui/
└── README.md
```

- `on-chain`: smart contract implementation
- `off-chain`: transaction building and connection with Pyth
- `web-ui`: dApp connection with browser wallet (Eternl recommended)
- `README.md`: project explanation and running instructions

## Setup

### 1. Build contracts

```bash
cd on-chain
aiken build
```

### 2. Set environment variables

Create a `.env` file in the `off-chain` directory with the following variables:

- `LAZER_TOKEN` - The token that provides access to the Pyth API.
- `NETWORK` - Cardano network (recommended `preprod`)
- `PROVIDER_TYPE` - Cardano provider (recommended Blockfrost)
- `BLOCKFROST_BASE_URL` - The base URL for the Blockfrost API. For preprod, this is `https://cardano-preprod.blockfrost.io/api/v0`.
- `BLOCKFROST_PROJECT_ID` - Your Blockfrost project ID for the preprod network.
- `WALLET_MNEMONIC` - The mnemonic phrase for the wallet that will be used to interact with the contracts. This wallet should have some ADA on the preprod network.
- `PYTH_POLICY_ID` - The policy ID of the Pyth on the Cardano preprod network.

### 3. Install off-chain deps

```bash
cd off-chain
bun install
```

## Running instructions

There are two ways to interact with the dApp:

### 1. Run the CLI

The CLI allows the creation and payout of the escrows.

#### 1.1 Start the escrow

Creates an UTxO allocating minAda and including the list of payees in the datum

```bash
bun run create-validator-utxo
```

![Create escrow](../OSI/img/create_escrow.png)

#### 1.2 Fund the escrow

Adds the funds to pay out later

```bash
bun run add-fund-validator-utxo <AMOUNT>
```

![Fund escrow](../OSI/img/add_funds.png)

#### 1.3 Pay out

Pays out the expected amount of ADA to the payees specified in the datum

```bash
bun run spend-validator-utxo <HASH>
```

![Pay out](../OSI/img/pay_out.png)

### 2. [Experimental] Run the webpage

Lift a webpage that will be available on `localhost:3000`.

```bash
cd web-ui
bun install
bun run dev
```

![Web](../OSI/img/web.png)

The web implementation can be accessed on [this branch](https://github.com/lolaaimar/pyth-examples/tree/integration).
Binary file added lazer/cardano/OSI/img/add_funds.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lazer/cardano/OSI/img/create_escrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lazer/cardano/OSI/img/pay_out.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lazer/cardano/OSI/img/web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions lazer/cardano/OSI/off-chain/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
50 changes: 50 additions & 0 deletions lazer/cardano/OSI/off-chain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# off-chain

To install dependencies:

```bash
bun install
```

Minimal e2e commands:

```bash
bun run create-validator-utxo
bun run add-fund-validator-utxo <lovelace> [outRef]
bun run spend-validator-utxo <createTxHash>
bun run evaluate-ogmios <txCborHex>
bun run fetch-ada-usdt-update
```

You can also pass an explicit out-ref as `<createTxHash>#<index>`.

### Fund Operation

Add funds to an existing OSI UTxO while preserving the deadline and payees:

```bash
# Add 1000000 lovelace to the first validator UTxO
bun run add-fund-validator-utxo 1000000

# Add 2000000 lovelace to a specific UTxO
bun run add-fund-validator-utxo 2000000 <txHash>#<index>
```

The Fund operation:
- Takes an existing OSI UTxO from the script address
- Adds additional ADA (lovelace) from your wallet
- Returns the combined funds to the same script address with the original datum unchanged
- Preserves the deadline and payees for later Payout operations

Required environment variables:

- `NETWORK` = `preprod`, `preview`, or `mainnet`
- `WALLET_MNEMONIC`
- `PYTH_POLICY_ID`
- `LAZER_TOKEN`
- `VALIDATOR_LOVELACE` (defaults to `5000000`)
- provider config:
- `PROVIDER_TYPE=blockfrost` with `BLOCKFROST_BASE_URL` and `BLOCKFROST_PROJECT_ID`
- or `PROVIDER_TYPE=kupmios` with `KUPO_URL` and `OGMIOS_URL`
- or `PROVIDER_TYPE=maestro` with `MAESTRO_BASE_URL` and `MAESTRO_API_KEY`
- or `PROVIDER_TYPE=koios` with `KOIOS_BASE_URL` and optional `KOIOS_TOKEN`
Loading