Giter Site home page Giter Site logo

input-output-hk / marlowe-ts-sdk Goto Github PK

View Code? Open in Web Editor NEW
19.0 14.0 10.0 31.2 MB

Marlowe TypeScript SDK

Home Page: https://marlowe.iohk.io/

License: Apache License 2.0

TypeScript 96.06% JavaScript 3.51% Nix 0.42%
cardano fp-ts input-output marlowe marlowe-contracts smart-contract

marlowe-ts-sdk's Introduction

Logo
Lightweight and typesafe SDK for writing Marlowe Contracts

Beta

The Marlowe TS-SDK is a suite of TypeScript/JavaScript libraries for developing Web-Dapp in the Cardano Blockchain using Marlowe Technologies.

It is composed of several npm packages documented in the API reference page.

Runtime

In order to interact with Marlowe contracts, the TS-SDK needs a Runtime instance. The following table shows the compatibility between the SDK and the Runtime versions:

runtime v0.0.5 runtime v0.0.6
SDK 0.2.0-beta x
SDK 0.3.0-beta

To get a running instance of the Runtime, it is recommended to check out the instructions on the Marlowe Starter Kit

Wallets

CIP-30 and Browser

The TS-SDK has a CIP-30 abstraction that works with the following wallets:

Wallets Compatible Not Compatible Not Tested
Nami
Eternl
Lace
Yoroi ?
Typhon ?

Lucid and NodeJS

The SDK also provides a wrapper around the Lucid Library. This allows you to use the SDK in a NodeJS environment.

Examples & Contract Use Cases

Inside the examples folder you can find a set of minimal examples on how to use different packages of the SDK.

Prototypes have been also built on top of this sdk:

Community & Support

Contributing

To report a bug or request a new feature, please look through existing Github Issues before opening a new one.

To help in the development of this SDK, please refer to this document.

marlowe-ts-sdk's People

Contributors

bjornkihlberg avatar franzavalla avatar hrajchert avatar nhenin avatar nstanford5 avatar palas avatar paluh avatar rober-m avatar sfoo-iohk avatar zeme-wana avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

marlowe-ts-sdk's Issues

Large/Deep Contract Support (Merkleized Contracts) Milestone Log

Specification

Why Merkleizing Contracts ?
In many real world scenarios, the size of a Marlowe contract can pose challenges. For instance, a contract may be too big to fit on a Cardano transaction. To handle this situation, the Marlowe semantics and plutus validator both support a size optimization called merkleization. Merkleization is a process that transforms a contract from a tree structure into a merkle DAG (directed-acyclic graph) consisting of multiple contract fragments that reference each other by hashes.

Merkle DAGs translate well to storage in UTxO-based blockchains like Cardano, because these blockchains are themselves merkle DAGs. Transactions reference outputs of previous transactions by their hashes.

A merkleized Marlowe contract gives just enough information to validate the next transaction. When applying an input to a merkleized contract, the next contract fragment must be provided alongside the input. As long as the continuation's hash matches the hash contained in the existing fragment, we know the continuation is genuine. The provided continuation can then be used to compute the next contract that will be in effect after the input is applied.

**What is the Development Status of this Feature on the Marlowe Stack ? **

The Building Blocks necessary for this functionality are complete at the Runtime level (Runtime Rest API). We have to propagate the feature in the ts-sdk and build a prototype on top of it (Token Plan 2.0).

Design Session

See Miro board link: https://miro.com/app/board/uXjVNO9wt2A=/ Password: marlowe123

Execution Plan

  1. Implement marlowe-object in the ts-sdk (used by endpoints below)
  2. Implement these endpoints at the ts-sdk level :
    - #69
    - #70
    - #71
    - #72
  3. Revisit the Vesting "POC" using merkleization
  4. Working on Token 2.0 Milestone

Add Readme with flows to the rest client example

Inside the examples folder, the rest-client-flow is a generic web tool that allows you to call the different endpoints by passing a simple JSON of the arguments.

We need to add a Readme that documents how to call the different endpoints.

Blockchain Agnostic Package

the Core package (that ideally should be blockchain agnostic, the same as the marlowe spec), this should just be an opaque type Address = string, and not a AddressBech32. Then when we are working with cardano runtime, the AddressBech32 will be assignable to the more permissive Address

