0.2.0 • Published 2 years ago

lucid-cardano-partialtx v0.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Plutus Partial Tx

A library to export partial transactions (unbalanced, unsigned) and get them signed and submitted by a frontend PAB. This enables you to re-use your regular Haskell Contracts while still having a deployment solution for production - effortlessly.

Highlights

  • Write all your contracts in the familiar Contract monad.
  • Leverage excellent Haskell-side testing solutions for your Contracts, using Plutip, Contract models etc.
  • Run your contracts on the testnet (and mainnet!) utilizing a lightweight frontend PAB (i.e Lucid) - without ever having to rewrite your contracts or any extra logic. Simply re-use your Haskell contracts, call .sign and .submit on the frontend.
  • Extremely lightweight, easy to test in local development environment. If using bot-plutus-interface (BPI), all you need is cardano-node and plutus-chain-index.

Usage

Backend environment setup

  1. Add the proper versions of bot-plutus-interface and plutus-partial-tx as dependencies to your project.
  2. Have the proper versions (usually latest) of cardano-node, cardano-cli, and a corresponding version (same one used by bot-plutus-interface) of plutus-chain-index in $PATH.
  3. Have cardano-node and chain-index running in the background and properly synced. You may simply copy over the provided testnet directory and use the scripts there to set up for testnet. Remember to create the db directory inside testnet/chain-index first!

    Usually, if using nix, plutus-chain-index is already included by BPI. All you have to do is make it available in the nix shell by adding project.hsPkgs.plutus-chain-index.components.exes.plutus-chain-index to nativeBuildInputs.

NOTE: The provided example is using the preview testnet.

NOTE: You need to use a vasil compliant version of BPI. Mainline BPI does not support vasil yet. Use the gergely/vasil branch instead.

Frontend environment setup

How you set up the frontend is entirely upto you, as long as it can query the Haskell server to obtain a PartialTx - and use it with lucid-cardano and lucid-cardano-partialtx, it's enough.

See Berry-Pool/lucid for adding Lucid to your dependency.

NOTE: You need to use a vasil compliant version of Lucid. Mainline Lucid does not support vasil yet. Use the vasil branch instead.

For lucid-cardano-partialtx (provided by this repo), there are three ways to import it:

Node.js

Install the npm package:

npm install lucid-cardano-partialtx

Import in your file:

import { mkPartialTxInterpreter } from "lucid-cardano-partialtx";

Aside: You can use webpack or similar to bundle your Node project to run on the browser. See full example that does this

Deno

Simply import from deno.land:

import { mkPartialTxInterpreter } from "https://deno.land/x/lucid_partialtx@0.1.3/mod.ts";

Aside: You can use ESBuild or similar to bundle your Deno project to run on the browser. However, you should to replace the deno.land imports with the browser package url if running in a browser environment. See lucid-partialtx/build.ts that does something similar (but only after generating a node package).

Browser JS

<script type="module">

import { mkPartialTxInterpreter } from "https://unpkg.com/lucid-cardano-partialtx@0.1.3/web/mod.js";

</script>

Aside: This is pure JS directly running in the browser: probably not too practical for large projects.

Haskell server

Once you have the environment set up, your haskell server merely has to use BPI (bot-plutus-interface) to run your contracts returning PartialTxs. You can hook up BPI with the testnet quite easily: simply copy over the BPI.Testnet.Setup module from the example.

A simple servant server, showcasing a simple Contract usage, can be found in example/Main.

Frontend Lucid

All you have to do is create a PartialTxInterpreter by passing your Lucid instance to mkPartialTxInterpreter, make an API call to receieve the PartialTx from your server, and pass it through the interpreter. The resulting Lucid Tx can be modified further or directly signed, and submitted.

See example/frontend/src/index.ts.

Full example and how to run it

There is a full example with servant, BPI, and Lucid that can run a dummy minting contract on the testnet. Check the haskell code in the example directory. The gist is that you can copy over BPI.Testnet.Setup and use the exposed interface to create PartialTxs in the context of the testnet.

The example frontend is in example/frontend.

To run the project and run stuff on the testnet, head inside the nix shell by doing nix develop, and follow these steps:

1. Fill in blockfrost config

You need to fill a config.json and put it in example/frontend/config.json, this config should contain your blockfrost API access key:

{
  "blockfrostUrl": "TESTNET_BLOCKFROST_URL",
  "blockfrostProjId": "TESTNET_BLOCKFROST_PROJID"
}

Aside: Of course, you can also deploy all this in production by switching out to connect to the mainnet in the BPI setup and blockfrost setup.

2. Start cardano-node and plutus-chain-index in background

You'll also need cardano-node and chain-index running in the background, properly connected to testnet.

Unless the directory testnet/chain-index/db already exists, you should create an empty directory: mkdir testnet/chain-index/db.

All you have to do run make services.

This will take some time to sync. You can see the node logs in testnet/node.log and chain index logs in testnet/cix.log. You can query the node sync progress by running make query-tip.

Note: Remember to stop these background services when you're done! Use make stop-services to do so.

3. Build the frontend project

Firstly, run make build-lucid-lib at the root project directory.

Now, head inside the example/frontend directory and run the following commands:

  • npm i - to install all the npm dependencies
  • npx webpack - to build the project

Alternatively, if you've already done npm i and have the node_modules from it - you can run make build-frontend from the root project path.

4. Start the server

Once the node has synced and all the previous steps have been completed, run make serve. Head to localhost:8080 to see a beautiful frontend with a singular dummy minting button!

Note: You'll need a wallet supporting Vasil for signing and submission to work properly. In particular, mainline Nami does not support vasil yet. You need to use the vasil branch of nami.

API

Here's the core idea:

Keep your Haskell contracts as they are, just make them return UnbalancedTx using Ledger.Constraints.mkTx. Alternatively, make them return the ScriptLookups and the TxConstraints.

Use either of the two functions provided within this repo to create a PartialTx:

import Plutus.Contract.PartialTx

mkPartialTx ::
  ( FromData (DatumType a)
  , ToData (DatumType a)
  , ToData (RedeemerType a)
  ) =>
  ScriptLookups a ->
  TxConstraints (RedeemerType a) (DatumType a) ->
  Either MkTxError PartialTx

unbalancedToPartial :: UnbalancedTx -> PartialTx

Aside: For your Haskell side tests (Plutip or EmulatorTrace), you'd still want to submit the UnbalancedTx - which you can still do using submitUnbalancedTx. So calling mkTx followed by submitUnbalancedTx is effectively the same as just calling submitTx (and similar).

In the frontend, bind your Lucid instance to mkPartialTxInterpreter, and use the resulting PartialTxInterpreter to interpret a PartialTx:

type PartialTxInterpreter = (x: PartialTx) => Tx;

mkPartialTxInterpreter(lucid: Lucid): PartialTxInterpreter;

Once you obtain a Lucid Tx, it's as simple as signing and submitting it, which looks like:

const signedTx = await tx.sign().complete();
return signedTx.submit();
0.2.0

2 years ago

0.1.3

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago