diff --git a/MetaLamp/lending-pool/README.md b/MetaLamp/lending-pool/README.md index c1aaaa9c4..3d3d6db7e 100644 --- a/MetaLamp/lending-pool/README.md +++ b/MetaLamp/lending-pool/README.md @@ -14,10 +14,9 @@ The smart contract protocol is based on [Aave](https://aave.com/), but does not We have provided two PAB applications in `./pab` and `./pab-simulation`. The first one is made for real world usage and interaction through frontend [client](client/README.md), the second one is a big test scenario. With the PAB we can serve and interact with contracts over a web API. You can read more about the PAB here: [PAB Architecture](https://github.com/input-output-hk/plutus/blob/master/plutus-pab/ARCHITECTURE.adoc). -1. Enter the nix shell (cd to the cloned Plutus repo): +1. Enter the nix shell (from `lending-pool` directory): ``` -git checkout 5cdd2c3d708bf4c33514681dee096da6463273b7 nix-shell ``` diff --git a/MetaLamp/lending-pool/cabal.project b/MetaLamp/lending-pool/cabal.project index 964bef10c..ad1a2aaad 100644 --- a/MetaLamp/lending-pool/cabal.project +++ b/MetaLamp/lending-pool/cabal.project @@ -1,4 +1,4 @@ -index-state: 2021-02-24T00:00:00Z +index-state: 2021-04-13T00:00:00Z packages: ./. @@ -26,7 +26,7 @@ source-repository-package prettyprinter-configurable quickcheck-dynamic word-array - tag: 5cdd2c3d708bf4c33514681dee096da6463273b7 + tag: plutus-starter-devcontainer/v1.0.6 -- The following sections are copied from the 'plutus' repository cabal.project at the revision -- given above. @@ -56,6 +56,12 @@ constraints: extra-packages: ieee, filemanip +-- Drops an instance breaking our code. Should be released to Hackage eventually. +source-repository-package + type: git + location: https://github.com/Quid2/flat.git + tag: 95e5d7488451e43062ca84d5376b3adcc465f1cd + -- Needs some patches, but upstream seems to be fairly dead (no activity in > 1 year) source-repository-package type: git @@ -70,7 +76,7 @@ source-repository-package source-repository-package type: git location: https://github.com/input-output-hk/cardano-crypto.git - tag: f73079303f663e028288f9f4a9e08bcca39a923e + tag: ce8f1934e4b6252084710975bd9bbc0a4648ece4 -- Needs a fix (https://github.com/wenkokke/unlit/pull/11) and a Hackage release source-repository-package @@ -81,18 +87,20 @@ source-repository-package source-repository-package type: git location: https://github.com/input-output-hk/cardano-base - tag: 4251c0bb6e4f443f00231d28f5f70d42876da055 + tag: a715c7f420770b70bbe95ca51d3dec83866cb1bd subdir: binary binary/test slotting cardano-crypto-class cardano-crypto-praos + cardano-crypto-tests + strict-containers source-repository-package type: git location: https://github.com/input-output-hk/cardano-prelude - tag: ee4e7b547a991876e6b05ba542f4e62909f4a571 + tag: fd773f7a58412131512b9f694ab95653ac430852 subdir: cardano-prelude cardano-prelude-test @@ -100,22 +108,25 @@ source-repository-package source-repository-package type: git location: https://github.com/input-output-hk/ouroboros-network - tag: 6cb9052bde39472a0555d19ade8a42da63d3e904 + tag: e50613562d6d4a0f933741fcf590b0f69a1eda67 subdir: typed-protocols typed-protocols-examples ouroboros-network ouroboros-network-testing ouroboros-network-framework + ouroboros-consensus + ouroboros-consensus-byron + ouroboros-consensus-cardano + ouroboros-consensus-shelley io-sim io-sim-classes network-mux - Win32-network source-repository-package type: git location: https://github.com/input-output-hk/iohk-monitoring-framework - tag: a89c38ed5825ba17ca79fddb85651007753d699d + tag: 34abfb7f4f5610cabb45396e0496472446a0b2ca subdir: iohk-monitoring tracer-transformers @@ -125,7 +136,7 @@ source-repository-package source-repository-package type: git location: https://github.com/input-output-hk/cardano-ledger-specs - tag: 097890495cbb0e8b62106bcd090a5721c3f4b36f + tag: a3ef848542961079b7cd53d599e5385198a3035c subdir: byron/chain/executable-spec byron/crypto @@ -137,14 +148,32 @@ source-repository-package semantics/small-steps-test shelley/chain-and-ledger/dependencies/non-integer shelley/chain-and-ledger/executable-spec + shelley/chain-and-ledger/shelley-spec-ledger-test shelley-ma/impl + cardano-ledger-core + alonzo/impl +-- A lot of plutus dependencies have to be synchronized with the dependencies of +-- cardano-node. If you update cardano-node, please make sure that all dependencies +-- of cardano-node are also updated. source-repository-package type: git - location: https://github.com/input-output-hk/goblins - tag: cde90a2b27f79187ca8310b6549331e59595e7ba + location: https://github.com/input-output-hk/cardano-node.git + tag: b3cabae6b3bf30a0b1b4e78bc4b67282dabad0a6 + subdir: + cardano-api source-repository-package type: git - location: https://github.com/Quid2/flat.git - tag: 95e5d7488451e43062ca84d5376b3adcc465f1cd + location: https://github.com/input-output-hk/Win32-network + tag: 94153b676617f8f33abe8d8182c37377d2784bd1 + +source-repository-package + type: git + location: https://github.com/input-output-hk/hedgehog-extras + tag: 8bcd3c9dc22cc44f9fcfe161f4638a384fc7a187 + +source-repository-package + type: git + location: https://github.com/input-output-hk/goblins + tag: cde90a2b27f79187ca8310b6549331e59595e7ba diff --git a/MetaLamp/lending-pool/client/README.md b/MetaLamp/lending-pool/client/README.md index 155196fcf..4a9bbdb90 100644 --- a/MetaLamp/lending-pool/client/README.md +++ b/MetaLamp/lending-pool/client/README.md @@ -4,34 +4,35 @@ The client application has a minimalistic interface to the PAB [server](/MetaLam ## Running the project -1. Install npm packages. +1. Enter the nix shell (from `lending-pool` directory): ``` -npm install +nix-shell ``` -2. Generate necessary PureScript code from Haskell source. This step runs an executable(`generate-purs`) from `lending-pool` directory, which requires a certain environment. The setup steps are described in `lending-pool/README`. Provided that you are able to build the backend, you can use the same approach to run purescript generation from `client` folder, i.e. +Cd to `./client` folder. + -Enter the nix shell (cd to the cloned Plutus repo): +2. Install npm packages. ``` -git checkout 5cdd2c3d708bf4c33514681dee096da6463273b7 -nix-shell +npm install ``` -cd to `lending-pool/client` folder and execute +3. Generate necessary PureScript code from Haskell source. This step runs an executable(`generate-purs`) from `lending-pool` directory, which requires a certain environment. The setup steps are described in `lending-pool/README`. Provided that you are able to build the backend, you can use the same approach to run purescript generation from `client` folder, i.e. + ``` npm run generate-purs ``` -3. Start the client: +4. Start the client: ``` npm start ``` -4. Open browser to interact with the app at https://localhost:8009/. +5. Open browser to interact with the app at https://localhost:8009/. CORS protection needs to be disabled. You can use this script to launch chromium (note that first you need to close chromium completely, otherwise security won't be disabled): ``` diff --git a/MetaLamp/lending-pool/client/scripts/fetch-plutus-purs.sh b/MetaLamp/lending-pool/client/scripts/fetch-plutus-purs.sh index 745d22fa7..4b185c343 100755 --- a/MetaLamp/lending-pool/client/scripts/fetch-plutus-purs.sh +++ b/MetaLamp/lending-pool/client/scripts/fetch-plutus-purs.sh @@ -6,4 +6,4 @@ git remote add origin -f https://github.com/input-output-hk/plutus git config core.sparseCheckout true echo 'web-common-plutus/*' >> .git/info/sparse-checkout echo 'web-common/*' >> .git/info/sparse-checkout -git pull origin 5cdd2c3d708bf4c33514681dee096da6463273b7 +git pull origin bd16cc29045ffc7eaa6beaabe3b985a56cb9292a # plutus-starter-devcontainer/v1.0.6 diff --git a/MetaLamp/lending-pool/default.nix b/MetaLamp/lending-pool/default.nix new file mode 100644 index 000000000..6c0824149 --- /dev/null +++ b/MetaLamp/lending-pool/default.nix @@ -0,0 +1,35 @@ +######################################################################## +# default.nix -- The top-level nix build file for plutus-starter. +# +# This file defines various attributes that are used for building and +# developing plutus-starter. +# +######################################################################## + +let + # Here a some of the various attributes for the variable 'packages': + # + # { pkgs + # plutus-starter: { + # haskell: { + # project # The Haskell project created by haskell-nix.project + # packages # All the packages defined by our project, including dependencies + # projectPackages # Just the packages in the project + # } + # hlint + # cabal-install + # stylish-haskell + # haskell-language-server + # } + # } + + packages = import ./nix; + + inherit (packages) pkgs plutus-starter; + project = plutus-starter.haskell.project; +in +{ + inherit pkgs plutus-starter; + + inherit project; +} diff --git a/MetaLamp/lending-pool/generate-purs/Main.hs b/MetaLamp/lending-pool/generate-purs/Main.hs index a3d528b2a..276c0e45f 100644 --- a/MetaLamp/lending-pool/generate-purs/Main.hs +++ b/MetaLamp/lending-pool/generate-purs/Main.hs @@ -43,23 +43,13 @@ import Language.PureScript.Bridge.CodeGenSwitches (ForeignOptions (For genForeign, unwrapSingleConstructors) import Language.PureScript.Bridge.TypeParameters (A) -import Ledger.Constraints.OffChain (UnbalancedTx) import qualified PSGenerator.Common import Plutus.Contract.Checkpoint (CheckpointKey, CheckpointStore, CheckpointStoreItem) -import Plutus.Contract.Effects.AwaitSlot (WaitingForSlot) -import Plutus.Contract.Effects.AwaitTxConfirmed (TxConfirmed) -import Plutus.Contract.Effects.ExposeEndpoint (ActiveEndpoint, - EndpointValue) -import Plutus.Contract.Effects.Instance (OwnIdRequest) -import Plutus.Contract.Effects.OwnPubKey (OwnPubKeyRequest) -import Plutus.Contract.Effects.UtxoAt (UtxoAtAddress) -import Plutus.Contract.Effects.WriteTx (WriteTxResponse) +import Plutus.Contract.Effects (TxConfirmed) import Plutus.Contract.Resumable (Responses) import Plutus.PAB.Effects.Contract.ContractExe (ContractExe) -import Plutus.PAB.Events.Contract (ContractPABRequest, - ContractPABResponse) import Plutus.PAB.Events.ContractInstanceState (PartiallyDecodedResponse) import qualified Plutus.PAB.Webserver.API as API import Plutus.PAB.Webserver.Types (ChainReport, @@ -84,8 +74,6 @@ import Servant.PureScript (HasBridge, writeAPIModuleWithSettings) import System.Directory (doesDirectoryExist, removeDirectoryRecursive) -import Wallet.Effects (AddressChangeRequest (..), - AddressChangeResponse (..)) import Wallet.Emulator.Wallet (Wallet (..)) myBridge :: BridgePart @@ -133,25 +121,13 @@ myTypes = , (equal <*> (genericShow <*> mkSumType)) (Proxy @(ContractSignatureResponse A)) , (equal <*> (genericShow <*> mkSumType)) (Proxy @(PartiallyDecodedResponse A)) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @ContractPABRequest) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @ContractPABResponse) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @UnbalancedTx) -- Contract request / response types - , (equal <*> (genericShow <*> mkSumType)) (Proxy @ActiveEndpoint) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @(EndpointValue A)) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @OwnPubKeyRequest) , (equal <*> (genericShow <*> mkSumType)) (Proxy @TxConfirmed) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @UtxoAtAddress) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @WriteTxResponse) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @WaitingForSlot) , (equal <*> (genericShow <*> mkSumType)) (Proxy @CheckpointStore) , (order <*> (genericShow <*> mkSumType)) (Proxy @CheckpointKey) , (equal <*> (genericShow <*> mkSumType)) (Proxy @(CheckpointStoreItem A)) , (equal <*> (genericShow <*> mkSumType)) (Proxy @(Responses A)) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @AddressChangeRequest) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @AddressChangeResponse) - , (equal <*> (genericShow <*> mkSumType)) (Proxy @OwnIdRequest) -- Logging types , (equal <*> (genericShow <*> mkSumType)) (Proxy @(LogMessage A)) diff --git a/MetaLamp/lending-pool/nix/default.nix b/MetaLamp/lending-pool/nix/default.nix new file mode 100644 index 000000000..6a866cbb2 --- /dev/null +++ b/MetaLamp/lending-pool/nix/default.nix @@ -0,0 +1,20 @@ +let + # Pratically, the only needed dependency is the plutus repository. + sources = import ./sources.nix { inherit pkgs; }; + + # We're going to get everything from the main plutus repository. This ensures + # we're using the same version of multiple dependencies such as nipxkgs, + # haskell-nix, cabal-install, compiler-nix-name, etc. + plutus = import sources.plutus {}; + pkgs = plutus.pkgs; + + haskell-nix = pkgs.haskell-nix; + + plutus-starter = import ./pkgs { + inherit pkgs haskell-nix sources plutus; + }; + +in +{ + inherit pkgs plutus-starter; +} diff --git a/MetaLamp/lending-pool/nix/lib/ci.nix b/MetaLamp/lending-pool/nix/lib/ci.nix new file mode 100644 index 000000000..80794a750 --- /dev/null +++ b/MetaLamp/lending-pool/nix/lib/ci.nix @@ -0,0 +1,201 @@ +{ pkgs }: + +let + # Generic nixpkgs, use *only* for lib functions that are stable across versions + lib = pkgs.lib; +in +rec { + # Borrowed from https://github.com/cachix/ghcide-nix/pull/4/files#diff-70bfff902f4dec33e545cac10ee5844d + # Tweaked to use builtins.mapAttrs instead of needing the one from nixpkgs lib + /* + dimension: name -> attrs -> function -> attrs + where + function: keyText -> value -> attrsOf package + + WARNING: Attribute names must not contain periods ("."). + See https://github.com/NixOS/nix/issues/3088 + + NOTE: The dimension name will be picked up by agent and web ui soon. + + Specifies a dimension of the build matrix. For example + + dimension "Example" { + withP = { p = true; } + withoutP = { p = false; } + } (key: # either "withP" or "withoutP" + { p }: # either p = true or p = false + myProject p + ) + + evaluates roughly to + + { + withP = myProject true; + withoutP = myProject false; + } + + Use nested calls for multiple dimensions. + + Example: + + dimension "System" { + "x86_64-linux" = {}; + # ... + }: (system: {}: + + dimension "Nixpkgs release" ( + { + "nixpkgs-19_03".nixpkgs = someSource + } // optionalAttrs (system != "...") { + "nixpkgs-unstable".nixpkgs = someOtherSource + } + ) (_key: { nixpkgs }: + + myProject system nixpkgs + + ) + ) + + evaluates roughly to + + { + x86_64-linux.nixpkgs-19_03 = myProject "x86_64-linux" someSource; + x86_64-linux.nixpkgs-unstable = myProject "x86_64-linux" someOtherSource; + ... + } + + If you need to make references across attributes, you can do so by binding + the result. Wherever you write + + dimension "My dimension" {} (key: value: f1 key value) + + You can also write + + let + myDimension = dimension "My dimension" {} (key: value: f2 key value myDimension) + in + myDimension + + This example builds a single test runner to reuse across releases: + + let + overlay = + testRunnerPkgs: self: super: { + # ... + }; + myProject = + { nixpkgs, + pkgs ? import nixpkgs { overlays = [ overlay ]; }, + testRunnerPkgs ? pkgs + }: pkgs; + in + + let + latest = "nixpkgs-19_03"; + releases = + dimension "Nixpkgs release" + { + nixpkgs-18_09.nixpkgs = someSource + nixpkgs-19_03.nixpkgs = someOtherSource + } + (_key: { nixpkgs }: + + myProject { + inherit nixpkgs; + testRunnerPkgs = releases."${latest}"; + } + + ); + in releases; + + */ + dimension = name: attrs: f: + builtins.mapAttrs + (k: v: + let o = f k v; + in o // { recurseForDerivations = o.recurseForDerivations or true; } + ) + attrs + // { meta.dimension.name = name; }; + + /* + Takes an attribute set and returns all the paths to derivations within it, i.e. + derivationPaths { a = { b = ; }; c = ; } == [ "a.b" "c" ] + This can be used with 'attrByPath' or the 'constitutents' of an aggregate Hydra job. + */ + derivationPaths = + let + names = x: lib.filter (n: n != "recurseForDerivations" && n != "meta") (builtins.attrNames x); + go = nameSections: attrs: + builtins.concatMap + (n: + let + v = builtins.getAttr n attrs; + newNameSections = nameSections ++ [ n ]; + in + if pkgs.lib.isDerivation v + then [ (builtins.concatStringsSep "." newNameSections) ] + else if builtins.isAttrs v + then go newNameSections v + else [ ] + ) + (names attrs); + in + go [ ]; + + # Creates an aggregate job with the given name from every derivation in the attribute set. + derivationAggregate = name: attrs: pkgs.releaseTools.aggregate { + inherit name; + constituents = derivationPaths attrs; + }; + + # A filter for removing packages that aren't supported on the current platform + # according to 'meta.platforms'. + platformFilterGeneric = pkgs: system: + # This needs to use the correct nixpkgs version so all the systems line up + let + lib = pkgs.lib; + platform = lib.systems.elaborate { inherit system; }; + # Can't just default to [] for platforms, since no meta.platforms + # means "all platforms" not "no platforms" + in + drv: + if drv ? meta && drv.meta ? platforms then + lib.any (lib.meta.platformMatch platform) drv.meta.platforms + else true; + + # Hydra doesn't like these attributes hanging around in "jobsets": it thinks they're jobs! + stripAttrsForHydra = filterAttrsOnlyRecursive (n: _: n != "recurseForDerivations" && n != "dimension"); + + # Keep derivations and attrsets with 'recurseForDerivations'. This ensures that we match the + # derivations that Hercules will see, and prevents Hydra from trying to pick up all sorts of bad stuff + # (like attrsets that contain themselves!). + filterDerivations = filterAttrsOnlyRecursive (n: attrs: lib.isDerivation attrs || attrs.recurseForDerivations or false); + + # A version of 'filterAttrsRecursive' that doesn't recurse into derivations. This prevents us from going into an infinite + # loop with the 'out' attribute on derivations. + # TODO: Surely this shouldn't be necessary. I think normal 'filterAttrsRecursive' will effectively cause infinite loops + # if you keep derivations and your predicate forces the value of the attribute, as this then triggers a loop on the + # 'out' attribute. Weird. + filterAttrsOnlyRecursive = pred: set: + lib.listToAttrs ( + lib.concatMap + (name: + let v = set.${name}; in + if pred name v then [ + (lib.nameValuePair name ( + if builtins.isAttrs v && !lib.isDerivation v then filterAttrsOnlyRecursive pred v + else v + )) + ] else [ ] + ) + (builtins.attrNames set) + ); + + # Takes an array of systems and returns a `name: system` AttrSet + # filterSystems :: [ string ] -> AttrSet + filterSystems = systems: lib.filterAttrs (_: v: builtins.elem v systems) { + linux = "x86_64-linux"; + darwin = "x86_64-darwin"; + }; +} diff --git a/MetaLamp/lending-pool/nix/pkgs/default.nix b/MetaLamp/lending-pool/nix/pkgs/default.nix new file mode 100644 index 000000000..98ffcd0e2 --- /dev/null +++ b/MetaLamp/lending-pool/nix/pkgs/default.nix @@ -0,0 +1,42 @@ +{ pkgs +, sources +, plutus +, haskell-nix +}: +let + gitignore-nix = pkgs.callPackage plutus."gitignore.nix" { }; + + compiler-nix-name = plutus.plutus.haskell.compiler-nix-name; + + haskell = pkgs.callPackage ./haskell { + inherit gitignore-nix sources haskell-nix; + inherit compiler-nix-name; # Use the same GHC version as plutus + }; + + hlint = plutus.plutus.hlint; + + cabal-install = plutus.plutus.cabal-install; + + nodejs = plutus.pkgs.nodejs; + + purs = plutus.plutus.purs; + + spago = plutus.plutus.spago; + + purty = plutus.plutus.purty; + + fix-purty = plutus.plutus.fixPurty; + + fix-stylish-haskell = plutus.plutus.fixStylishHaskell; + + stylish-haskell = plutus.plutus.stylish-haskell; + + haskell-language-server = plutus.plutus.haskell-language-server; + + cardano-repo-tool = plutus.plutus.cardano-repo-tool; +in +{ + inherit nodejs purs spago purty fix-purty; + inherit haskell hlint cabal-install stylish-haskell fix-stylish-haskell haskell-language-server; + inherit cardano-repo-tool; +} diff --git a/MetaLamp/lending-pool/nix/pkgs/haskell/default.nix b/MetaLamp/lending-pool/nix/pkgs/haskell/default.nix new file mode 100644 index 000000000..67036b9d5 --- /dev/null +++ b/MetaLamp/lending-pool/nix/pkgs/haskell/default.nix @@ -0,0 +1,35 @@ +{ lib +, haskell-nix +, gitignore-nix +, sources +, compiler-nix-name +}: +let + # The Hackage index-state from cabal.project + index-state = + let + parseIndexState = rawCabalProject: + let + indexState = lib.lists.concatLists ( + lib.lists.filter (l: l != null) + (map (l: builtins.match "^index-state: *(.*)" l) + (lib.splitString "\n" rawCabalProject))); + in + lib.lists.head (indexState ++ [ null ]); + in + parseIndexState (builtins.readFile ../../../cabal.project); + + # The haskell project created by haskell-nix.cabalProject' + project = import ./haskell.nix { + inherit haskell-nix compiler-nix-name gitignore-nix; + }; + + # All the packages defined by our project, including dependencies + packages = project.hsPkgs; + + # Just the packages in the project + projectPackages = haskell-nix.haskellLib.selectProjectPackages packages; +in +rec { + inherit project projectPackages packages; +} diff --git a/MetaLamp/lending-pool/nix/pkgs/haskell/haskell.nix b/MetaLamp/lending-pool/nix/pkgs/haskell/haskell.nix new file mode 100644 index 000000000..517deaa42 --- /dev/null +++ b/MetaLamp/lending-pool/nix/pkgs/haskell/haskell.nix @@ -0,0 +1,54 @@ +############################################################################ +# Builds Haskell packages with Haskell.nix +############################################################################ +{ haskell-nix +, gitignore-nix +, compiler-nix-name +}: + +let + project = haskell-nix.project { + # 'cleanGit' cleans a source directory based on the files known by git + src = haskell-nix.haskellLib.cleanGit { + name = "plutus-starter"; + src = ../../../.; + }; + + inherit compiler-nix-name; + + sha256map = { + "https://github.com/Quid2/flat.git"."95e5d7488451e43062ca84d5376b3adcc465f1cd" = "06l31x3y93rjpryvlxnpsyq2zyxvb0z6lik6yq2fvh36i5zwvwa3"; + "https://github.com/input-output-hk/plutus.git"."plutus-starter-devcontainer/v1.0.6" = "1jzbcsdrv0b43dj7bwbd1fbk71f7gph6zzb8y29n9cn3j8illnyc"; + "https://github.com/shmish111/purescript-bridge.git"."6a92d7853ea514be8b70bab5e72077bf5a510596" = "13j64vv116in3c204qsl1v0ajphac9fqvsjp7x3zzfr7n7g61drb"; + "https://github.com/shmish111/servant-purescript.git"."a76104490499aa72d40c2790d10e9383e0dbde63" = "11nxxmi5bw66va7psvrgrw7b7n85fvqgfp58yva99w3v9q3a50v9"; + "https://github.com/input-output-hk/cardano-crypto.git"."ce8f1934e4b6252084710975bd9bbc0a4648ece4" = "1v2laq04piyj511b2m77hxjh9l1yd6k9kc7g6bjala4w3zdwa4ni"; + "https://github.com/michaelpj/unlit.git"."9ca1112093c5ffd356fc99c7dafa080e686dd748" = "145sffn8gbdn6xp9q5b75yd3m46ql5bnc02arzmpfs6wgjslfhff"; + "https://github.com/input-output-hk/cardano-base"."a715c7f420770b70bbe95ca51d3dec83866cb1bd" = "06l06mmb8cd4q37bnvfpgx1c5zgsl4xaf106dqva98738i8asj7j"; + "https://github.com/input-output-hk/cardano-prelude"."fd773f7a58412131512b9f694ab95653ac430852" = "02jddik1yw0222wd6q0vv10f7y8rdgrlqaiy83ph002f9kjx7mh6"; + "https://github.com/input-output-hk/ouroboros-network"."e50613562d6d4a0f933741fcf590b0f69a1eda67" = "0i192ksa69lpzjhzmhd2h1mramkvvikw04pqws18h5dly55f4z3k"; + "https://github.com/input-output-hk/iohk-monitoring-framework"."34abfb7f4f5610cabb45396e0496472446a0b2ca" = "1fdc0a02ipa385dnwa6r6jyc8jlg537i12hflfglkhjs2b7i92gs"; + "https://github.com/input-output-hk/cardano-ledger-specs"."a3ef848542961079b7cd53d599e5385198a3035c" = "02iwn2lcfcfvrnvcqnx586ncdnma23vdqvicxgr4f39vcacalzpd"; + "https://github.com/input-output-hk/cardano-node.git"."b3cabae6b3bf30a0b1b4e78bc4b67282dabad0a6" = "1csmji1bgi45wgrw7kqy19s4bbbpa78kjg3bz7mbiwb8vjgg9kvq"; + "https://github.com/input-output-hk/Win32-network"."94153b676617f8f33abe8d8182c37377d2784bd1" = "0pb7bg0936fldaa5r08nqbxvi2g8pcy4w3c7kdcg7pdgmimr30ss"; + "https://github.com/input-output-hk/hedgehog-extras"."8bcd3c9dc22cc44f9fcfe161f4638a384fc7a187" = "12viwpahjdfvlqpnzdgjp40nw31rvyznnab1hml9afpaxd6ixh70"; + "https://github.com/input-output-hk/goblins"."cde90a2b27f79187ca8310b6549331e59595e7ba" = "17c88rbva3iw82yg9srlxjv2ia5wjb9cyqw44hik565f5v9svnyg"; + }; + + modules = [ + { + packages = { + eventful-sql-common = { + # This is needed so evenful-sql-common will build with a newer version of persistent. + ghcOptions = [ "-XDerivingStrategies -XStandaloneDeriving -XUndecidableInstances -XDataKinds -XFlexibleInstances -XMultiParamTypeClasses" ]; + doHaddock = false; + }; + + # Broken due to haddock errors. Refer to https://github.com/input-output-hk/plutus/blob/master/nix/pkgs/haskell/haskell.nix + plutus-ledger.doHaddock = false; + plutus-use-cases.doHaddock = false; + }; + } + ]; + }; +in + project diff --git a/MetaLamp/lending-pool/nix/sources.json b/MetaLamp/lending-pool/nix/sources.json new file mode 100644 index 000000000..94979120f --- /dev/null +++ b/MetaLamp/lending-pool/nix/sources.json @@ -0,0 +1,14 @@ +{ + "plutus": { + "branch": "master", + "description": "The Plutus language implementation and tools", + "homepage": "", + "owner": "input-output-hk", + "repo": "plutus", + "rev": "plutus-starter-devcontainer/v1.0.6", + "sha256": "1jzbcsdrv0b43dj7bwbd1fbk71f7gph6zzb8y29n9cn3j8illnyc", + "type": "tarball", + "url": "https://github.com/input-output-hk/plutus/archive/plutus-starter-devcontainer/v1.0.6.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/MetaLamp/lending-pool/nix/sources.nix b/MetaLamp/lending-pool/nix/sources.nix new file mode 100644 index 000000000..1938409dd --- /dev/null +++ b/MetaLamp/lending-pool/nix/sources.nix @@ -0,0 +1,174 @@ +# This file has been generated by Niv. + +let + + # + # The fetchers. fetch_ fetches specs of type . + # + + fetch_file = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchurl { inherit (spec) url sha256; name = name'; } + else + pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; + + fetch_tarball = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchTarball { name = name'; inherit (spec) url sha256; } + else + pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; + + fetch_git = name: spec: + let + ref = + if spec ? ref then spec.ref else + if spec ? branch then "refs/heads/${spec.branch}" else + if spec ? tag then "refs/tags/${spec.tag}" else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + in + builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; }; + + fetch_local = spec: spec.path; + + fetch_builtin-tarball = name: throw + ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; + + fetch_builtin-url = name: throw + ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; + + # + # Various helpers + # + + # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 + sanitizeName = name: + ( + concatMapStrings (s: if builtins.isList s then "-" else s) + ( + builtins.split "[^[:alnum:]+._?=-]+" + ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + ) + ); + + # The set of packages used when specs are fetched using non-builtins. + mkPkgs = sources: system: + let + sourcesNixpkgs = + import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; + hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; + hasThisAsNixpkgsPath = == ./.; + in + if builtins.hasAttr "nixpkgs" sources + then sourcesNixpkgs + else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then + import {} + else + abort + '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # The actual fetching function. + fetch = pkgs: name: spec: + + if ! builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then fetch_file pkgs name spec + else if spec.type == "tarball" then fetch_tarball pkgs name spec + else if spec.type == "git" then fetch_git name spec + else if spec.type == "local" then fetch_local spec + else if spec.type == "builtin-tarball" then fetch_builtin-tarball name + else if spec.type == "builtin-url" then fetch_builtin-url name + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # If the environment variable NIV_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + replace = name: drv: + let + saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; + ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; + in + if ersatz == "" then drv else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = builtins.mapAttrs or ( + f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) + ); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 + optionalAttrs = cond: as: if cond then as else {}; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec + then abort + "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) config.sources; + + # The "config" used by the fetchers + mkConfig = + { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null + , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile) + , system ? builtins.currentSystem + , pkgs ? mkPkgs sources system + }: rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; + +in +mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/MetaLamp/lending-pool/release.nix b/MetaLamp/lending-pool/release.nix new file mode 100644 index 000000000..d83bfbf3f --- /dev/null +++ b/MetaLamp/lending-pool/release.nix @@ -0,0 +1,52 @@ +# The content of this file was partially copied from the equivalent file in the plutus repository. +# It is used by IOHK's Hydra for CI (building the project, running the tests, etc.) +# +# Therefore, do not worry too much about the structure. +let + packages = import ./.; + + pkgs = packages.pkgs; + haskellNix = pkgs.haskell-nix; + + # Just the packages in the project + projectPackages = haskellNix.haskellLib.selectProjectPackages packages.project.hsPkgs; + + inherit (import ./nix/lib/ci.nix { inherit pkgs; }) dimension filterAttrsOnlyRecursive filterDerivations stripAttrsForHydra derivationAggregate; + + # Collects haskell derivations and builds an attrset: + # + # { library = { ... } + # , tests = { ... } + # , benchmarks = { ... } + # , exes = { ... } + # , checks = { ... } + # } + # Where each attribute contains an attribute set + # with all haskell components of that type + mkHaskellDimension = pkgs: haskellProjects: + let + # retrieve all checks from a Haskell package + collectChecks = _: ps: pkgs.haskell-nix.haskellLib.collectChecks' ps; + # retrieve all components of a Haskell package + collectComponents = type: ps: pkgs.haskell-nix.haskellLib.collectComponents' type ps; + # Given a component type and the retrieve function, retrieve components from haskell packages + select = type: selector: (selector type) haskellProjects; + # { component-type : retriever-fn } + attrs = { + "library" = collectComponents; + "tests" = collectComponents; + "benchmarks" = collectComponents; + "exes" = collectComponents; + "checks" = collectChecks; + }; + in + dimension "Haskell component" attrs select; + + ciJobsets = stripAttrsForHydra (filterDerivations { + shell = (import ./shell.nix); + + build = pkgs.recurseIntoAttrs (mkHaskellDimension pkgs projectPackages); + }); +in + ciJobsets // { required = derivationAggregate "required-plutus-starter" ciJobsets; } + diff --git a/MetaLamp/lending-pool/shell.nix b/MetaLamp/lending-pool/shell.nix new file mode 100644 index 000000000..69f0ba40d --- /dev/null +++ b/MetaLamp/lending-pool/shell.nix @@ -0,0 +1,24 @@ +let + packages = import ./.; + inherit (packages) pkgs plutus-starter; + inherit (plutus-starter) haskell; + +in + haskell.project.shellFor { + withHoogle = false; + + nativeBuildInputs = with plutus-starter; [ + hlint + cabal-install + nodejs + purs + spago + purty + fix-purty + haskell-language-server + stylish-haskell + fix-stylish-haskell + pkgs.niv + cardano-repo-tool + ]; + } diff --git a/MetaLamp/lending-pool/src/Plutus/Abstract/ContractResponse.hs b/MetaLamp/lending-pool/src/Plutus/Abstract/ContractResponse.hs index 94fb78572..28b87b51e 100644 --- a/MetaLamp/lending-pool/src/Plutus/Abstract/ContractResponse.hs +++ b/MetaLamp/lending-pool/src/Plutus/Abstract/ContractResponse.hs @@ -66,7 +66,7 @@ instance Monoid (ContractResponse e a) where mappend = (<>) withContractResponse :: forall l a p r s. - HasEndpoint l p s + (HasEndpoint l p s, FromJSON p) => Proxy l -> (a -> r) -> (p -> Contract (ContractResponse Text r) s Text a) diff --git a/MetaLamp/lending-pool/src/Plutus/Abstract/State/Select.hs b/MetaLamp/lending-pool/src/Plutus/Abstract/State/Select.hs index eabb0146a..e85c29670 100644 --- a/MetaLamp/lending-pool/src/Plutus/Abstract/State/Select.hs +++ b/MetaLamp/lending-pool/src/Plutus/Abstract/State/Select.hs @@ -40,7 +40,7 @@ getDatum o = case txOutDatumHash $ txOutTxOut o of Nothing -> throwError "datum has wrong type" Just d -> return d -getState :: (HasBlockchainActions s, PlutusTx.IsData datum) => Address -> Contract w s Text [OutputValue datum] +getState :: (PlutusTx.IsData datum) => Address -> Contract w s Text [OutputValue datum] getState address = do utxos <- utxoAt address traverse getDatum' . Map.toList $ utxos @@ -49,7 +49,7 @@ getState address = do d <- getDatum o pure $ OutputValue oref o d -findOutputsBy :: (HasBlockchainActions s, PlutusTx.IsData datum) => +findOutputsBy :: (PlutusTx.IsData datum) => Address -> AssetClass -> (datum -> Maybe a) -> @@ -61,7 +61,7 @@ findOutputsBy address stateToken mapDatum = mapMaybe checkStateToken <$> getStat then fmap (OutputValue oref outTx) (mapDatum datum) else Nothing -findOutputBy :: (HasBlockchainActions s, PlutusTx.IsData datum) => +findOutputBy :: (PlutusTx.IsData datum) => Address -> AssetClass -> (datum -> Maybe a) -> diff --git a/MetaLamp/lending-pool/src/Plutus/Abstract/State/Update.hs b/MetaLamp/lending-pool/src/Plutus/Abstract/State/Update.hs index b25c0d736..356a047bd 100644 --- a/MetaLamp/lending-pool/src/Plutus/Abstract/State/Update.hs +++ b/MetaLamp/lending-pool/src/Plutus/Abstract/State/Update.hs @@ -86,7 +86,7 @@ data StateHandle scriptType a = StateHandle { } putState :: - (HasBlockchainActions s, IsData (DatumType scriptType), IsData (RedeemerType scriptType)) => + (IsData (DatumType scriptType), IsData (RedeemerType scriptType)) => PutStateHandle scriptType -> StateHandle scriptType a -> a -> @@ -105,7 +105,7 @@ putState PutStateHandle {..} StateHandle{..} newState = do (assetClassValue ownerToken 1) updateState :: - (HasBlockchainActions s, IsData (DatumType scriptType), IsData (RedeemerType scriptType)) => + (IsData (DatumType scriptType), IsData (RedeemerType scriptType)) => Scripts.TypedValidator scriptType -> StateHandle scriptType a -> OutputValue a -> diff --git a/MetaLamp/lending-pool/src/Plutus/Abstract/TxUtils.hs b/MetaLamp/lending-pool/src/Plutus/Abstract/TxUtils.hs index a542e5dbd..05f55d187 100644 --- a/MetaLamp/lending-pool/src/Plutus/Abstract/TxUtils.hs +++ b/MetaLamp/lending-pool/src/Plutus/Abstract/TxUtils.hs @@ -44,7 +44,7 @@ type TxPair a = (Constraints.ScriptLookups a, Constraints.TxConstraints (Redeeme type IsScriptData a = (PlutusTx.IsData (RedeemerType a), PlutusTx.IsData (DatumType a)) -submitTxPair :: (AsContractError e, HasWriteTx s, IsScriptData a) => +submitTxPair :: (AsContractError e, IsScriptData a) => TxPair a -> Contract w s e Tx submitTxPair = Prelude.uncurry submitTxConstraintsWith diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/AToken.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/AToken.hs index 4fb7f21ae..ac1c5c356 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/AToken.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/AToken.hs @@ -45,7 +45,7 @@ import qualified PlutusTx.Semigroup as Semigroup import Prelude (Semigroup (..)) import qualified Prelude -forgeATokensFrom :: forall w s. (HasBlockchainActions s) => Aave -> Reserve -> PubKeyHash -> Integer -> Contract w s Text (TxUtils.TxPair AaveScript) +forgeATokensFrom :: forall w s. Aave -> Reserve -> PubKeyHash -> Integer -> Contract w s Text (TxUtils.TxPair AaveScript) forgeATokensFrom aave reserve pkh amount = do let policy = makeLiquidityPolicy (Core.aaveHash aave) (rCurrency reserve) aTokenAmount = amount -- / rLiquidityIndex reserve -- TODO: how should we divide? @@ -56,7 +56,7 @@ forgeATokensFrom aave reserve pkh amount = do <> (Prelude.mempty, mustPayToPubKey pkh forgeValue) <> TxUtils.mustPayToScript (Core.aaveInstance aave) pkh Core.ReserveFundsDatum payment -burnATokensFrom :: (HasBlockchainActions s) => Aave -> Reserve -> PubKeyHash -> Integer -> Contract w s Text (TxUtils.TxPair AaveScript) +burnATokensFrom :: Aave -> Reserve -> PubKeyHash -> Integer -> Contract w s Text (TxUtils.TxPair AaveScript) burnATokensFrom aave reserve pkh amount = do let asset = rCurrency reserve let userConfigId = (asset, pkh) diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Info.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Info.hs index 54d3b6959..7171142fb 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Info.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Info.hs @@ -62,23 +62,22 @@ import qualified Prelude import Text.Printf (printf) -- | Gets current Lending Pool reserves state -reserves :: HasBlockchainActions s => Aave -> Contract w s Text (AssocMap.Map AssetClass Reserve) +reserves :: Aave -> Contract w s Text (AssocMap.Map AssetClass Reserve) reserves aave = ovValue <$> State.findAaveReserves aave -- | Gets current Lending Pool user configs state -users :: HasBlockchainActions s => Aave -> Contract w s Text (AssocMap.Map (AssetClass, PubKeyHash) UserConfig) +users :: Aave -> Contract w s Text (AssocMap.Map (AssetClass, PubKeyHash) UserConfig) users aave = ovValue <$> State.findAaveUserConfigs aave -fundsAt :: HasBlockchainActions s => PubKeyHash -> Contract w s Text Value +fundsAt :: PubKeyHash -> Contract w s Text Value fundsAt pkh = utxoValue <$> utxoAt (pubKeyHashAddress pkh) -- | Gets all UTxOs belonging to the Lending Pool script and concats them into one Value -poolFunds :: HasBlockchainActions s => Aave -> Contract w s Text Value +poolFunds :: Aave -> Contract w s Text Value poolFunds aave = utxoValue <$> utxoAt (Core.aaveAddress aave) type AaveInfoSchema = - BlockchainActions - .\/ Endpoint "fundsAt" PubKeyHash + Endpoint "fundsAt" PubKeyHash .\/ Endpoint "poolFunds" () .\/ Endpoint "reserves" () .\/ Endpoint "users" () diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Owner.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Owner.hs index ca2cb309f..7a8dc406d 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Owner.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/Owner.hs @@ -88,14 +88,14 @@ createReserve aave CreateParams {..} = } -- | Starts the Lending Pool protocol: minting pool NFTs, creating empty user configuration state and all specified liquidity reserves -start :: HasBlockchainActions s => [CreateParams] -> Contract w s Text Aave +start :: [CreateParams] -> Contract w s Text Aave start = start' $ do pkh <- pubKeyHash <$> ownPubKey fmap Currency.currencySymbol $ mapError (pack . show @Currency.CurrencyError) $ Currency.forgeContract pkh [(Core.aaveProtocolName, 1)] -start' :: HasBlockchainActions s => Contract w s Text CurrencySymbol -> [CreateParams] -> Contract w s Text Aave +start' :: Contract w s Text CurrencySymbol -> [CreateParams] -> Contract w s Text Aave start' getAaveToken params = do aaveToken <- getAaveToken pkh <- pubKeyHash <$> ownPubKey @@ -118,8 +118,7 @@ start' getAaveToken params = do pure aave type AaveOwnerSchema = - BlockchainActions - .\/ Endpoint "start" [CreateParams] + Endpoint "start" [CreateParams] data OwnerContractState = Started Aave deriving (Prelude.Eq, Show, Generic, FromJSON, ToJSON) diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/State.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/State.hs index 4772d939a..7b53bb1c5 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/State.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/State.hs @@ -55,36 +55,36 @@ import Prelude (Semigroup (..), fmap) import qualified Prelude -findOutputsBy :: HasBlockchainActions s => Aave -> AssetClass -> (AaveDatum -> Maybe a) -> Contract w s Text [OutputValue a] +findOutputsBy :: Aave -> AssetClass -> (AaveDatum -> Maybe a) -> Contract w s Text [OutputValue a] findOutputsBy aave = State.findOutputsBy (Core.aaveAddress aave) -findOutputBy :: HasBlockchainActions s => Aave -> AssetClass -> (AaveDatum -> Maybe a) -> Contract w s Text (OutputValue a) +findOutputBy :: Aave -> AssetClass -> (AaveDatum -> Maybe a) -> Contract w s Text (OutputValue a) findOutputBy aave = State.findOutputBy (Core.aaveAddress aave) -findAaveOwnerToken :: HasBlockchainActions s => Aave -> Contract w s Text (OutputValue PubKeyHash) +findAaveOwnerToken :: Aave -> Contract w s Text (OutputValue PubKeyHash) findAaveOwnerToken aave@Aave{..} = findOutputBy aave aaveProtocolInst (^? Core._LendingPoolDatum) reserveStateToken, userStateToken :: Aave -> AssetClass reserveStateToken aave = State.makeStateToken (Core.aaveHash aave) (aaveProtocolInst aave) "aaveReserve" userStateToken aave = State.makeStateToken (Core.aaveHash aave) (aaveProtocolInst aave) "aaveUser" -findAaveReserves :: HasBlockchainActions s => Aave -> Contract w s Text (OutputValue (AssocMap.Map AssetClass Reserve)) +findAaveReserves :: Aave -> Contract w s Text (OutputValue (AssocMap.Map AssetClass Reserve)) findAaveReserves aave = findOutputBy aave (reserveStateToken aave) (^? Core._ReservesDatum . _2) -findAaveReserve :: HasBlockchainActions s => Aave -> AssetClass -> Contract w s Text Reserve +findAaveReserve :: Aave -> AssetClass -> Contract w s Text Reserve findAaveReserve aave reserveId = do reserves <- ovValue <$> findAaveReserves aave maybe (throwError "Reserve not found") pure $ AssocMap.lookup reserveId reserves -findAaveUserConfigs :: HasBlockchainActions s => Aave -> Contract w s Text (OutputValue (AssocMap.Map UserConfigId UserConfig)) +findAaveUserConfigs :: Aave -> Contract w s Text (OutputValue (AssocMap.Map UserConfigId UserConfig)) findAaveUserConfigs aave = findOutputBy aave (userStateToken aave) (^? Core._UserConfigsDatum . _2) -findAaveUserConfig :: HasBlockchainActions s => Aave -> UserConfigId -> Contract w s Text UserConfig +findAaveUserConfig :: Aave -> UserConfigId -> Contract w s Text UserConfig findAaveUserConfig aave userConfigId = do configs <- ovValue <$> findAaveUserConfigs aave maybe (throwError "UserConfig not found") pure $ AssocMap.lookup userConfigId configs -putState :: (HasBlockchainActions s) => Aave -> StateHandle AaveScript a -> a -> Contract w s Text (TxUtils.TxPair AaveScript) +putState :: Aave -> StateHandle AaveScript a -> a -> Contract w s Text (TxUtils.TxPair AaveScript) putState aave stateHandle newState = do ownerTokenOutput <- fmap Core.LendingPoolDatum <$> findAaveOwnerToken aave State.putState @@ -92,7 +92,7 @@ putState aave stateHandle newState = do stateHandle newState -updateState :: (HasBlockchainActions s) => Aave -> StateHandle AaveScript a -> OutputValue a -> Contract w s Text (TxUtils.TxPair AaveScript, a) +updateState :: Aave -> StateHandle AaveScript a -> OutputValue a -> Contract w s Text (TxUtils.TxPair AaveScript, a) updateState aave = State.updateState (Core.aaveInstance aave) makeReserveHandle :: Aave -> (AssocMap.Map AssetClass Reserve -> AaveRedeemer) -> StateHandle AaveScript (AssocMap.Map AssetClass Reserve) @@ -104,20 +104,20 @@ makeReserveHandle aave toRedeemer = toRedeemer = toRedeemer } -putReserves :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> AssocMap.Map AssetClass Reserve -> Contract w s Text (TxUtils.TxPair AaveScript) +putReserves :: Aave -> AaveRedeemer -> AssocMap.Map AssetClass Reserve -> Contract w s Text (TxUtils.TxPair AaveScript) putReserves aave redeemer = putState aave $ makeReserveHandle aave (const redeemer) -updateReserves :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> OutputValue (AssocMap.Map AssetClass Reserve) -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map AssetClass Reserve) +updateReserves :: Aave -> AaveRedeemer -> OutputValue (AssocMap.Map AssetClass Reserve) -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map AssetClass Reserve) updateReserves aave redeemer = updateState aave $ makeReserveHandle aave (const redeemer) -updateReserve :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> AssetClass -> Reserve -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map AssetClass Reserve) +updateReserve :: Aave -> AaveRedeemer -> AssetClass -> Reserve -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map AssetClass Reserve) updateReserve aave redeemer reserveId reserve = do reservesOutput <- findAaveReserves aave _ <- maybe (throwError "Update failed: reserve not found") pure $ AssocMap.lookup reserveId (ovValue reservesOutput) updateReserves aave redeemer $ Prelude.fmap (AssocMap.insert reserveId reserve) reservesOutput -roundtripReserves :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> Contract w s Text (TxUtils.TxPair AaveScript) +roundtripReserves :: Aave -> AaveRedeemer -> Contract w s Text (TxUtils.TxPair AaveScript) roundtripReserves aave redeemer = do reservesOutput <- findAaveReserves aave fst <$> updateReserves aave redeemer reservesOutput @@ -131,20 +131,20 @@ makeUserHandle aave toRedeemer = toRedeemer = toRedeemer } -putUserConfigs :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> AssocMap.Map UserConfigId UserConfig -> Contract w s Text (TxUtils.TxPair AaveScript) +putUserConfigs :: Aave -> AaveRedeemer -> AssocMap.Map UserConfigId UserConfig -> Contract w s Text (TxUtils.TxPair AaveScript) putUserConfigs aave redeemer = putState aave $ makeUserHandle aave (const redeemer) -updateUserConfigs :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> OutputValue (AssocMap.Map UserConfigId UserConfig) -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map UserConfigId UserConfig) +updateUserConfigs :: Aave -> AaveRedeemer -> OutputValue (AssocMap.Map UserConfigId UserConfig) -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map UserConfigId UserConfig) updateUserConfigs aave redeemer = updateState aave $ makeUserHandle aave (const redeemer) -addUserConfig :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> UserConfigId -> UserConfig -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map UserConfigId UserConfig) +addUserConfig :: Aave -> AaveRedeemer -> UserConfigId -> UserConfig -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map UserConfigId UserConfig) addUserConfig aave redeemer userConfigId userConfig = do configsOutput <- findAaveUserConfigs aave _ <- maybe (pure ()) (const $ throwError "Add user config failed: config exists") $ AssocMap.lookup userConfigId (ovValue configsOutput) updateUserConfigs aave redeemer $ Prelude.fmap (AssocMap.insert userConfigId userConfig) configsOutput -updateUserConfig :: (HasBlockchainActions s) => Aave -> AaveRedeemer -> UserConfigId -> UserConfig -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map UserConfigId UserConfig) +updateUserConfig :: Aave -> AaveRedeemer -> UserConfigId -> UserConfig -> Contract w s Text (TxUtils.TxPair AaveScript, AssocMap.Map UserConfigId UserConfig) updateUserConfig aave redeemer userConfigId userConfig = do configsOutput <- findAaveUserConfigs aave _ <- maybe (throwError "Update failed: user config not found") pure $ diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/User.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/User.hs index b2c97dc9b..7bd81b162 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/User.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OffChain/User.hs @@ -80,7 +80,7 @@ PlutusTx.unstableMakeIsData ''DepositParams PlutusTx.makeLift ''DepositParams -- | The user puts N amount of his asset into a corresponding reserve, in exchange he gets N equivalent aTokens -deposit :: (HasBlockchainActions s) => Aave -> DepositParams -> Contract w s Text () +deposit :: Aave -> DepositParams -> Contract w s Text () deposit aave DepositParams {..} = do reserve <- State.findAaveReserve aave dpAsset forgeTx <- AToken.forgeATokensFrom aave reserve dpOnBehalfOf dpAmount @@ -117,7 +117,7 @@ PlutusTx.unstableMakeIsData ''WithdrawParams PlutusTx.makeLift ''WithdrawParams -- | The user withdraws N amount of a specific asset from the corresponding reserve, N aTokens are taken from his wallet and burned -withdraw :: (HasBlockchainActions s) => Aave -> WithdrawParams -> Contract w s Text () +withdraw :: Aave -> WithdrawParams -> Contract w s Text () withdraw aave WithdrawParams {..} = do reserve <- State.findAaveReserve aave wpAsset let userConfigId = (wpAsset, wpUser) @@ -143,7 +143,7 @@ PlutusTx.unstableMakeIsData ''BorrowParams PlutusTx.makeLift ''BorrowParams -- | The user borrows N amount of a needed asset from the corresponding reserve, his debt entry state is encreased by N -borrow :: (HasBlockchainActions s) => Aave -> BorrowParams -> Contract w s Text () +borrow :: Aave -> BorrowParams -> Contract w s Text () borrow aave BorrowParams {..} = do reserves <- ovValue <$> State.findAaveReserves aave reserve <- maybe (throwError "Reserve not found") pure $ AssocMap.lookup bpAsset reserves @@ -207,7 +207,7 @@ PlutusTx.unstableMakeIsData ''RepayParams PlutusTx.makeLift ''RepayParams -- | The user repays N amount of a specific asset to the corresponding reserve, his debt entry state is decreased by N -repay :: (HasBlockchainActions s) => Aave -> RepayParams -> Contract w s Text () +repay :: Aave -> RepayParams -> Contract w s Text () repay aave RepayParams {..} = do reserve <- State.findAaveReserve aave rpAsset @@ -242,14 +242,14 @@ PlutusTx.unstableMakeIsData ''ProvideCollateralParams PlutusTx.makeLift ''ProvideCollateralParams -- | Gets all UTxOs belonging to a user and concats them into one Value -fundsAt :: HasBlockchainActions s => PubKeyHash -> Contract w s Text Value +fundsAt :: PubKeyHash -> Contract w s Text Value fundsAt pkh = utxoValue <$> utxoAt (pubKeyHashAddress pkh) -balanceAt :: HasBlockchainActions s => PubKeyHash -> AssetClass -> Contract w s Text Integer +balanceAt :: PubKeyHash -> AssetClass -> Contract w s Text Integer balanceAt pkh asset = flip assetClassValueOf asset <$> fundsAt pkh -- | User deposits N amount of aToken as collateral, his investment entry state is increased by N -provideCollateral :: (HasBlockchainActions s) => Aave -> ProvideCollateralParams -> Contract w s Text () +provideCollateral :: Aave -> ProvideCollateralParams -> Contract w s Text () provideCollateral aave ProvideCollateralParams {..} = do reserve <- State.findAaveReserve aave pcpUnderlyingAsset @@ -291,7 +291,7 @@ PlutusTx.unstableMakeIsData ''RevokeCollateralParams PlutusTx.makeLift ''RevokeCollateralParams -- | User withdraws N amount of collateralized aToken, his investment entry state is decreased by N -revokeCollateral :: (HasBlockchainActions s) => Aave -> RevokeCollateralParams -> Contract w s Text () +revokeCollateral :: Aave -> RevokeCollateralParams -> Contract w s Text () revokeCollateral aave RevokeCollateralParams {..} = do reserves <- ovValue <$> State.findAaveReserves aave reserve <- maybe (throwError "Reserve not found") pure $ AssocMap.lookup rcpUnderlyingAsset reserves @@ -334,22 +334,21 @@ revokeCollateral aave RevokeCollateralParams {..} = do getUsersCollateral asset tx = ((> 0) . flip assetClassValueOf asset . txOutValue . txOutTxOut $ tx) && (txOutDatumHash . txOutTxOut $ tx) == Just (datumHash . Datum . PlutusTx.toData $ userDatum asset) -getOwnPubKey :: HasBlockchainActions s => Contract w s Text PubKeyHash +getOwnPubKey :: Contract w s Text PubKeyHash getOwnPubKey = pubKeyHash <$> ownPubKey -ownPubKeyBalance :: HasBlockchainActions s => Contract w s Text Value +ownPubKeyBalance :: Contract w s Text Value ownPubKeyBalance = getOwnPubKey >>= fundsAt type AaveUserSchema = - BlockchainActions - .\/ Endpoint "deposit" DepositParams - .\/ Endpoint "withdraw" WithdrawParams - .\/ Endpoint "borrow" BorrowParams - .\/ Endpoint "repay" RepayParams - .\/ Endpoint "provideCollateral" ProvideCollateralParams - .\/ Endpoint "revokeCollateral" RevokeCollateralParams - .\/ Endpoint "ownPubKey" () - .\/ Endpoint "ownPubKeyBalance" () + Endpoint "deposit" DepositParams + .\/ Endpoint "withdraw" WithdrawParams + .\/ Endpoint "borrow" BorrowParams + .\/ Endpoint "repay" RepayParams + .\/ Endpoint "provideCollateral" ProvideCollateralParams + .\/ Endpoint "revokeCollateral" RevokeCollateralParams + .\/ Endpoint "ownPubKey" () + .\/ Endpoint "ownPubKeyBalance" () data UserContractState = Deposited diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OnChain/Core/Script.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OnChain/Core/Script.hs index 4cca7c6db..e6ff63139 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OnChain/Core/Script.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/LendingPool/OnChain/Core/Script.hs @@ -50,8 +50,6 @@ import PlutusTx.Prelude hiding (Semigroup (..), import Prelude (Semigroup (..)) import qualified Prelude -deriving anyclass instance ToSchema Rational - data Reserve = Reserve { rCurrency :: AssetClass, -- reserve id rAToken :: AssetClass, diff --git a/MetaLamp/lending-pool/src/Plutus/Contracts/Service/Oracle.hs b/MetaLamp/lending-pool/src/Plutus/Contracts/Service/Oracle.hs index 438ae2c4e..35026434f 100644 --- a/MetaLamp/lending-pool/src/Plutus/Contracts/Service/Oracle.hs +++ b/MetaLamp/lending-pool/src/Plutus/Contracts/Service/Oracle.hs @@ -181,7 +181,7 @@ data OracleParams = OracleParams deriving stock (Prelude.Eq, Prelude.Show, Generic) deriving anyclass (ToJSON, FromJSON, ToSchema) -startOracle :: forall w s. HasBlockchainActions s => OracleParams -> Contract w s Text Oracle +startOracle :: forall w s. OracleParams -> Contract w s Text Oracle startOracle op = do pkh <- pubKeyHash <$> Contract.ownPubKey osc <- mapError (pack . Prelude.show) (forgeContract pkh [(oracleTokenName, 1)] :: Contract w s CurrencyError OneShotCurrency) @@ -195,7 +195,7 @@ startOracle op = do logInfo @Prelude.String $ "started oracle " ++ Prelude.show oracle return oracle -updateOracle :: forall w s. HasBlockchainActions s => Oracle -> Integer -> Contract w s Text () +updateOracle :: forall w s. Oracle -> Integer -> Contract w s Text () updateOracle oracle x = do m <- findOracle oracle let c = Constraints.mustPayToTheScript x $ assetClassValue (oracleAsset oracle) 1 @@ -213,7 +213,7 @@ updateOracle oracle x = do awaitTxConfirmed $ txId ledgerTx logInfo @Prelude.String $ "updated oracle value to " ++ Prelude.show x -findOracle :: forall w s. HasBlockchainActions s => Oracle -> Contract w s Text (Maybe (TxOutRef, TxOutTx, Integer)) +findOracle :: forall w s. Oracle -> Contract w s Text (Maybe (TxOutRef, TxOutTx, Integer)) findOracle oracle = do utxos <- Map.filter f <$> utxoAt (oracleAddress oracle) return $ case Map.toList utxos of @@ -227,7 +227,7 @@ findOracle oracle = do useOracle :: forall a w s. - ( HasBlockchainActions s, TxUtils.IsScriptData a + ( TxUtils.IsScriptData a ) => (CurrencySymbol, PubKeyHash, Integer, AssetClass) -> Contract w s Text (TxUtils.TxPair a) @@ -244,7 +244,7 @@ useOracle (fromTuple -> oracle) = do where oracleCoin = oracleAsset oracle -type OracleSchema = BlockchainActions .\/ Endpoint "update" Integer +type OracleSchema = Endpoint "update" Integer runOracle :: OracleParams -> Contract (Last Oracle) OracleSchema Text () runOracle op = do diff --git a/MetaLamp/lending-pool/src/Plutus/PAB/Simulation.hs b/MetaLamp/lending-pool/src/Plutus/PAB/Simulation.hs index 3d4a129d4..868619e75 100644 --- a/MetaLamp/lending-pool/src/Plutus/PAB/Simulation.hs +++ b/MetaLamp/lending-pool/src/Plutus/PAB/Simulation.hs @@ -85,7 +85,7 @@ toAsset tokenName = distributeFunds :: [Wallet] -> [AssetClass] -> - Contract () BlockchainActions Text () + Contract () EmptySchema Text () distributeFunds wallets assets = do ownPK <- pubKeyHash <$> ownPubKey let testCurrenciesValue = mconcat $ fmap (`assetClassValue` 1000) assets @@ -104,7 +104,7 @@ distributeFunds wallets assets = do createOracles :: [AssetClass] -> - Contract (Monoid.Last [Oracle.Oracle]) BlockchainActions Text () + Contract (Monoid.Last [Oracle.Oracle]) EmptySchema Text () createOracles assets = do oracles <- forM assets $ \asset -> do let oracleParams = Oracle.OracleParams @@ -273,11 +273,11 @@ handleAaveContract :: ~> Eff effs handleAaveContract = Builtin.handleBuiltin getSchema getContract where getSchema = \case - AaveUser _ -> Builtin.endpointsToSchemas @(Aave.AaveUserSchema .\\ BlockchainActions) - AaveInfo _ -> Builtin.endpointsToSchemas @(Aave.AaveInfoSchema .\\ BlockchainActions) - AaveStart -> Builtin.endpointsToSchemas @(Aave.AaveOwnerSchema .\\ BlockchainActions) - DistributeFunds _ _ -> Builtin.endpointsToSchemas @Empty - CreateOracles _ -> Builtin.endpointsToSchemas @Empty + AaveUser _ -> Builtin.endpointsToSchemas @Aave.AaveUserSchema + AaveInfo _ -> Builtin.endpointsToSchemas @Aave.AaveInfoSchema + AaveStart -> Builtin.endpointsToSchemas @Aave.AaveOwnerSchema + DistributeFunds _ _ -> Builtin.endpointsToSchemas @Empty + CreateOracles _ -> Builtin.endpointsToSchemas @Empty getContract = \case AaveInfo aave -> SomeBuiltin $ Aave.infoEndpoints aave AaveUser aave -> SomeBuiltin $ Aave.userEndpoints aave diff --git a/MetaLamp/lending-pool/test/Fixtures/Init.hs b/MetaLamp/lending-pool/test/Fixtures/Init.hs index 85742b794..7b66213a1 100644 --- a/MetaLamp/lending-pool/test/Fixtures/Init.hs +++ b/MetaLamp/lending-pool/test/Fixtures/Init.hs @@ -70,7 +70,7 @@ startTrace = do _ <- Trace.waitNSlots 5 pure () -startOracles :: Contract () BlockchainActions Text () +startOracles :: Contract () EmptySchema Text () startOracles = forM_ oracles (\oracle -> do _ <- forgeSymbol Oracle.oracleTokenName diff --git a/MetaLamp/lending-pool/test/Fixtures/Symbol.hs b/MetaLamp/lending-pool/test/Fixtures/Symbol.hs index f765c3f74..f6737d7fc 100644 --- a/MetaLamp/lending-pool/test/Fixtures/Symbol.hs +++ b/MetaLamp/lending-pool/test/Fixtures/Symbol.hs @@ -34,7 +34,7 @@ makePolicy tokenName = Scripts.mkMonetaryPolicyScript $ getSymbol :: TokenName -> CurrencySymbol getSymbol = Ledger.scriptCurrencySymbol . makePolicy -forgeSymbol :: HasBlockchainActions s => TokenName -> Contract () s Text CurrencySymbol +forgeSymbol :: TokenName -> Contract () s Text CurrencySymbol forgeSymbol tokenName = do pkh <- Ledger.pubKeyHash <$> ownPubKey let symbol = getSymbol tokenName diff --git a/MetaLamp/lending-pool/test/Utils/Trace.hs b/MetaLamp/lending-pool/test/Utils/Trace.hs index 603219669..e7de24026 100644 --- a/MetaLamp/lending-pool/test/Utils/Trace.hs +++ b/MetaLamp/lending-pool/test/Utils/Trace.hs @@ -20,7 +20,6 @@ import Ledger (Address) import qualified Ledger import Ledger.AddressMap (UtxoMap) import Plutus.Abstract.ContractResponse (ContractResponse (..)) -import Plutus.Contract (HasBlockchainActions) import Plutus.Contract.Test (TracePredicate) import qualified Plutus.Trace.Emulator as Trace import Plutus.Trace.Emulator.Types (EmulatorRuntimeError (..)) @@ -31,7 +30,6 @@ import Wallet.Emulator.MultiAgent (EmulatorEvent) getState :: (Show a , Show e - , HasBlockchainActions s , Trace.ContractConstraints s , JSON.FromJSON e , JSON.FromJSON a @@ -47,7 +45,7 @@ getState pick userHandle = do case res of ContractSuccess s -> maybe (throwError . GenericError $ "Unexpected state: " <> show s) pure (pick s) ContractError e -> throwError . GenericError . show $ e - s -> throwError . JSONDecodingError $ "Unexpected state: " <> show s + s -> throwError $ EmulatorJSONDecodingError ("Unexpected state: " <> show s) (JSON.toJSON s) utxoAtAddress :: Monad m => Address -> (UtxoMap -> m c)-> L.FoldM m EmulatorEvent c utxoAtAddress address check = Folds.postMapM check (L.generalize $ Folds.utxoAtAddress address)