Generated schema targets OpenApi 3.1.0

PLT-8824

Background

tx-pipe found a problem with the schema and reported it here.

Subtasks

  • Set generated schema to target OpenApi 3.1.0
  • Validate generated schema
    • openapi-generator-cli seem to keep generating issues with heterogenous arrays. Could it be that it's not updated?

    • openapi-spec-validator could be an alternative but it generates odd errors

      $ openapi-spec-validator openapi.json
      list indices must be integers or slices, not str

      I believe these errors are type errors from the implementation in Python. It probably should report more clearly exactly what is wrong with the file but that is not my problem right now. Might report it later to the maintainers as professional courtesy.

      Could it be because the version available on nix is 0.6.0? The latest version is 0.7.1. If I can test out 0.7.1 and it still doesn't work, it's worth asking the project maintainers what is wrong.

    • The generated schema was validated with https://editor-next.swagger.io.

PR

PLT-8824: Set generated schema to OpenApi version 3.1.0 #769

Create flat version of getPayouts

PLT-7704

Context

Required method for allowing API consumers to get contract payouts through a clean interface with the RestAPI type.

getPayouts: any

Example usage

import { mkRestClient } from "@marlowe.io/runtime-rest-client";

const restAPI: RestAPI = mkRestClient("www.runtimeurl.com");

const response = restAPI.getPayouts(...args);

Make manual release

[ ] - Change versions to 0.2.0-beta
[ ] - Collect scriv entries and create Changelog
[ ] - Manual deploy to npm
[ ] - Manual tag in repo

Pagination Fully Controllable For Collection Endpoints

Currently the only way of creating a TransactionRange is through the pagination links provided by the backend, but when I talked with @jamie Bertram he mentioned it is intended to be constructed by the user.

Link to relevant code

Currently the only way of creating a ContractRange is through the pagination links provided by the backend, but when I talked with he mentioned it is intended to be constructed by the user.

Link to relevant code

Improve the rest-client-flow example

For the moment the example is very raw, and it is only used for internal testing.

In order to be useful as a standalone example we could do some of the following:

  • Add some bootstrap styling (like the survey example)
  • Add guards to the request, so that if an invalid json is provided the error message is clearer.
  • Maybe remove the json request that works for all endpoints and put specific forms for each request

PLT-8746 - Generated schema does not conform to OpenApi spec

PLT-8746

Background

tx-pipe found problems with the schema and reported it here.

Subtasks

  • Get validator
    • nix-shell -p openapi-generator-cli
    • openapi-generator-cli validate -i openapi.json
  • Get openapi.json
    • cabal run marlowe-runtime-web -- --enable-open-api --http-port 8000
    • Navigate to http://localhost:8000/openapi.json
  • List issues
    • Errors:
      • attribute components.schemas.MarloweState.items is not of type object
      • attribute components.schemas.Plutus.StakingCredential.items is missing
      • attribute components.schemas.Plutus.StakingCredential.items is not of type object
      • attribute components.schemas.MarloweState.items is missing
    • Warnings:
      • Unused model: WithdrawTxBodyEnvelope
      • Unused model: CreateTxBodyEnvelope
  • Fix issues
    • attribute components.schemas.MarloweState.items is not of type object
    • attribute components.schemas.Plutus.StakingCredential.items is missing
    • attribute components.schemas.Plutus.StakingCredential.items is not of type object
    • attribute components.schemas.MarloweState.items is missing
    • Unused model: WithdrawTxBodyEnvelope Wont do this, requires more thought and isn't urgent.
    • Unused model: CreateTxBodyEnvelope Wont do this, requires more thought and isn't urgent.
  • Test ToSchema instances to prevent further issues
    • Relevant procedures can be found in Data.OpenApi.Schema.Validation.
    • No need, it's handled already with validateEveryToJSONWithPatternChecker!
    • StakingCredential (marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Orphans.hs)
    • State (marlowe-runtime-web/src/Language/Marlowe/Runtime/Web/Orphans.hs)

Notes

  • The problem with the schema is that you can't seem to model Haskell tuples as [13, "hey"] with the following schema according to the OpenAPI specification:
    { "type": "array"
    , "minItems": 2
    , "maxItems": 2
    , "items": [ { "type": "integer" }
               , { "type": "string" }
               ]
    }
    ... because items must be an object, and not an array.
  • One solution is to serialize tuples as object, eg:
    { "type": "object"
    , "properties": { "n": { "type": "integer" }
                    , "s": { "type": "string" }
                    }
    }
    This would introduce a breaking change because now [13, "hey"] becomes { "n": 13, "s": "hey" }
    @hrajchert notes regarding this:

    is more than the ts-sdk, tuples are serialized like that from the core specification
    it is too much of a breaking change

  • One solution is:
    { "type": "array"
    , "minItems": 2
    , "maxItems": 2
    , "items": { "oneOf": [ { "type": "integer" }
                          , { "type": "string" }
                          ]
               }
    }
    ... which doesn't introduce breaking changes but it
    • makes the derived documentation less clear.
      This can be mitigated by including a description.
    • makes any autogenerated interface that tx-pipe is building less type safe
      (because you could construct ["hey", 13] or [3, 14] etc etc).

Definition of done

  • Generated schema in marlowe runtime web satisfies the OpenApi specification

PR

PLT-8746: Generated schema conforms to OpenApi spec #761

Sanity checks on OpenAPI schema

PLT-8555

Work will occur in marlowe-cardano, a project not referenced on this board.

Specification

OpenAPI schema is unreliable. This ticket gets us started on a test suite for making it more reliable.

Design

Tests will be implemented in here: marlowe-cardano/marlowe-integration-tests/test/Language/Marlowe/Runtime/Web

Quote from Jamie:

At a high level, we want something like

lintOpenApi :: OpenApi -> [OpenApiIssue]

And then check

do
 let OpenApiWithEmptySecurity openApi' = openApi
 lintOpenApi openApi' `shouldBe` []

Open Role Support

Scope

  • Providing Open Roles and Thread Tokens Support within the ts-sdk. (read Doc)
  • createContract Endpoint Request side feature complete without #68

Out Of Scope

Currently, the ts-sdk hasn't implemented all the features available in the Runtime Rest API. This is the goal of 1-1 feature parity with marlowe-runtime-web (runtime) v0.0.5.1. This issue only focus on the Open Roles Feature and not on having a feature complete Contract Creation.

Runtime REST API Specification

Runtime Implementation : input-output-hk/marlowe-cardano#751 (Will be available Officially in next release 0.0.6)

  1. Configuration of Token Roles Happens at the creation of the Contract over Cardano in the runtime.
-- | POST /contracts sub-API
type PostContractsAPI =
  Summary "Create a new contract"
    :> Description
        "Build an unsigned (Cardano) transaction body which opens a new Marlowe contract. \
        \This unsigned transaction must be signed by a wallet (such as a CIP-30 or CIP-45 wallet) before being submitted. \
        \To submit the signed transaction, use the PUT /contracts/{contractId} endpoint."
    :> OperationId "createContract"
    :> RenameResponseSchema "CreateContractResponse"
    :> Header'
        '[Optional, Strict, Description "Where to send staking rewards for the Marlowe script outputs of this contract."]
        "X-Stake-Address"
        StakeAddress
    :> ( ReqBody '[JSON] PostContractsRequest :> PostTxAPI (PostCreated '[JSON] (PostContractsResponse CardanoTxBody))
          :<|> ReqBody '[JSON] PostContractsRequest :> PostTxAPI (PostCreated '[TxJSON ContractTx] (PostContractsResponse CardanoTx))
       )

data PostContractsRequest = PostContractsRequest
  { tags :: Map Text Metadata
  , metadata :: Map Word64 Metadata
  , version :: MarloweVersion
  , roles :: Maybe RolesConfig
  , threadTokenName :: Maybe Text 
  , contract :: ContractOrSourceId
  , minUTxODeposit :: Maybe Word64
  }
  deriving (Show, Eq, Ord, Generic)

newtype ContractOrSourceId = ContractOrSourceId (Either Semantics.Contract ContractSourceId)
  deriving (Show, Eq, Ord, Generic) 

