Skip to content

feat(lazer/cardano): add inventory-edge-protocol example#103

Open
JuanCasimiro wants to merge 5 commits intopyth-network:mainfrom
JuanCasimiro:main
Open

feat(lazer/cardano): add inventory-edge-protocol example#103
JuanCasimiro wants to merge 5 commits intopyth-network:mainfrom
JuanCasimiro:main

Conversation

@JuanCasimiro
Copy link
Copy Markdown

@JuanCasimiro JuanCasimiro commented Mar 22, 2026

What this adds

Inventory-Edge Protocol (lazer/cardano/inventory-edge-protocol) — hackathon-style RealFi / RWA MVP on Cardano PreProd: a vault spending validator (Aiken / Plutus v3) that locks a demo shadow NFT, tracks synthetic debt and collateral, supports parametric insurance (strike in datum), and uses Pyth Lazer in the pull model (pyth.get_updates) for liquidation and insurance paths.

Product narrative and judge-facing thesis: PITCH.md. Full operator / auditor detail: README.md.

On-chain

Piece Role
onchain/validators/vault.ak Core vault validator: datum/redeemer, NFT continuity, Pyth-verified Liquidate / ClaimInsurance.
onchain/validators/liquidity_pool.ak Small tADA pool (deposit / withdraw) complementing the demo.
onchain/plutus.json Committed blueprint from aiken build.

Same Pyth Lazer Cardano dependency and PreProd governance policy id as the existing reference lazer/cardano/lazer-rwa (called out explicitly in the README).

Shadow NFTs are native assets minted off-chain (Lucid + CIP-25 metadata with Lazer feed hints), not minted by this Aiken project.

Redeemers (vault)

Redeemer Pyth? Summary
Adjust No Owner updates debt; NFT stays in continuing output.
ApplyHedge No Owner sets insurance fields (strike_raw, payout_lovelace).
Close No Debt zero, vault consumed.
Liquidate Yes Anyone; underwater check vs verified price (price * qty * 100 < debt * 110 in MVP).
ClaimInsurance Yes Owner; hedge set and price < strike.

Off-chain stack

  • Lucid (+ Blockfrost / Maestro): mint + metadata for demo NFTs (mock_assets, judge UI flows where noted).
  • Evolution SDK: Plutus v3 vault spends + Pyth withdrawal witness (README documents why Lucid 0.10 is not used for those paths).
  • Express local API (server/index.ts) + Vite/React judge UI (npm run demo).
  • @pythnetwork/pyth-lazer-sdk + @pythnetwork/pyth-lazer-cardano-js for payloads and Pyth state resolution.

Layout (high level)

lib/ (transactions, feeds, Pyth helpers), scripts/ (open vault, hedge, liquidate, mock assets), web/, server/, onchain/ — see README §4 for the full tree.

How to verify locally

Prerequisites: Node 20+, Aiken 1.1+, PreProd tADA, Lazer ACCESS_TOKEN, Blockfrost Preprod or Maestro key (see .env.example).

cd lazer/cardano/inventory-edge-protocol
npm install
npm run build:onchain
npx tsc   # optional

Suggested scripted flow: npm run mock-assetsnpm run tx:open-vault → optional npm run tx:hedgenpm run tx:liquidate (needs underwater economics + token). Full UI: npm run demohttp://127.0.0.1:5173 (API on 8787).

Honest MVP limits (from README)

  • Some feed ids in lib/feeds.ts may be placeholders; XAU (346) is aligned with the reference app — confirm others via Lazer symbols API before production claims.
  • Insurance: on-chain authorizes ClaimInsurance when price < strike; exact payout routing to outputs is left as a product-layer refinement.
  • PreProd only; signing in the judge stack is server-side via mnemonic — booth/demo pattern, not production custody.

License

On-chain: Apache-2.0 (see onchain/aiken.toml).


Open with Devin

JuanCasimiro and others added 5 commits March 22, 2026 18:00
- Refactor console.log statements for signed integers to a single line format
- Update README to reflect changes in expected output format
- Ensure consistency in logging for price-related outputs
…g, pool/mint UX

- README/PITCH: static review path for judges, CLI vs UI, operator pitfalls
- server/load_env.ts: load .env from package root; harden stdout under concurrently
- mint shadow subprocess, pool chain state, API/UI and onchain lock updates

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 8 additional findings in Devin Review.

Open in Devin Review

Comment on lines +172 to +175
hasBlockfrostOrMaestro: Boolean(
process.env.BLOCKFROST_PROJECT_ID?.trim() ??
process.env.MAESTRO_API_KEY?.trim(),
),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 hasBlockfrostOrMaestro uses ?? instead of ||, falsely reports false when BLOCKFROST_PROJECT_ID is empty

The health endpoint uses nullish coalescing (??) to check for Blockfrost or Maestro keys. Since .env.example has BLOCKFROST_PROJECT_ID= uncommented (line 12), users who copy it to .env and only fill in MAESTRO_API_KEY will have BLOCKFROST_PROJECT_ID set to "". The ?? operator does NOT fall through on empty string (only on null/undefined), so Boolean("") evaluates to false even when MAESTRO_API_KEY is valid. This contradicts the actual provider selection in evolution_client.ts:19-25 which uses truthy checks (if (bf)) and correctly falls through to Maestro. The false hasBlockfrostOrMaestro value disables the UI's mint and pool deposit buttons (web/src/App.tsx:1168, web/src/App.tsx:1700-1703).

Suggested change
hasBlockfrostOrMaestro: Boolean(
process.env.BLOCKFROST_PROJECT_ID?.trim() ??
process.env.MAESTRO_API_KEY?.trim(),
),
hasBlockfrostOrMaestro: Boolean(
process.env.BLOCKFROST_PROJECT_ID?.trim() ||
process.env.MAESTRO_API_KEY?.trim(),
),
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant