Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,47 @@
# purescript-bridge
# purescript-bridge (Plutus remix)

Comment on lines +1 to 2

Choose a reason for hiding this comment

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

Excellent read! Thanks for doing this!

This repository contains a fork of `purescript-bridge` which has been modified for compatibility with with Plutus. The top-level `PlutusBridge` module should provide all of the necessary functionality for Plutus-related uses.

[![Build Status](https://travis-ci.org/eskimor/purescript-bridge.svg?branch=master)](https://travis-ci.org/eskimor/purescript-bridge)
To facilitate compatibility with Plutus, the modules in this project provide:

## The `HasConstrIndices` type class (located in `PlutusTx.ConstrIndices`)

``` haskell
class HasConstrIndices (a :: Type) where
getConstrIndices :: [(Int, String)]
```

This class is used to record constructor index information. Due to the existence of the `makeIsDataIndexed` function in Plutus, the `PlutusCore.Data.Data` instance generated by `ToData` for a given Haskell type may contain constructors (i.e. `Constr Integer [Data]`) where the index (the `Integer`) may not match the natural order of the constructors. The natural order of the constructors, therefore, cannot be relied upon. `HasConstrIndices` allows us to encode the correct order and use that to generate PureScript `ToData`/`FromData` instances which are compatible with the Haskell instances.

Users should not ordinarily have to write `HasConstrIndices` instances by hand, and ought to employ the template haskell hooks to generate these instances if possible.


## Template Haskell machinery

The `PlutusTx.Aux` module contains several template Haskell functions which can generate `HasConstrIndices` instances. Most users will simply use `PlutusTx.Aux.unstableMakeIsData` or `PlutusTx.Aux.makeIsDataIndexed`. Each of these functions generates the same Haskell `ToData`/`FromData` instances as the Plutus `unstableMakeIsData`/`makeIsDataIndexed` functions, but also generates a Haskell `HasConstrIndices` instance which can be used to generate compatible PureScript `ToData`/`FromData` instances.

## `mkSumTypeIndexed` & friends

Once a Haskell `HasConstrIndices` instance has been provided for a type (again, typically through the template haskell functions), you can use `mkSumTypeIndexed` to produce a `SumType Haskell` which will generate a corresponding _PureScript_ `HasConstrIndices` class when writing the bridge. (The PureScript `HasConstrIndices` class is defined in the `ConstrIndices` module of the [cardano-transaction-lib](https://github.com/Plutonomicon/cardano-transaction-lib/) library.)

A type with a PureScript `HasConstrIndices` instance can (provided it is otherwise suitable, i.e., does not contain functions/etc) make use of `genericToData` and `genericFromData` from the `cardano-transaction-lib` library. See the `ToData` and `FromData` modules in that library for more details.

In cases where you are _certain_ that the index information for a type will never change (perhaps because it is a simple newtpe wrapper), or where you are _certain_ that the constructor indices will always conform with the "natural" order, you may use `extremelyUnsafeMkSumType` instead. This is provided as a convenience however, and its use is discouraged.

## A Plutus.V1.Ledger Type Package

Because almost anyone using this library will probably want PureScript versions of those `Plutus.V1.Ledger.X` types that have `Lift`/`ToData`/`FromData` instances, functions for generating those types are provided in this project's `PlutusTx.LedgerTypes` module.

If you want to generate _only_ the Ledger types (and not generate PureScript versions of your own Haskell types), use `writeLedgerTypes :: FilePath -> IO ()`. The Sample directory in this project's root folder provides an example of the output of that function.

If you wish to generate both PureScript versions of the Ledger types _and_ some of your own Haskell types, use the function `writerLedgerTypesAnd :: FilePath -> [SumType 'Haskell] -> IO ()`.

## Examples

The `PlutusTx.LedgerTypes` and `PlutusTx.ConstrIndices` modules should provide sufficient examples of how all of this works together. If you remain confused, please open an issue and I will attempt to clear up the confusion.


Comment on lines +42 to +43

Choose a reason for hiding this comment

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

We'll need a chapter on Nix utilities and how to use it in projects.

# Old Readme

Translate your Haskell types to PureScript types. It should in theory work for almost all Haskell types, including type constructors!
You just have to instantiate it with dummy parameters from e.g. "Language.PureScript.Bridge.TypeParameters".
Expand Down
29 changes: 29 additions & 0 deletions Sample/Plutus/V1/Ledger/Ada.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-- File auto generated by purescript-bridge! --
module Plutus.V1.Ledger.Ada where

import Prelude

import ConstrIndices (class HasConstrIndices, constrIndices, fromConstr2Index)
import Data.BigInt (BigInt)
import Data.Generic.Rep (class Generic)
import Data.Lens (Iso', Lens', Prism', iso, prism')
import Data.Lens.Iso.Newtype (_Newtype)
import Data.Lens.Record (prop)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.Tuple (Tuple(..))
import Type.Proxy (Proxy(Proxy))

newtype Ada = Lovelace { getLovelace :: BigInt }

derive instance Generic Ada _

derive instance Newtype Ada _

instance HasConstrIndices Ada where
constrIndices _ = fromConstr2Index [Tuple "Lovelace" 0]

--------------------------------------------------------------------------------

_Lovelace :: Iso' Ada {getLovelace :: BigInt}
_Lovelace = _Newtype
32 changes: 32 additions & 0 deletions Sample/Plutus/V1/Ledger/Address.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-- File auto generated by purescript-bridge! --
module Plutus.V1.Ledger.Address where

import Prelude

import ConstrIndices (class HasConstrIndices, constrIndices, fromConstr2Index)
import Data.Generic.Rep (class Generic)
import Data.Lens (Iso', Lens', Prism', iso, prism')
import Data.Lens.Iso.Newtype (_Newtype)
import Data.Lens.Record (prop)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.Tuple (Tuple(..))
import Plutus.V1.Ledger.Credential (Credential, StakingCredential)
import Type.Proxy (Proxy(Proxy))

newtype Address = Address
{ addressCredential :: Credential
, addressStakingCredential :: Maybe StakingCredential
}

derive instance Generic Address _

derive instance Newtype Address _

instance HasConstrIndices Address where
constrIndices _ = fromConstr2Index [Tuple "Address" 0]

--------------------------------------------------------------------------------

_Address :: Iso' Address {addressCredential :: Credential, addressStakingCredential :: Maybe StakingCredential}
_Address = _Newtype
29 changes: 29 additions & 0 deletions Sample/Plutus/V1/Ledger/Bytes.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-- File auto generated by purescript-bridge! --
module Plutus.V1.Ledger.Bytes where

import Prelude

import ConstrIndices (class HasConstrIndices, constrIndices, fromConstr2Index)
import Data.Generic.Rep (class Generic)
import Data.Lens (Iso', Lens', Prism', iso, prism')
import Data.Lens.Iso.Newtype (_Newtype)
import Data.Lens.Record (prop)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.Tuple (Tuple(..))
import Type.Proxy (Proxy(Proxy))
import Types.ByteArray (ByteArray)

newtype LedgerBytes = LedgerBytes { getLedgerBytes :: ByteArray }

derive instance Generic LedgerBytes _

derive instance Newtype LedgerBytes _

instance HasConstrIndices LedgerBytes where
constrIndices _ = fromConstr2Index [Tuple "LedgerBytes" 0]

--------------------------------------------------------------------------------

_LedgerBytes :: Iso' LedgerBytes {getLedgerBytes :: ByteArray}
_LedgerBytes = _Newtype
122 changes: 122 additions & 0 deletions Sample/Plutus/V1/Ledger/Contexts.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
-- File auto generated by purescript-bridge! --
module Plutus.V1.Ledger.Contexts where

import Prelude

import ConstrIndices (class HasConstrIndices, constrIndices, fromConstr2Index)
import Data.BigInt (BigInt)
import Data.Generic.Rep (class Generic)
import Data.Lens (Iso', Lens', Prism', iso, prism')
import Data.Lens.Iso.Newtype (_Newtype)
import Data.Lens.Record (prop)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.Tuple (Tuple(..))
import Plutus.V1.Ledger.Credential (StakingCredential)
import Plutus.V1.Ledger.Crypto (PubKeyHash)
import Plutus.V1.Ledger.DCert (DCert)
import Plutus.V1.Ledger.Interval (Interval)
import Plutus.V1.Ledger.Scripts (Datum, DatumHash)
import Plutus.V1.Ledger.Time (POSIXTime)
import Plutus.V1.Ledger.Tx (TxOut, TxOutRef)
import Plutus.V1.Ledger.TxId (TxId)
import Plutus.V1.Ledger.Value (CurrencySymbol, Value)
import Type.Proxy (Proxy(Proxy))

newtype TxInfo = TxInfo
{ txInfoInputs :: Array TxInInfo
, txInfoOutputs :: Array TxOut
, txInfoFee :: Value
, txInfoMint :: Value
, txInfoDCert :: Array DCert
, txInfoWdrl :: Array (Tuple StakingCredential BigInt)
, txInfoValidRange :: Interval POSIXTime
, txInfoSignatories :: Array PubKeyHash
, txInfoData :: Array (Tuple DatumHash Datum)
, txInfoId :: TxId
}

derive instance Generic TxInfo _

derive instance Newtype TxInfo _

instance HasConstrIndices TxInfo where
constrIndices _ = fromConstr2Index [Tuple "TxInfo" 0]

--------------------------------------------------------------------------------

_TxInfo :: Iso' TxInfo {txInfoInputs :: Array TxInInfo, txInfoOutputs :: Array TxOut, txInfoFee :: Value, txInfoMint :: Value, txInfoDCert :: Array DCert, txInfoWdrl :: Array (Tuple StakingCredential BigInt), txInfoValidRange :: Interval POSIXTime, txInfoSignatories :: Array PubKeyHash, txInfoData :: Array (Tuple DatumHash Datum), txInfoId :: TxId}
_TxInfo = _Newtype

--------------------------------------------------------------------------------

newtype TxInInfo = TxInInfo
{ txInInfoOutRef :: TxOutRef
, txInInfoResolved :: TxOut
}

derive instance Generic TxInInfo _

derive instance Newtype TxInInfo _

instance HasConstrIndices TxInInfo where
constrIndices _ = fromConstr2Index [Tuple "TxInInfo" 0]

--------------------------------------------------------------------------------

_TxInInfo :: Iso' TxInInfo {txInInfoOutRef :: TxOutRef, txInInfoResolved :: TxOut}
_TxInInfo = _Newtype

--------------------------------------------------------------------------------

newtype ScriptContext = ScriptContext
{ scriptContextTxInfo :: TxInfo
, scriptContextPurpose :: ScriptPurpose
}

derive instance Generic ScriptContext _

derive instance Newtype ScriptContext _

instance HasConstrIndices ScriptContext where
constrIndices _ = fromConstr2Index [Tuple "ScriptContext" 0]

--------------------------------------------------------------------------------

_ScriptContext :: Iso' ScriptContext {scriptContextTxInfo :: TxInfo, scriptContextPurpose :: ScriptPurpose}
_ScriptContext = _Newtype

--------------------------------------------------------------------------------

data ScriptPurpose
= Minting CurrencySymbol
| Spending TxOutRef
| Rewarding StakingCredential
| Certifying DCert

derive instance Generic ScriptPurpose _

instance HasConstrIndices ScriptPurpose where
constrIndices _ = fromConstr2Index [Tuple "Minting" 0,Tuple "Spending" 1,Tuple "Rewarding" 2,Tuple "Certifying" 3]

--------------------------------------------------------------------------------

_Minting :: Prism' ScriptPurpose CurrencySymbol
_Minting = prism' Minting case _ of
(Minting a) -> Just a
_ -> Nothing

_Spending :: Prism' ScriptPurpose TxOutRef
_Spending = prism' Spending case _ of
(Spending a) -> Just a
_ -> Nothing

_Rewarding :: Prism' ScriptPurpose StakingCredential
_Rewarding = prism' Rewarding case _ of
(Rewarding a) -> Just a
_ -> Nothing

_Certifying :: Prism' ScriptPurpose DCert
_Certifying = prism' Certifying case _ of
(Certifying a) -> Just a
_ -> Nothing
60 changes: 60 additions & 0 deletions Sample/Plutus/V1/Ledger/Credential.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
-- File auto generated by purescript-bridge! --
module Plutus.V1.Ledger.Credential where

import Prelude

import ConstrIndices (class HasConstrIndices, constrIndices, fromConstr2Index)
import Data.BigInt (BigInt)
import Data.Generic.Rep (class Generic)
import Data.Lens (Iso', Lens', Prism', iso, prism')
import Data.Lens.Iso.Newtype (_Newtype)
import Data.Lens.Record (prop)
import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..))
import Plutus.V1.Ledger.Crypto (PubKeyHash)
import Plutus.V1.Ledger.Scripts (ValidatorHash)
import Type.Proxy (Proxy(Proxy))

data StakingCredential
= StakingHash Credential
| StakingPtr BigInt BigInt BigInt

derive instance Generic StakingCredential _

instance HasConstrIndices StakingCredential where
constrIndices _ = fromConstr2Index [Tuple "StakingHash" 0,Tuple "StakingPtr" 1]

--------------------------------------------------------------------------------

_StakingHash :: Prism' StakingCredential Credential
_StakingHash = prism' StakingHash case _ of
(StakingHash a) -> Just a
_ -> Nothing

_StakingPtr :: Prism' StakingCredential {a :: BigInt, b :: BigInt, c :: BigInt}
_StakingPtr = prism' (\{a, b, c} -> (StakingPtr a b c)) case _ of
(StakingPtr a b c) -> Just {a, b, c}
_ -> Nothing

--------------------------------------------------------------------------------

data Credential
= PubKeyCredential PubKeyHash
| ScriptCredential ValidatorHash

derive instance Generic Credential _

instance HasConstrIndices Credential where
constrIndices _ = fromConstr2Index [Tuple "PubKeyCredential" 0,Tuple "ScriptCredential" 1]

--------------------------------------------------------------------------------

_PubKeyCredential :: Prism' Credential PubKeyHash
_PubKeyCredential = prism' PubKeyCredential case _ of
(PubKeyCredential a) -> Just a
_ -> Nothing

_ScriptCredential :: Prism' Credential ValidatorHash
_ScriptCredential = prism' ScriptCredential case _ of
(ScriptCredential a) -> Just a
_ -> Nothing
Loading