newtype ContractSourceId = ContractSourceId {unContractSourceId :: ByteString}
  deriving (Eq, Ord, Generic)
  deriving (Show, ToHttpApiData, ToJSON) via Base16

data RolesConfig
  = UsePolicy PolicyId
  | UsePolicyWithOpenRoles PolicyId [Text]
  | Mint (Map Text RoleTokenConfig)
  deriving (Show, Eq, Ord, Generic)

instance FromJSON RolesConfig where
  parseJSON (String s) = UsePolicy <$> parseJSON (String s)
  parseJSON value =
    withObject
      "RolesConfig"
      ( \obj ->
          let parseMint = Mint <$> parseJSON value
              parseOpen =
                do
                  script <- obj .: "script"
                  unless (script == ("OpenRole" :: String)) $ fail "AllowedValues: \"OpenRole\""
                  UsePolicyWithOpenRoles <$> obj .: "policyId" <*> obj .: "openRoleNames"
           in parseOpen <|> parseMint
      )
      value
data RoleTokenConfig = RoleTokenConfig
  { recipients :: RoleTokenRecipients
  , metadata :: Maybe TokenMetadata
  }
  deriving (Show, Eq, Ord, Generic)

type RoleTokenRecipients = Map RoleTokenRecipient Word64

data RoleTokenRecipient
  = ClosedRole Address
  | OpenRole
  deriving (Show, Eq, Ord, Generic)

instance FromJSON RoleTokenConfig where
  parseJSON (String "OpenRole") =
    pure
      . flip RoleTokenConfig Nothing
      $ Map.singleton OpenRole 1
  parseJSON (String s) =
    pure
      . flip RoleTokenConfig Nothing
      . flip Map.singleton 1
      . ClosedRole
      $ Address s
  parseJSON value =
    withObject
      "RoleTokenConfig"
      ( \obj -> do
          mRecipients <- obj .:? "recipients"
          mAddress <- obj .:? "address"
          mScriptRole <- do
            mScript :: Maybe String <- obj .:? "script"
            for mScript \case
              "OpenRole" -> pure OpenRole
              _ -> fail "Expected \'OpenRole\""
          metadata <- obj .:? "metadata"
          recipients <- case (mRecipients, mAddress, mScriptRole) of
            (Just recipients, _, _) -> pure recipients
            (_, Just address, _) -> pure $ Map.singleton (ClosedRole address) 1
            (_, _, Just scriptRole) -> pure $ Map.singleton scriptRole 1
            _ -> fail "one of recipients, address, or script required"
          pure RoleTokenConfig{..}
      )
      value

instance ToJSON RoleTokenConfig where
  toJSON (RoleTokenConfig recipients metadata) =
    object
      [ "recipients" .= recipients
      , "metadata" .= metadata
      ]

data TokenMetadata = TokenMetadata
  { name :: Text
  , image :: URI
  , mediaType :: Maybe Text
  , description :: Maybe Text
  , files :: Maybe [TokenMetadataFile]
  }
  deriving (Show, Eq, Ord, Generic)

Design Session

https://miro.com/app/board/uXjVNL4Nk0g=/ Password: MArlowe.1234

References / Examples

Specifications

export type CreateContractRequest = {
  contract: Contract;
  roles?: RolesConfig;
  tags?: Tags;
  metadata?: Metadata;
  mininmumLovelaceUTxODeposit?: number;
};

Atomic Swap Contract in @marlowe.io/language-examples

References

PRD : https://docs.google.com/document/d/1HvjoOa-xeGRPwwOogMROmp-9cmxTlxciPLWfUpKtKy8/edit#heading=h.a7cqpowdv776

Specifications

Description

The Atomic Swap Contract is a Marlowe Contract allowing 2 participants (A Seller and a Buyer) to atomically exchange some tokens A against some token B.

Definition

  • Create
    • Participants
      • Seller : Closed Role
      • Buyer : Open Role
        • Prerequisite #54
    • Scheme
      • Offered Tokens
        • Policy Id + Token Name
        • Amount
      • Asked Tokens
        • Policy Id + Token Name
        • Offered/Asked Rate
      • Offer Deadline
  • Apply Inputs
    • Swap
    • Retract

N.B : This feature is enabling the full completion of the Order Book Swap Prototype

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.