diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..537c860 --- /dev/null +++ b/.npmignore @@ -0,0 +1,15 @@ +.github +.psc-ide-port +.spago +.spago2nix +dist +exe +flake.lock +Makefile +node_modules +output +src +test +*purs +*.nix +*.dhall \ No newline at end of file diff --git a/.output.js.swm b/.output.js.swm new file mode 100644 index 0000000..7ffa410 Binary files /dev/null and b/.output.js.swm differ diff --git a/.output.js.swn b/.output.js.swn new file mode 100644 index 0000000..f2f9018 Binary files /dev/null and b/.output.js.swn differ diff --git a/.output.js.swo b/.output.js.swo new file mode 100644 index 0000000..4254023 Binary files /dev/null and b/.output.js.swo differ diff --git a/.output.js.swp b/.output.js.swp new file mode 100644 index 0000000..6b5d882 Binary files /dev/null and b/.output.js.swp differ diff --git a/Makefile b/Makefile index b6cdd1e..192930d 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ SHELL := bash .SHELLFLAGS := -eu -o pipefail -c ps-sources := $(shell fd -epurs) -ps-entrypoint := Main +ps-entrypoint := Seabug ps-bundle = spago bundle-module -m ${ps-entrypoint} --to output.js run-dev: diff --git a/README.md b/README.md index d857380..4fd2f59 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,32 @@ # seabug-contracts -TODO +A library for interacting with Seabug smart contracts via the Cardano Transaction Lib (CTL). + +## Tests + +Use `spago test` to run the tests. Something like `nix build .#checks..seabug-contracts` can also be used, where `` is something like `x86_64-linux`. + +## Minting + +The minting process currently requires some manual steps. To mint a new NFT: + +- Upload a new image to nft.storage (e.g. using `seabug/scripts/mint-nft.sh`) +- Uncomment [this line](https://github.com/mlabs-haskell/seabug-contracts/blob/cda88824f87e0b961b738c66a428b7ade77454be/index.js#L39) +- Update the image info [here](https://github.com/mlabs-haskell/seabug-contracts/blob/cda88824f87e0b961b738c66a428b7ade77454be/src/Seabug/Seabug.purs#L34) + - Make sure you're using the base36 encoded CID (`mint-nft.sh` prints this out) +- Run `make run-dev` and open the link from the console in chrome; this will trigger the minting + - If Nami/Gero are giving you trouble, this snippet can be used to use a key wallet instead: + ``` + privateKey <- liftM (error "Failed to parse private key") $ + privateKeyFromBytes + =<< hexToRawBytes "" + privateStakeKey <- liftM (error "Failed to parse private stake key") + $ privateKeyFromBytes + =<< hexToRawBytes "" + let wallet = Just $ mkKeyWallet (wrap privateKey) (Just $ wrap privateStakeKey) + ``` + - The secret key can be obtained through e.g. `seabug/scripts/prepare-wallet.sh` (make sure to add ada to that wallet) + - Note you may have to remove the "5820" from the start of the "cborHex" in the skey file + - The stake key will also be necessary for minting, the command `cardano-cli stake-address key-gen --signing-key-file stake.skey --verification-key-file stake.vkey` can be used to get a stake key +- Add the wallet that you minted with as an artist to the + `nft-marketplace-server` database with `admin/create_artist` diff --git a/exe/Main.purs b/exe/Main.purs index 4df387c..fe19108 100644 --- a/exe/Main.purs +++ b/exe/Main.purs @@ -3,12 +3,12 @@ module Main (main) where import Contract.Prelude import Contract.Address (ownPaymentPubKeyHash) -import Contract.Monad (defaultContractConfig, runContract_) +import Contract.Monad (defaultTestnetContractConfig, runContract_) import Effect.Aff (launchAff_) main :: Effect Unit main = launchAff_ $ do - cfg <- defaultContractConfig + cfg <- defaultTestnetContractConfig runContract_ cfg $ log <<< show diff --git a/flake.lock b/flake.lock index 34725f7..b3cd831 100644 --- a/flake.lock +++ b/flake.lock @@ -32,22 +32,6 @@ "type": "github" } }, - "HTTP_3": { - "flake": false, - "locked": { - "lastModified": 1451647621, - "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", - "owner": "phadej", - "repo": "HTTP", - "rev": "9bc0996d412fef1787449d841277ef663ad9a915", - "type": "github" - }, - "original": { - "owner": "phadej", - "repo": "HTTP", - "type": "github" - } - }, "Win32-network": { "flake": false, "locked": { @@ -83,23 +67,6 @@ } }, "cabal-32": { - "flake": false, - "locked": { - "lastModified": 1603716527, - "narHash": "sha256-sDbrmur9Zfp4mPKohCD8IDZfXJ0Tjxpmr2R+kg5PpSY=", - "owner": "haskell", - "repo": "cabal", - "rev": "94aaa8e4720081f9c75497e2735b90f6a819b08e", - "type": "github" - }, - "original": { - "owner": "haskell", - "ref": "3.2", - "repo": "cabal", - "type": "github" - } - }, - "cabal-32_2": { "flake": false, "locked": { "lastModified": 1603716527, @@ -116,7 +83,7 @@ "type": "github" } }, - "cabal-32_3": { + "cabal-32_2": { "flake": false, "locked": { "lastModified": 1603716527, @@ -134,23 +101,6 @@ } }, "cabal-34": { - "flake": false, - "locked": { - "lastModified": 1622475795, - "narHash": "sha256-chwTL304Cav+7p38d9mcb+egABWmxo2Aq+xgVBgEb/U=", - "owner": "haskell", - "repo": "cabal", - "rev": "b086c1995cdd616fc8d91f46a21e905cc50a1049", - "type": "github" - }, - "original": { - "owner": "haskell", - "ref": "3.4", - "repo": "cabal", - "type": "github" - } - }, - "cabal-34_2": { "flake": false, "locked": { "lastModified": 1640353650, @@ -167,7 +117,7 @@ "type": "github" } }, - "cabal-34_3": { + "cabal-34_2": { "flake": false, "locked": { "lastModified": 1640353650, @@ -255,17 +205,17 @@ "cardano-base_2": { "flake": false, "locked": { - "lastModified": 1635841753, - "narHash": "sha256-OXKsJ1UTj5kJ9xaThM54ZmxFAiFINTPKd4JQa4dPmEU=", + "lastModified": 1654537609, + "narHash": "sha256-4b0keLjRaVSdEwfBXB1iT3QPlsutdxSltGfBufT4Clw=", "owner": "input-output-hk", "repo": "cardano-base", - "rev": "41545ba3ac6b3095966316a99883d678b5ab8da8", + "rev": "0f3a867493059e650cda69e20a5cbf1ace289a57", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-base", - "rev": "41545ba3ac6b3095966316a99883d678b5ab8da8", + "rev": "0f3a867493059e650cda69e20a5cbf1ace289a57", "type": "github" } }, @@ -289,11 +239,11 @@ "cardano-configurations": { "flake": false, "locked": { - "lastModified": 1634002394, - "narHash": "sha256-yqw88AbBjBa0VDwXz04+1gV3zXYAaS+/1PNowwmrsJ8=", + "lastModified": 1655361562, + "narHash": "sha256-b/z5RSgqTMQpEUSD4nbrBAr86PcQs+n6EMtn/YPeyj4=", "owner": "input-output-hk", "repo": "cardano-configurations", - "rev": "26b6b6de73f90e4777602b372798bf77addcc321", + "rev": "08e6c0572d5d48049fab521995b29607e0a91a9e", "type": "github" }, "original": { @@ -356,17 +306,17 @@ "cardano-ledger_2": { "flake": false, "locked": { - "lastModified": 1639498285, - "narHash": "sha256-lRNfkGMHnpPO0T19FZY5BnuRkr0zTRZIkxZVgHH0fys=", + "lastModified": 1655762257, + "narHash": "sha256-SaMhULHXgY0FiSKWc2dAYlgtbfPaFh/bUTgGqoNnMqY=", "owner": "input-output-hk", "repo": "cardano-ledger", - "rev": "1a9ec4ae9e0b09d54e49b2a40c4ead37edadcce5", + "rev": "ce3057e0863304ccb3f79d78c77136219dc786c6", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-ledger", - "rev": "1a9ec4ae9e0b09d54e49b2a40c4ead37edadcce5", + "rev": "ce3057e0863304ccb3f79d78c77136219dc786c6", "type": "github" } }, @@ -387,48 +337,20 @@ "type": "github" } }, - "cardano-node-exe": { - "inputs": { - "customConfig": "customConfig", - "haskellNix": "haskellNix", - "iohkNix": "iohkNix", - "nixpkgs": [ - "cardano-transaction-lib", - "cardano-node-exe", - "haskellNix", - "nixpkgs-2105" - ], - "utils": "utils" - }, - "locked": { - "lastModified": 1631803678, - "narHash": "sha256-8BFI16sQGE+ltlA7LcDnh/9V8xjuKcTUd09FyPs1p94=", - "owner": "input-output-hk", - "repo": "cardano-node", - "rev": "ea8b632820db5546b22430bbb5ed8db4a2fef7dd", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "cardano-node", - "rev": "ea8b632820db5546b22430bbb5ed8db4a2fef7dd", - "type": "github" - } - }, "cardano-node_2": { "flake": false, "locked": { - "lastModified": 1640022647, - "narHash": "sha256-M+YnF7Zj/7QK2pu0T75xNVaX0eEeijtBH8yz+jEHIMM=", + "lastModified": 1656166930, + "narHash": "sha256-R7YGQ6UMG16ed9sGguDWq2cUgFnADeRdx8O2s2HqWRk=", "owner": "input-output-hk", "repo": "cardano-node", - "rev": "814df2c146f5d56f8c35a681fe75e85b905aed5d", + "rev": "9f1d7dc163ee66410d912e48509d6a2300cfa68a", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "cardano-node", - "rev": "814df2c146f5d56f8c35a681fe75e85b905aed5d", + "rev": "9f1d7dc163ee66410d912e48509d6a2300cfa68a", "type": "github" } }, @@ -498,22 +420,6 @@ "type": "github" } }, - "cardano-shell_3": { - "flake": false, - "locked": { - "lastModified": 1608537748, - "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", - "owner": "input-output-hk", - "repo": "cardano-shell", - "rev": "9392c75087cb9a3d453998f4230930dea3a95725", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "cardano-shell", - "type": "github" - } - }, "cardano-transaction-lib": { "inputs": { "Win32-network": "Win32-network", @@ -524,11 +430,11 @@ "cardano-crypto": "cardano-crypto", "cardano-ledger": "cardano-ledger", "cardano-node": "cardano-node", - "cardano-node-exe": "cardano-node-exe", "cardano-prelude": "cardano-prelude", "cardano-wallet": "cardano-wallet", "easy-purescript-nix": "easy-purescript-nix", "ekg-forward": "ekg-forward", + "flake-compat": "flake-compat", "flat": "flat", "goblins": "goblins", "haskell-nix": "haskell-nix", @@ -541,24 +447,24 @@ ], "ogmios": "ogmios", "ogmios-datum-cache": "ogmios-datum-cache", - "optparse-applicative": "optparse-applicative", + "optparse-applicative": "optparse-applicative_2", "ouroboros-network": "ouroboros-network_2", "plutus": "plutus_2", "purescript-bridge": "purescript-bridge", "servant-purescript": "servant-purescript" }, "locked": { - "lastModified": 1651223750, - "narHash": "sha256-7wvFP7D4itWFNTsUVZMR3sX6i6Zsp0Ko347opAQlZck=", + "lastModified": 1658177328, + "narHash": "sha256-UFAIFcPN7xp85VzYkkU/hJQpN7+Y6qO/BUh/xa3HZTs=", "owner": "Plutonomicon", "repo": "cardano-transaction-lib", - "rev": "a83d75e852571e6a8ad2e60c449f198e1b3270a2", + "rev": "32194c502e4a068bf99388b05c708f81612d7541", "type": "github" }, "original": { "owner": "Plutonomicon", "repo": "cardano-transaction-lib", - "rev": "a83d75e852571e6a8ad2e60c449f198e1b3270a2", + "rev": "32194c502e4a068bf99388b05c708f81612d7541", "type": "github" } }, @@ -579,21 +485,6 @@ "type": "github" } }, - "customConfig": { - "locked": { - "lastModified": 1630400035, - "narHash": "sha256-MWaVOCzuFwp09wZIW9iHq5wWen5C69I940N1swZLEQ0=", - "owner": "input-output-hk", - "repo": "empty-flake", - "rev": "2040a05b67bf9a669ce17eca56beb14b4206a99a", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "empty-flake", - "type": "github" - } - }, "easy-purescript-nix": { "flake": false, "locked": { @@ -627,7 +518,40 @@ "type": "github" } }, + "ekg-json": { + "flake": false, + "locked": { + "lastModified": 1642583945, + "narHash": "sha256-VT8Ur585TCn03P2TVi6t92v2Z6tl8vKijICjse6ocv8=", + "owner": "vshabanov", + "repo": "ekg-json", + "rev": "00ebe7211c981686e65730b7144fbf5350462608", + "type": "github" + }, + "original": { + "owner": "vshabanov", + "repo": "ekg-json", + "rev": "00ebe7211c981686e65730b7144fbf5350462608", + "type": "github" + } + }, "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { "flake": false, "locked": { "lastModified": 1641205782, @@ -643,7 +567,7 @@ "type": "github" } }, - "flake-compat_2": { + "flake-compat_3": { "flake": false, "locked": { "lastModified": 1650374568, @@ -659,22 +583,23 @@ "type": "github" } }, - "flake-utils": { + "flake-compat_4": { + "flake": false, "locked": { - "lastModified": 1623875721, - "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "edolstra", + "repo": "flake-compat", "type": "github" } }, - "flake-utils_2": { + "flake-utils": { "locked": { "lastModified": 1644229661, "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", @@ -689,7 +614,7 @@ "type": "github" } }, - "flake-utils_3": { + "flake-utils_2": { "locked": { "lastModified": 1644229661, "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", @@ -772,23 +697,6 @@ "type": "github" } }, - "ghc-8.6.5-iohk_3": { - "flake": false, - "locked": { - "lastModified": 1600920045, - "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", - "owner": "input-output-hk", - "repo": "ghc", - "rev": "95713a6ecce4551240da7c96b6176f980af75cae", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "ref": "release/8.6.5-iohk", - "repo": "ghc", - "type": "github" - } - }, "goblins": { "flake": false, "locked": { @@ -826,11 +734,11 @@ "hackage": { "flake": false, "locked": { - "lastModified": 1631668346, - "narHash": "sha256-4dWzl+HoFlXNhaqw4snC3ELBU+6IVBUihuVz41JZi4Y=", + "lastModified": 1650157984, + "narHash": "sha256-hitutrIIn+qINGi6oef53f87we+cp3QNmXSBiCzVU90=", "owner": "input-output-hk", "repo": "hackage.nix", - "rev": "7eb138fdad1ce0a3fba0697d3eba819b185a83d6", + "rev": "2290fdc4d135407896f41ba518a0eae8efaae9c5", "type": "github" }, "original": { @@ -855,46 +763,30 @@ "type": "github" } }, - "hackage_3": { - "flake": false, - "locked": { - "lastModified": 1644887696, - "narHash": "sha256-o4gltv4npUl7+1gEQIcrRqZniwqC9kK8QsPaftlrawc=", - "owner": "input-output-hk", - "repo": "hackage.nix", - "rev": "6ff64aa49b88e75dd6e0bbd2823c2a92c9174fa5", - "type": "github" - }, - "original": { - "owner": "input-output-hk", - "repo": "hackage.nix", - "type": "github" - } - }, "haskell-nix": { "inputs": { - "HTTP": "HTTP_2", - "cabal-32": "cabal-32_2", - "cabal-34": "cabal-34_2", + "HTTP": "HTTP", + "cabal-32": "cabal-32", + "cabal-34": "cabal-34", "cabal-36": "cabal-36", - "cardano-shell": "cardano-shell_2", - "flake-utils": "flake-utils_2", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", - "hackage": "hackage_2", - "hpc-coveralls": "hpc-coveralls_2", + "cardano-shell": "cardano-shell", + "flake-utils": "flake-utils", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", + "hackage": "hackage", + "hpc-coveralls": "hpc-coveralls", "hydra": "hydra", - "nix-tools": "nix-tools_2", + "nix-tools": "nix-tools", "nixpkgs": [ "cardano-transaction-lib", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003_2", - "nixpkgs-2105": "nixpkgs-2105_2", + "nixpkgs-2003": "nixpkgs-2003", + "nixpkgs-2105": "nixpkgs-2105", "nixpkgs-2111": "nixpkgs-2111", - "nixpkgs-unstable": "nixpkgs-unstable_2", - "old-ghc-nix": "old-ghc-nix_2", - "stackage": "stackage_2" + "nixpkgs-unstable": "nixpkgs-unstable", + "old-ghc-nix": "old-ghc-nix", + "stackage": "stackage" }, "locked": { "lastModified": 1650194184, @@ -913,129 +805,93 @@ }, "haskell-nix_2": { "inputs": { - "HTTP": "HTTP_3", - "cabal-32": "cabal-32_3", - "cabal-34": "cabal-34_3", + "HTTP": "HTTP_2", + "cabal-32": "cabal-32_2", + "cabal-34": "cabal-34_2", "cabal-36": "cabal-36_2", - "cardano-shell": "cardano-shell_3", - "flake-utils": "flake-utils_3", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_3", - "hackage": "hackage_3", - "hpc-coveralls": "hpc-coveralls_3", - "nix-tools": "nix-tools_3", + "cardano-shell": "cardano-shell_2", + "flake-utils": "flake-utils_2", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk_2", + "hackage": "hackage_2", + "hpc-coveralls": "hpc-coveralls_2", + "hydra": "hydra_2", + "nix-tools": "nix-tools_2", "nixpkgs": [ "cardano-transaction-lib", "ogmios", "haskell-nix", "nixpkgs-unstable" ], - "nixpkgs-2003": "nixpkgs-2003_3", - "nixpkgs-2105": "nixpkgs-2105_3", + "nixpkgs-2003": "nixpkgs-2003_2", + "nixpkgs-2105": "nixpkgs-2105_2", "nixpkgs-2111": "nixpkgs-2111_2", - "nixpkgs-unstable": "nixpkgs-unstable_3", - "old-ghc-nix": "old-ghc-nix_3", - "stackage": "stackage_3" - }, - "locked": { - "lastModified": 1644944726, - "narHash": "sha256-jJWdP/3Ne1y1akC3m9rSO5ItRoBc4UTdVQZBCuPmmrM=", - "owner": "L-as", - "repo": "haskell.nix", - "rev": "45c583b5580c130487eb5a342679f0bdbc2b23fc", - "type": "github" - }, - "original": { - "owner": "L-as", - "ref": "master", - "repo": "haskell.nix", - "type": "github" - } - }, - "haskellNix": { - "inputs": { - "HTTP": "HTTP", - "cabal-32": "cabal-32", - "cabal-34": "cabal-34", - "cardano-shell": "cardano-shell", - "flake-utils": "flake-utils", - "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", - "hackage": "hackage", - "hpc-coveralls": "hpc-coveralls", - "nix-tools": "nix-tools", - "nixpkgs": [ - "cardano-transaction-lib", - "cardano-node-exe", - "nixpkgs" - ], - "nixpkgs-2003": "nixpkgs-2003", - "nixpkgs-2009": "nixpkgs-2009", - "nixpkgs-2105": "nixpkgs-2105", - "nixpkgs-unstable": "nixpkgs-unstable", - "old-ghc-nix": "old-ghc-nix", - "stackage": "stackage" + "nixpkgs-unstable": "nixpkgs-unstable_2", + "old-ghc-nix": "old-ghc-nix_2", + "stackage": "stackage_2" }, "locked": { - "lastModified": 1631703614, - "narHash": "sha256-XYC0M96V9oQTGq1TSIQTVwkA+SrUqE4o6kUZo4iO8Z4=", - "owner": "input-output-hk", + "lastModified": 1650194184, + "narHash": "sha256-wwRdO075Gh+NbyTH4Gce/hxn7hKJjbNs4/YrKpOguAA=", + "owner": "mlabs-haskell", "repo": "haskell.nix", - "rev": "19052d83fda811dd39216e3fc197c980abd037fd", + "rev": "cf1f0460b65efadac6dc96169ef1e497410fa4f4", "type": "github" }, "original": { - "owner": "input-output-hk", + "owner": "mlabs-haskell", "repo": "haskell.nix", + "rev": "cf1f0460b65efadac6dc96169ef1e497410fa4f4", "type": "github" } }, "hedgehog-extras": { "flake": false, "locked": { - "lastModified": 1626138074, - "narHash": "sha256-KYLGLpDGHWlb/Gcx6Q/2HTnRMzZQmPKz0JbIw+bHh3E=", + "lastModified": 1647260073, + "narHash": "sha256-TR9i1J3HUYz3QnFQbfJPr/kGDahxZPojDsorYtRZeGU=", "owner": "input-output-hk", "repo": "hedgehog-extras", - "rev": "edf6945007177a638fbeb8802397f3a6f4e47c14", + "rev": "967d79533c21e33387d0227a5f6cc185203fe658", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "hedgehog-extras", - "rev": "edf6945007177a638fbeb8802397f3a6f4e47c14", + "rev": "967d79533c21e33387d0227a5f6cc185203fe658", "type": "github" } }, "hjsonpointer": { "flake": false, "locked": { - "lastModified": 1538408336, - "narHash": "sha256-l2GZpN5SGalPalIa8xcHOdafSQqLK1Y66aYWOVElwlk=", + "lastModified": 1654184599, + "narHash": "sha256-y1UCtaVI5Zsb8MeOQA8XbSX3p4/JoroRTG9RGl0I7DY=", "owner": "KtorZ", "repo": "hjsonpointer", - "rev": "75ed0d049c33274a6cb4c36c8538d4bf2ef9c30e", + "rev": "879f0e74d55eef76ceaec8f60ed07657ab84bad7", "type": "github" }, "original": { "owner": "KtorZ", "repo": "hjsonpointer", - "rev": "75ed0d049c33274a6cb4c36c8538d4bf2ef9c30e", + "rev": "879f0e74d55eef76ceaec8f60ed07657ab84bad7", "type": "github" } }, "hjsonschema": { "flake": false, "locked": { - "lastModified": 1588363390, - "narHash": "sha256-lep5HGrtxp/XN72WXY1JVk5lJ5cE0XMhxKwjMpCoAxk=", + "lastModified": 1654186606, + "narHash": "sha256-1UG+rP7Z/kxiqj2qcx70688u1P23RzopAim+MClo6PA=", "owner": "KtorZ", "repo": "hjsonschema", - "rev": "fde6e676f79f3f3320a558f20492ad816a2543a7", + "rev": "35e0b05c3867463363e67f00a5092cd39fa33313", "type": "github" }, "original": { "owner": "KtorZ", "repo": "hjsonschema", - "rev": "fde6e676f79f3f3320a558f20492ad816a2543a7", + "rev": "35e0b05c3867463363e67f00a5092cd39fa33313", "type": "github" } }, @@ -1071,27 +927,36 @@ "type": "github" } }, - "hpc-coveralls_3": { - "flake": false, + "hydra": { + "inputs": { + "nix": "nix", + "nixpkgs": [ + "cardano-transaction-lib", + "haskell-nix", + "hydra", + "nix", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1607498076, - "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "lastModified": 1646878427, + "narHash": "sha256-KtbrofMtN8GlM7D+n90kixr7QpSlVmdN+vK5CA/aRzc=", + "owner": "NixOS", + "repo": "hydra", + "rev": "28b682b85b7efc5cf7974065792a1f22203a5927", "type": "github" }, "original": { - "owner": "sevanspowell", - "repo": "hpc-coveralls", - "type": "github" + "id": "hydra", + "type": "indirect" } }, - "hydra": { + "hydra_2": { "inputs": { - "nix": "nix", + "nix": "nix_2", "nixpkgs": [ "cardano-transaction-lib", + "ogmios", "haskell-nix", "hydra", "nix", @@ -1111,6 +976,23 @@ "type": "indirect" } }, + "io-sim": { + "flake": false, + "locked": { + "lastModified": 1653046584, + "narHash": "sha256-vFE67shdZScks67KezdKToLuk6k6wwyLFzshClO7Ym0=", + "owner": "input-output-hk", + "repo": "io-sim", + "rev": "f4183f274d88d0ad15817c7052df3a6a8b40e6dc", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "io-sim", + "rev": "f4183f274d88d0ad15817c7052df3a6a8b40e6dc", + "type": "github" + } + }, "iohk-monitoring-framework": { "flake": false, "locked": { @@ -1131,17 +1013,17 @@ "iohk-monitoring-framework_2": { "flake": false, "locked": { - "lastModified": 1624367860, - "narHash": "sha256-QE3QRpIHIABm+qCP/wP4epbUx0JmSJ9BMePqWEd3iMY=", + "lastModified": 1653619339, + "narHash": "sha256-0ia5UflYEmBYepj2gkJy9msknklI0UPtUavMEGwk3Wg=", "owner": "input-output-hk", "repo": "iohk-monitoring-framework", - "rev": "46f994e216a1f8b36fe4669b47b2a7011b0e153c", + "rev": "066f7002aac5a0efc20e49643fea45454f226caa", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "iohk-monitoring-framework", - "rev": "46f994e216a1f8b36fe4669b47b2a7011b0e153c", + "rev": "066f7002aac5a0efc20e49643fea45454f226caa", "type": "github" } }, @@ -1163,25 +1045,22 @@ "type": "github" } }, - "iohkNix": { + "iohk-nix_2": { "inputs": { - "nixpkgs": [ - "cardano-transaction-lib", - "cardano-node-exe", - "nixpkgs" - ] + "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1631778944, - "narHash": "sha256-N5eCcUYtZ5kUOl/JJGjx6ZzhA3uIn1itDRTiRV+3jLw=", + "lastModified": 1649070135, + "narHash": "sha256-UFKqcOSdPWk3TYUCPHF22p1zf7aXQpCmmgf7UMg7fWA=", "owner": "input-output-hk", "repo": "iohk-nix", - "rev": "db2c75a09c696271194bb3ef25ec8e9839b594b7", + "rev": "cecab9c71d1064f05f1615eead56ac0b9196bc20", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "iohk-nix", + "rev": "cecab9c71d1064f05f1615eead56ac0b9196bc20", "type": "github" } }, @@ -1201,6 +1080,22 @@ "type": "github" } }, + "lowdown-src_2": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, "nix": { "inputs": { "lowdown-src": "lowdown-src", @@ -1225,11 +1120,11 @@ "nix-tools": { "flake": false, "locked": { - "lastModified": 1626997434, - "narHash": "sha256-1judQmP298ao6cGUNxcGhcAXHOnA9qSLvWk/ZtoUL7w=", + "lastModified": 1649424170, + "narHash": "sha256-XgKXWispvv5RCvZzPb+p7e6Hy3LMuRjafKMl7kXzxGw=", "owner": "input-output-hk", "repo": "nix-tools", - "rev": "c8c5e6a6fbb12a73598d1a434984a36e880ce3cf", + "rev": "e109c94016e3b6e0db7ed413c793e2d4bdb24aa7", "type": "github" }, "original": { @@ -1254,19 +1149,24 @@ "type": "github" } }, - "nix-tools_3": { - "flake": false, + "nix_2": { + "inputs": { + "lowdown-src": "lowdown-src_2", + "nixpkgs": "nixpkgs_3", + "nixpkgs-regression": "nixpkgs-regression_2" + }, "locked": { - "lastModified": 1644395812, - "narHash": "sha256-BVFk/BEsTLq5MMZvdy3ZYHKfaS3dHrsKh4+tb5t5b58=", - "owner": "input-output-hk", - "repo": "nix-tools", - "rev": "d847c63b99bbec78bf83be2a61dc9f09b8a9ccc1", + "lastModified": 1643066034, + "narHash": "sha256-xEPeMcNJVOeZtoN+d+aRwolpW8mFSEQx76HTRdlhPhg=", + "owner": "NixOS", + "repo": "nix", + "rev": "a1cd7e58606a41fcf62bf8637804cf8306f17f62", "type": "github" }, "original": { - "owner": "input-output-hk", - "repo": "nix-tools", + "owner": "NixOS", + "ref": "2.6.0", + "repo": "nix", "type": "github" } }, @@ -1317,45 +1217,13 @@ "type": "github" } }, - "nixpkgs-2003_3": { - "locked": { - "lastModified": 1620055814, - "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-20.03-darwin", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-2009": { - "locked": { - "lastModified": 1624271064, - "narHash": "sha256-qns/uRW7MR2EfVf6VEeLgCsCp7pIOjDeR44JzTF09MA=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "46d1c3f28ca991601a53e9a14fdd53fcd3dd8416", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-20.09-darwin", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs-2105": { "locked": { - "lastModified": 1630481079, - "narHash": "sha256-leWXLchbAbqOlLT6tju631G40SzQWPqaAXQG3zH1Imw=", + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "110a2c9ebbf5d4a94486854f18a37a938cfacbbb", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", "type": "github" }, "original": { @@ -1381,23 +1249,23 @@ "type": "github" } }, - "nixpkgs-2105_3": { + "nixpkgs-2111": { "locked": { - "lastModified": 1642244250, - "narHash": "sha256-vWpUEqQdVP4srj+/YLJRTN9vjpTs4je0cdWKXPbDItc=", + "lastModified": 1648744337, + "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0fd9ee1aa36ce865ad273f4f07fdc093adeb5c00", + "rev": "0a58eebd8ec65ffdef2ce9562784123a73922052", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-21.05-darwin", + "ref": "nixpkgs-21.11-darwin", "repo": "nixpkgs", "type": "github" } }, - "nixpkgs-2111": { + "nixpkgs-2111_2": { "locked": { "lastModified": 1648744337, "narHash": "sha256-bYe1dFJAXovjqiaPKrmAbSBEK5KUkgwVaZcTbSoJ7hg=", @@ -1413,23 +1281,22 @@ "type": "github" } }, - "nixpkgs-2111_2": { + "nixpkgs-regression": { "locked": { - "lastModified": 1644510859, - "narHash": "sha256-xjpVvL5ecbyi0vxtVl/Fh9bwGlMbw3S06zE5nUzFB8A=", + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0d1d5d7e3679fec9d07f2eb804d9f9fdb98378d3", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-21.11-darwin", - "repo": "nixpkgs", - "type": "github" + "id": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "indirect" } }, - "nixpkgs-regression": { + "nixpkgs-regression_2": { "locked": { "lastModified": 1643052045, "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", @@ -1446,11 +1313,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1628785280, - "narHash": "sha256-2B5eMrEr6O8ff2aQNeVxTB+9WrGE80OB4+oM6T7fOcc=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6525bbc06a39f26750ad8ee0d40000ddfdc24acb", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", "type": "github" }, "original": { @@ -1476,23 +1343,35 @@ "type": "github" } }, - "nixpkgs-unstable_3": { + "nixpkgs_2": { "locked": { - "lastModified": 1644486793, - "narHash": "sha256-EeijR4guVHgVv+JpOX3cQO+1XdrkJfGmiJ9XVsVU530=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "1882c6b7368fd284ad01b0a5b5601ef136321292", - "type": "github" + "lastModified": 1647122627, + "narHash": "sha256-w4hGsXYyMgJAQRSBxh7O6AAsawJSbudCxfQXhDRhwPQ=", + "path": "/nix/store/s6wigis38dnikj5y92jrrj7ywc38b78g-source", + "rev": "0f85665118d850aae5164d385d24783d0b16cf1b", + "type": "path" }, "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1632864508, + "narHash": "sha256-d127FIvGR41XbVRDPVvozUPQ/uRHbHwvfyKHwEt5xFM=", "owner": "NixOS", - "ref": "nixpkgs-unstable", "repo": "nixpkgs", + "rev": "82891b5e2c2359d7e58d08849e4c89511ab94234", "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-21.05-small", + "type": "indirect" } }, - "nixpkgs_2": { + "nixpkgs_4": { "locked": { "lastModified": 1647122627, "narHash": "sha256-w4hGsXYyMgJAQRSBxh7O6AAsawJSbudCxfQXhDRhwPQ=", @@ -1505,6 +1384,22 @@ "type": "indirect" } }, + "nixpkgs_5": { + "locked": { + "lastModified": 1634172192, + "narHash": "sha256-FBF4U/T+bMg4sEyT/zkgasvVquGzgdAf4y8uCosKMmo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2cf9db0e3d45b9d00f16f2836cb1297bcadc475e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2cf9db0e3d45b9d00f16f2836cb1297bcadc475e", + "type": "github" + } + }, "ogmios": { "inputs": { "Win32-network": "Win32-network_2", @@ -1513,52 +1408,62 @@ "cardano-ledger": "cardano-ledger_2", "cardano-node": "cardano-node_2", "cardano-prelude": "cardano-prelude_2", - "flake-compat": "flake-compat", + "ekg-json": "ekg-json", + "flake-compat": "flake-compat_2", "flat": "flat_2", "goblins": "goblins_2", "haskell-nix": "haskell-nix_2", "hedgehog-extras": "hedgehog-extras", "hjsonpointer": "hjsonpointer", "hjsonschema": "hjsonschema", + "io-sim": "io-sim", "iohk-monitoring-framework": "iohk-monitoring-framework_2", + "iohk-nix": "iohk-nix_2", "nixpkgs": [ "cardano-transaction-lib", "ogmios", "haskell-nix", - "nixpkgs-2105" + "nixpkgs-unstable" ], + "optparse-applicative": "optparse-applicative", "ouroboros-network": "ouroboros-network", "plutus": "plutus", + "typed-protocols": "typed-protocols", "wai-routes": "wai-routes" }, "locked": { - "lastModified": 1646900647, - "narHash": "sha256-UIUu3B1ONjXCnNJjLwgeGxczo00FrSUd2Iwg1mSb8VQ=", + "lastModified": 1656650330, + "narHash": "sha256-Rl5xNP3LVtuOzXXSsdAWNB3EXGRPsFPMvBO0TDUvSJE=", "owner": "mlabs-haskell", "repo": "ogmios", - "rev": "c4f896bf32ad066be8edd8681ee11e4ab059be7f", + "rev": "e406801eaeb32b28cd84357596ca1512bff27741", "type": "github" }, "original": { "owner": "mlabs-haskell", "repo": "ogmios", - "rev": "c4f896bf32ad066be8edd8681ee11e4ab059be7f", + "rev": "e406801eaeb32b28cd84357596ca1512bff27741", "type": "github" } }, "ogmios-datum-cache": { - "flake": false, + "inputs": { + "flake-compat": "flake-compat_3", + "nixpkgs": "nixpkgs_5", + "unstable_nixpkgs": "unstable_nixpkgs" + }, "locked": { - "lastModified": 1649871652, - "narHash": "sha256-X2oDliRDUb7Y8a5SfBxSzWgzYY0Spun2YwZFN+3gCTE=", + "lastModified": 1656671352, + "narHash": "sha256-EO3WrQnCXK+Lg8PNG2TK8iQxn5Zo+x7pmYFf1qWs0fk=", "owner": "mlabs-haskell", "repo": "ogmios-datum-cache", - "rev": "9e8bcbe00f88715afdb202cd9654ec2adc72c09e", + "rev": "1c7a4af3f18bd3fa94a59e5a52e0ad6d974233e8", "type": "github" }, "original": { "owner": "mlabs-haskell", "repo": "ogmios-datum-cache", + "rev": "1c7a4af3f18bd3fa94a59e5a52e0ad6d974233e8", "type": "github" } }, @@ -1596,24 +1501,24 @@ "type": "github" } }, - "old-ghc-nix_3": { + "optparse-applicative": { "flake": false, "locked": { - "lastModified": 1631092763, - "narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=", - "owner": "angerman", - "repo": "old-ghc-nix", - "rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8", + "lastModified": 1628901899, + "narHash": "sha256-uQx+SEYsCH7JcG3xAT0eJck9yq3y0cvx49bvItLLer8=", + "owner": "input-output-hk", + "repo": "optparse-applicative", + "rev": "7497a29cb998721a9068d5725d49461f2bba0e7a", "type": "github" }, "original": { - "owner": "angerman", - "ref": "master", - "repo": "old-ghc-nix", + "owner": "input-output-hk", + "repo": "optparse-applicative", + "rev": "7497a29cb998721a9068d5725d49461f2bba0e7a", "type": "github" } }, - "optparse-applicative": { + "optparse-applicative_2": { "flake": false, "locked": { "lastModified": 1628901899, @@ -1633,17 +1538,17 @@ "ouroboros-network": { "flake": false, "locked": { - "lastModified": 1639767242, - "narHash": "sha256-n/4it/p3OxqtzVHESgZIZVdgFBsSNlvjYdTvxC0gc3I=", + "lastModified": 1654820431, + "narHash": "sha256-bmLD5sFsiny/eRv6MHrqGvo6I4QG9pO0psiHWGFZqro=", "owner": "input-output-hk", "repo": "ouroboros-network", - "rev": "32af91686b86dac7454eee8b8a8d6e97a80638da", + "rev": "a65c29b6a85e90d430c7f58d362b7eb097fd4949", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "ouroboros-network", - "rev": "32af91686b86dac7454eee8b8a8d6e97a80638da", + "rev": "a65c29b6a85e90d430c7f58d362b7eb097fd4949", "type": "github" } }, @@ -1667,17 +1572,17 @@ "plutus": { "flake": false, "locked": { - "lastModified": 1632818067, - "narHash": "sha256-jiqrzS519eoHg9NqTr4UZOVme3uIACL17OCiDMn0LMo=", + "lastModified": 1655404007, + "narHash": "sha256-8ZCD/f321fFs8k+FBfxnpYlm1+C+rKM8Io9K0CDCEqA=", "owner": "input-output-hk", "repo": "plutus", - "rev": "1efbb276ef1a10ca6961d0fd32e6141e9798bd11", + "rev": "f680ac6979e069fcc013e4389ee607ff5fa6672f", "type": "github" }, "original": { "owner": "input-output-hk", "repo": "plutus", - "rev": "1efbb276ef1a10ca6961d0fd32e6141e9798bd11", + "rev": "f680ac6979e069fcc013e4389ee607ff5fa6672f", "type": "github" } }, @@ -1718,7 +1623,7 @@ "root": { "inputs": { "cardano-transaction-lib": "cardano-transaction-lib", - "flake-compat": "flake-compat_2", + "flake-compat": "flake-compat_4", "nixpkgs": [ "cardano-transaction-lib", "nixpkgs" @@ -1745,11 +1650,11 @@ "stackage": { "flake": false, "locked": { - "lastModified": 1631495632, - "narHash": "sha256-jnkmC3PqnRpM4y74b4ZxgD+MTpz3ovxoU99TBCNRDP0=", + "lastModified": 1650158092, + "narHash": "sha256-uQ/TEFcce0bKmYcoBziDhYYzCDmhPsjC5WgsJjpd9wA=", "owner": "input-output-hk", "repo": "stackage.nix", - "rev": "3f43e2e72e0853e911497277ec094933892718a9", + "rev": "adc7f942e756b382a7a833520ebef6dfc859af8e", "type": "github" }, "original": { @@ -1774,34 +1679,35 @@ "type": "github" } }, - "stackage_3": { + "typed-protocols": { "flake": false, "locked": { - "lastModified": 1644887829, - "narHash": "sha256-tjUXJpqB7MMnqM4FF5cdtZipfratUcTKRQVA6F77sEQ=", + "lastModified": 1653046676, + "narHash": "sha256-5Wof5yTKb12EPY6B8LfapX18xNZZpF+rvhnQ88U6KdM=", "owner": "input-output-hk", - "repo": "stackage.nix", - "rev": "db8bdef6588cf4f38e6069075ba76f0024381f68", + "repo": "typed-protocols", + "rev": "181601bc3d9e9d21a671ce01e0b481348b3ca104", "type": "github" }, "original": { "owner": "input-output-hk", - "repo": "stackage.nix", + "repo": "typed-protocols", + "rev": "181601bc3d9e9d21a671ce01e0b481348b3ca104", "type": "github" } }, - "utils": { + "unstable_nixpkgs": { "locked": { - "lastModified": 1623875721, - "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", + "lastModified": 1653307806, + "narHash": "sha256-VPej3GE4IBMwYnXRfbiVqMWKa32+ysuvbHRkQXD0gTw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9d7aff488a8f9429d9e6cd82c10dffbf21907fb1", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "NixOS", + "repo": "nixpkgs", "type": "github" } }, diff --git a/flake.nix b/flake.nix index 23c4bdc..a9d20aa 100644 --- a/flake.nix +++ b/flake.nix @@ -10,7 +10,10 @@ type = "github"; owner = "Plutonomicon"; repo = "cardano-transaction-lib"; - rev = "a83d75e852571e6a8ad2e60c449f198e1b3270a2"; + # should be same rev as in packages.dhall + # To update, do `spago2nix generate` + # calum/metadata-invalid-char-fix + rev = "32194c502e4a068bf99388b05c708f81612d7541"; }; nixpkgs.follows = "cardano-transaction-lib/nixpkgs"; }; @@ -21,7 +24,7 @@ perSystem = nixpkgs.lib.genAttrs defaultSystems; nixpkgsFor = system: import nixpkgs { inherit system; - overlays = [ cardano-transaction-lib.overlay.${system} ]; + overlays = [ cardano-transaction-lib.overlay ]; }; psProjectFor = system: let @@ -31,10 +34,16 @@ pkgs.purescriptProject { inherit pkgs src; projectName = "seabug-contracts"; + shell = { + packages = [ + pkgs.easy-ps.purs-tidy + pkgs.fd + ]; + }; }; in { - defaultPackage = perSystem (system: self.packages.${system}.seabug-contracts); + defaultPackage = perSystem (system: self.packages.${system}.seabug-contracts-bundle-web); packages = perSystem (system: let diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..a239ae6 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,119 @@ +export function callMarketPlaceBuy(config: Config, args: BuyNftArgs): + Promise +export function callMarketPlaceListNft(config: Config): + Promise> +/** + * Fetch the info for a single NFT. Returns null if the given + * transaction input has been spent (for example if the NFT has been + * bought). + */ +export function callMarketPlaceFetchNft(config: Config, args: FetchNftArgs): + Promise +export function connectWallet(): Promise +export function getWalletBalance(): Promise + +export type NetworkId + = 0 // Testnet + | 1 // Mainnet + +export type Config = { + serverHost: string, + serverPort: number, + // If CTL Haskell server uses SSL + serverSecureConn: boolean, + ogmiosHost: string, + ogmiosPort: number, + // If Ogmios uses SSL + ogmiosSecureConn: boolean, + datumCacheHost: string, + datumCachePort: number, + // If ogmios-datum-cache uses SSL + datumCacheSecureConn: boolean, + networkId: NetworkId, + // blockfrost.io API key + projectId: string, +} + +export type ContractArgs = { + nftCollectionArgs: NftCollectionArgs, + nftIdArgs: NftIdArgs +} + +export type BuyNftArgs = { + +} + +export type FetchNftArgs = Input + +export type NftCollectionArgs = { + // CurrencySymbol of nft collection + collectionNftCs: string, + lockLockup: bigint, + lockLockupEnd: bigint, + // ValidatorHash of a script locking the nft + lockingScript: string, + //PaymentPubKeyHash of the nft author + author: string, + authorShare: bigint, + // Validator hash + daoScript: string, + daoShare: bigint +} + +export type NftIdArgs = { + // TokenName of the nft collection + collectionNftTn: string, + price: bigint, + // PaymentPubKeyHash of the nft current owner + owner: string +} + +export type NftListing = { + input: Input, + output: Output, + metadata: Metadata +} + +export type Input = { + transactionId: String, + inputIndex: number +} + +export type Output = { + address: string, + value: ValueOut, + data_hash: string +} + +export type ValueOut = { + currencySymbol: string, + tokenName: string, + amount: bigint +} + +export type Metadata = { + seabugMetadata: SeabugMetadata + ipfsHash: string +} + +export type SeabugMetadata = { + // Hash of minting policy + policyId: string, + // Hexadecimal string representing bytes of minting policy + mintPolicy: string, + // Currency symbol + collectionNftCS: string, + // Token name + collectionNftTN: string, + // Hash of locking script + lockingScript: string, + // Pub key hash of author + authorPkh: string, + authorShare: bigint, + // Hash of marketplace validator + marketplaceScript: string, + marketplaceShare: bigint, + // Pub key hash of owner + ownerPkh: string, + ownerPrice: bigint +} diff --git a/index.js b/index.js index eb14d5a..53339d7 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,41 @@ // You also need to call `spago bundle-module` to generate the module that is // imported here. From the repository root, run: // spago bundle-module -m
--to output.js -import("./output.js").then((m) => m.main()); +const seabug = import("./output.js"); -console.log("app starting"); +/** + * Calls Seabug Contract 'marketPlaceBuy'. + * It returns a promise holding no data. + * + */ +exports.callMarketPlaceBuy = async (config, args) => { + const sb = await seabug; + return sb.callMarketPlaceBuy(config)(args)(); +}; + +/** + * Calls Seabug Contract 'marketPlaceListNft'. + * Returns a promise holding nft listings. + * + */ +exports.callMarketPlaceListNft = async (config) => { + const sb = await seabug; + return sb.callMarketPlaceListNft(config)(); +}; + +exports.callMarketPlaceFetchNft = async (config, args) => { + const sb = await seabug; + return sb.callMarketPlaceFetchNft(config)(args)(); +}; + + +/** + * Returns a promise containing the connected wallet's balance. + */ +exports.getWalletBalance = async () => { + const sb = await seabug; + return sb.getWalletBalance(); +}; + +// Uncomment this for manually minting new tokens (see README) +// seabug.then((sb) => sb.mint().then(() => console.log("Done"))) diff --git a/package-lock.json b/package-lock.json index 04894d9..5d06735 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,15 +10,15 @@ "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", "dev": true }, - "@ngua/cardano-serialization-lib-browser": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@ngua/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-9.1.2.tgz", - "integrity": "sha512-0KkS3vCwrK8Yxs+yuoFJ05Ou5r0AZJNTWks9otP5h9ODsTUpkgJDb3lVmflJmSB0KnA9JvF3AmcN/swXj/yw+A==" + "@emurgo/cardano-serialization-lib-browser": { + "version": "11.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.0.0-beta.1.tgz", + "integrity": "sha512-y2jxCPQBZIG1WTcNxPT8AVb1KjCUQV5nq0em32m4l4siHCQjA4STVVds1r61sSCyviP6dzrAJo4n5i/rs+zeKQ==" }, - "@ngua/cardano-serialization-lib-nodejs": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@ngua/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-9.1.2.tgz", - "integrity": "sha512-6xpp5Xjcqm9eHIrKBUmmIeZV6n0OeK6t8vCyQzF8KcHEQiknAcIcoIq/wf7sEcLV3ohwn945QCKkM3rKsKF5FA==" + "@emurgo/cardano-serialization-lib-nodejs": { + "version": "11.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.0.0-beta.1.tgz", + "integrity": "sha512-YCsfZCXDDFGeX8dp0CFOksPEsTYbnJ8YbmwKc+Vm6e6Vv6yNpXRRhcwE0Zm29lGqLQ+gUbMmLZSclKiXAb52fA==" }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -550,6 +550,11 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, + "b4a": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.5.3.tgz", + "integrity": "sha512-1aCQIzQJK7G0z1Una75tWMlwVAR8o+QHoAlnWc5XAxRVBESY9WsitfBgM5nPyDBP5HrhPU1Np4Pq2Y7CJQ+tVw==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -578,6 +583,20 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "blake2b-wasm": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/blake2b-wasm/-/blake2b-wasm-2.4.0.tgz", + "integrity": "sha512-S1kwmW2ZhZFFFOghcx73+ZajEfKBqhP82JMssxtLVMxlaPea1p9uoLiUZ5WYyHn0KddwbLc+0vh4wR0KBNoT5w==", + "requires": { + "b4a": "^1.0.1", + "nanoassert": "^2.0.0" + } + }, + "blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" + }, "bn.js": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", @@ -2264,6 +2283,11 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "jssha": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.2.0.tgz", + "integrity": "sha512-QuruyBENDWdN4tZwJbQq7/eAK85FqrI4oDbXjy5IBhYD+2pTJyBUWZe8ctWaCkrV0gy6AaelgOZZBMeswEa/6Q==" + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -2458,6 +2482,11 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "nanoassert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz", + "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==" + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -2995,6 +3024,11 @@ "resolve": "^1.9.0" } }, + "reconnecting-websocket": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz", + "integrity": "sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==" + }, "regexp.prototype.flags": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", diff --git a/package.json b/package.json index 180efef..ce00467 100644 --- a/package.json +++ b/package.json @@ -14,20 +14,28 @@ "author": "", "license": "MIT", "dependencies": { - "@ngua/cardano-serialization-lib-browser": "9.1.2", - "@ngua/cardano-serialization-lib-nodejs": "9.1.2", + "@emurgo/cardano-serialization-lib-browser": "11.0.0-beta.1", + "@emurgo/cardano-serialization-lib-nodejs": "11.0.0-beta.1", "big-integer": "1.6.51", + "blakejs": "1.2.1", + "blake2b-wasm": "2.4.0", "bufferutil": "4.0.5", + "jssha": "3.2.0", "node-polyfill-webpack-plugin": "1.1.4", "uniqid": "5.4.0", + "reconnecting-websocket": "4.4.0", "ws": "8.4.0", "xhr2": "0.2.1" }, "devDependencies": { "buffer": "6.0.3", + "html-webpack-plugin": "5.5.0", "webpack": "5.67.0", "webpack-cli": "4.9.2", - "html-webpack-plugin": "5.5.0", "webpack-dev-server": "4.7.4" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mlabs-haskell/seabug-contracts.git" } } diff --git a/packages.dhall b/packages.dhall index 32fef19..a67b853 100644 --- a/packages.dhall +++ b/packages.dhall @@ -108,7 +108,104 @@ let upstream = https://github.com/purescript/package-sets/releases/download/psc-0.14.5-20211116/packages.dhall sha256:7ba810597a275e43c83411d2ab0d4b3c54d0b551436f4b1632e9ff3eb62e327a let additions = - { + { aeson = + { dependencies = + [ "aff" + , "argonaut" + , "argonaut-codecs" + , "argonaut-core" + , "arrays" + , "bifunctors" + , "bigints" + , "const" + , "control" + , "effect" + , "either" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "gen" + , "identity" + , "integers" + , "maybe" + , "newtype" + , "node-buffer" + , "node-fs-aff" + , "node-path" + , "nonempty" + , "numbers" + , "partial" + , "prelude" + , "quickcheck" + , "record" + , "sequences" + , "spec" + , "strings" + , "transformers" + , "tuples" + , "typelevel" + , "typelevel-prelude" + , "uint" + , "untagged-union" + ] + , repo = "https://github.com/mlabs-haskell/purescript-aeson.git" + , version = "286862a975f4bafbef15540c365bbbb0480e0bf7" + } + , aeson-helpers = + { dependencies = + [ "aff" + , "argonaut-codecs" + , "argonaut-core" + , "arrays" + , "bifunctors" + , "contravariant" + , "control" + , "effect" + , "either" + , "enums" + , "foldable-traversable" + , "foreign-object" + , "maybe" + , "newtype" + , "ordered-collections" + , "prelude" + , "profunctor" + , "psci-support" + , "quickcheck" + , "record" + , "spec" + , "spec-quickcheck" + , "transformers" + , "tuples" + , "typelevel-prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-bridge-aeson-helpers.git" + , version = "44d0dae060cf78babd4534320192b58c16a6f45b" + } + , sequences = + { dependencies = + [ "arrays" + , "assert" + , "console" + , "effect" + , "lazy" + , "maybe" + , "newtype" + , "nonempty" + , "partial" + , "prelude" + , "profunctor" + , "psci-support" + , "quickcheck" + , "quickcheck-laws" + , "tuples" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = "https://github.com/hdgarrood/purescript-sequences" + , version = "v3.0.2" + } , properties = { dependencies = ["prelude", "console"] , repo = "https://github.com/Risto-Stevcev/purescript-properties.git" @@ -171,12 +268,10 @@ let additions = } , cardano-transaction-lib = { dependencies = - [ "aff" + [ "aeson" + , "aff" , "aff-promise" , "affjax" - , "argonaut" - , "argonaut-codecs" - , "argonaut-core" , "arraybuffer-types" , "arrays" , "bifunctors" @@ -193,7 +288,6 @@ let additions = , "exceptions" , "foldable-traversable" , "foreign-object" - , "gen" , "identity" , "integers" , "js-date" @@ -207,7 +301,6 @@ let additions = , "node-buffer" , "node-fs" , "node-fs-aff" - , "node-path" , "nonempty" , "ordered-collections" , "partial" @@ -234,7 +327,12 @@ let additions = , "variant" ] , repo = "https://github.com/Plutonomicon/cardano-transaction-lib.git" - , version = "a83d75e852571e6a8ad2e60c449f198e1b3270a2" + -- should be same rev as in flake.nix + -- https://github.com/Plutonomicon/cardano-transaction-lib/pull/696 + -- PR: Return error if no utxo is specified for a tx input & Fix transaction inputs locking + -- Commit is from our branch calum/metadata-invalid-char-fix which is based off this PR and + -- includes a small fix to get the build working. Also updated to include `awaitTxConfirmed`. + , version = "32194c502e4a068bf99388b05c708f81612d7541" } } -in upstream // additions +in upstream // additions diff --git a/seabug-contracts-0.1.0.tgz b/seabug-contracts-0.1.0.tgz new file mode 100644 index 0000000..c7b561a Binary files /dev/null and b/seabug-contracts-0.1.0.tgz differ diff --git a/spago-packages.nix b/spago-packages.nix index 35d3b6a..f2ff121 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -5,6 +5,30 @@ let inputs = { + "aeson" = pkgs.stdenv.mkDerivation { + name = "aeson"; + version = "286862a975f4bafbef15540c365bbbb0480e0bf7"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-aeson.git"; + rev = "286862a975f4bafbef15540c365bbbb0480e0bf7"; + sha256 = "1d5h9n9f2qk8hjzqmhjfzwf86x3y60g3cm13gyvm5aaqjraaksvg"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "aeson-helpers" = pkgs.stdenv.mkDerivation { + name = "aeson-helpers"; + version = "44d0dae060cf78babd4534320192b58c16a6f45b"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-bridge-aeson-helpers.git"; + rev = "44d0dae060cf78babd4534320192b58c16a6f45b"; + sha256 = "1fgvaqvd9145zz5xw3fsa5vm75kp6bxcwa2nzq1dx2367h3a0zl0"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "aff" = pkgs.stdenv.mkDerivation { name = "aff"; version = "v6.0.0"; @@ -175,11 +199,11 @@ let "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; - version = "a83d75e852571e6a8ad2e60c449f198e1b3270a2"; + version = "32194c502e4a068bf99388b05c708f81612d7541"; src = pkgs.fetchgit { url = "https://github.com/Plutonomicon/cardano-transaction-lib.git"; - rev = "a83d75e852571e6a8ad2e60c449f198e1b3270a2"; - sha256 = "1jb54l2a9s4fvyl459vcls5zmify269ma51v6n2xb2pqn0zwa2zg"; + rev = "32194c502e4a068bf99388b05c708f81612d7541"; + sha256 = "0fv5qynwazs80nzs7slqpwvjk5447x2r5n2wwmy1mvydqcahhl2h"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -1073,6 +1097,18 @@ let installPhase = "ln -s $src $out"; }; + "sequences" = pkgs.stdenv.mkDerivation { + name = "sequences"; + version = "v3.0.2"; + src = pkgs.fetchgit { + url = "https://github.com/hdgarrood/purescript-sequences"; + rev = "1f1d828ef30070569c812d0af23eb7253bb1e990"; + sha256 = "0mc0jjs1119c2nyd08yhdmliq3s47lhrdknhziga3lnbzja889k4"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "spec" = pkgs.stdenv.mkDerivation { name = "spec"; version = "v5.0.1"; @@ -1085,6 +1121,18 @@ let installPhase = "ln -s $src $out"; }; + "spec-quickcheck" = pkgs.stdenv.mkDerivation { + name = "spec-quickcheck"; + version = "v4.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/purescript-spec/purescript-spec-quickcheck.git"; + rev = "c2991f475b8fa11de8b68bcb5895b36be04d1e82"; + sha256 = "01xcbfyqzax9c5najbfy12q0nvfklfm37llj2vkmi3wgkskg4prz"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "st" = pkgs.stdenv.mkDerivation { name = "st"; version = "v5.0.1"; @@ -1121,6 +1169,18 @@ let installPhase = "ln -s $src $out"; }; + "text-encoding" = pkgs.stdenv.mkDerivation { + name = "text-encoding"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/AlexaDeWit/purescript-text-encoding.git"; + rev = "609ea0916f6817971d4a6c11b991b59715aaa096"; + sha256 = "1r6ihj6m6ahp1cjf4i25pq9a00r2mvgrd8794xiapzsaigljz42c"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "these" = pkgs.stdenv.mkDerivation { name = "these"; version = "v5.0.0"; diff --git a/spago.dhall b/spago.dhall index 6d2145c..326bced 100644 --- a/spago.dhall +++ b/spago.dhall @@ -2,8 +2,45 @@ Welcome to a Spago project! You can edit this file as you like. -} -{ name = "ctl-package-example" -, dependencies = ["aff", "cardano-transaction-lib", "identity"] +{ name = "seabug-contract" +, dependencies = + [ "aeson" + , "aeson-helpers" + , "aff" + , "aff-promise" + , "affjax" + , "argonaut" + , "argonaut-codecs" + , "arrays" + , "bifunctors" + , "bigints" + , "cardano-transaction-lib" + , "const" + , "control" + , "debug" + , "effect" + , "either" + , "exceptions" + , "foldable-traversable" + , "http-methods" + , "maybe" + , "monad-logger" + , "mote" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "parallel" + , "partial" + , "prelude" + , "random" + , "spec" + , "strings" + , "text-encoding" + , "transformers" + , "tuples" + , "uint" + ] , packages = ./packages.dhall , sources = [ "exe/**/*.purs", "src/**/*.purs", "test/**/*.purs" ] } diff --git a/src/Seabug/CallContract.purs b/src/Seabug/CallContract.purs index 81005ab..7a32301 100644 --- a/src/Seabug/CallContract.purs +++ b/src/Seabug/CallContract.purs @@ -1,41 +1,32 @@ module Seabug.CallContract ( callMarketPlaceBuy + , callMarketPlaceFetchNft , callMarketPlaceListNft - , callMarketPlaceBuyTest + , callMint ) where -import Contract.Prelude +import Contract.Prelude hiding (null) -import Cardano.Types.Value as Cardano.Types.Value import Contract.Address (Slot(Slot)) import Contract.Monad ( ConfigParams(ConfigParams) , ContractConfig - , LogLevel(Debug) - , defaultSlotConfig , mkContractConfig , runContract , runContract_ ) import Contract.Numeric.Natural (toBigInt) -import Contract.Prim.ByteArray - ( byteArrayToHex - , hexToByteArray - ) -import Contract.Scripts - ( ed25519KeyHashToBytes - , ed25519KeyHashFromBytes - , scriptHashFromBech32 - , scriptHashToBech32Unsafe - ) +import Contract.Prim.ByteArray (byteArrayToHex, hexToByteArray) import Contract.Transaction - ( TransactionInput(TransactionInput) + ( TransactionInput(..) , TransactionOutput(TransactionOutput) + , awaitTxConfirmed ) import Contract.Value ( CurrencySymbol , TokenName , Value + , currencyMPSHash , flattenNonAdaAssets , getCurrencySymbol , getTokenName @@ -44,39 +35,75 @@ import Contract.Value ) import Control.Promise (Promise) import Control.Promise as Promise -import Data.Array (singleton) import Data.BigInt (BigInt) import Data.BigInt as BigInt -import Data.Identity (Identity(Identity)) -import Data.List (toUnfoldable) +import Data.Log.Level (LogLevel(..)) +import Data.Nullable (Nullable, notNull, null) import Data.Tuple.Nested ((/\)) import Data.UInt as UInt import Effect (Effect) import Effect.Aff (error) import Effect.Class (liftEffect) import Effect.Exception (Error) -import Metadata.Seabug (SeabugMetadata(SeabugMetadata)) -import Metadata.Seabug.Share (unShare) import Partial.Unsafe (unsafePartial) -import Plutus.ToPlutusType (toPlutusType) +import Plutus.Conversion (fromPlutusAddress) +import Seabug.Contract.CnftMint (mintCnft) +import Seabug.Contract.Common (NftResult) import Seabug.Contract.MarketPlaceBuy (marketplaceBuy) -import Seabug.Contract.MarketPlaceListNft (ListNftResult, marketPlaceListNft) +import Seabug.Contract.MarketPlaceFetchNft (marketPlaceFetchNft) +import Seabug.Contract.MarketPlaceListNft (marketPlaceListNft) +import Seabug.Contract.Mint (mintWithCollection) +import Seabug.Metadata.Share (unShare) +import Seabug.Metadata.Types (SeabugMetadata(SeabugMetadata)) import Seabug.Types - ( NftCollection(NftCollection) + ( MintCnftParams + , MintParams + , NftCollection(NftCollection) , NftData(NftData) , NftId(NftId) ) -import Serialization.Address (addressBech32, intToNetworkId) +import Serialization.Address (NetworkId, addressBech32, intToNetworkId) +import Serialization.Hash + ( ed25519KeyHashToBytes + , ed25519KeyHashFromBytes + , scriptHashFromBech32 + , scriptHashToBech32Unsafe + ) +import Types.BigNum as BigNum import Types.Natural as Nat -import Types.UsedTxOuts (newUsedTxOuts) import Wallet (mkNamiWalletAff) --- | Exists temporarily for testing purposes -callMarketPlaceBuyTest :: String -> Effect (Promise String) -callMarketPlaceBuyTest = Promise.fromAff <<< pure +callMint :: ContractConfiguration -> MintArgs -> Effect (Promise Unit) +callMint cfg args = Promise.fromAff do + contractConfig <- buildContractConfig cfg + mintCnftParams /\ mintParams <- liftEffect $ liftEither $ buildMintArgs args + runContract contractConfig $ do + log "Minting cnft..." + txHash /\ cnft <- mintCnft mintCnftParams + log $ "Waiting for confirmation of cnft transaction: " <> show txHash + awaitTxConfirmed txHash + log $ "Cnft transaction confirmed: " <> show txHash + log $ "Minted cnft: " <> show cnft + log "Minting sgNft..." + sgNftTxHash <- mintWithCollection cnft mintParams + log $ "Waiting for confirmation of nft transaction: " <> show sgNftTxHash + awaitTxConfirmed sgNftTxHash + log $ "Nft transaction confirmed: " <> show sgNftTxHash + +callMarketPlaceFetchNft + :: ContractConfiguration + -> TransactionInputOut + -> Effect (Promise (Nullable ListNftResultOut)) +callMarketPlaceFetchNft cfg args = Promise.fromAff do + contractConfig <- buildContractConfig cfg + txInput <- liftEffect $ liftEither $ buildTransactionInput args + runContract contractConfig (marketPlaceFetchNft txInput) >>= case _ of + Nothing -> pure null + Just nftResult -> pure $ notNull $ + buildNftList (unwrap contractConfig).networkId nftResult -- | Calls Seabugs marketplaceBuy and takes care of converting data types. --- Returns a JS promise holding no data. +-- | Returns a JS promise holding no data. callMarketPlaceBuy :: ContractConfiguration -> BuyNftArgs -> Effect (Promise Unit) callMarketPlaceBuy cfg args = Promise.fromAff do @@ -85,13 +112,13 @@ callMarketPlaceBuy cfg args = Promise.fromAff do runContract_ contractConfig (marketplaceBuy nftData) -- | Calls Seabugs marketPlaceListNft and takes care of converting data types. --- Returns a JS promise holding nft listings. +-- | Returns a JS promise holding nft listings. callMarketPlaceListNft :: ContractConfiguration -> Effect (Promise (Array ListNftResultOut)) callMarketPlaceListNft cfg = Promise.fromAff do contractConfig <- buildContractConfig cfg listnft <- runContract contractConfig marketPlaceListNft - pure $ buildNftList <$> listnft + pure $ buildNftList (unwrap contractConfig).networkId <$> listnft -- | Configuation needed to call contracts from JS. type ContractConfiguration = @@ -106,7 +133,7 @@ type ContractConfiguration = , datumCacheSecureConn :: Boolean , networkId :: Int , projectId :: String - , logLevel :: LogLevel + , logLevel :: String -- Trace | Debug | Info | Warn | Error } type BuyNftArgs = @@ -127,12 +154,13 @@ type BuyNftArgs = } } --- Placeholder for types I'm not sure how should we represent on frontend. +type TransactionInputOut = { transactionId :: String, inputIndex :: Int } + type ValueOut = Array { currencySymbol :: String, tokenName :: String, amount :: BigInt } type ListNftResultOut = - { input :: { transactionId :: String, inputIndex :: Int } + { input :: TransactionInputOut , output :: { address :: String, value :: ValueOut, dataHash :: String } , metadata :: { seabugMetadata :: @@ -144,7 +172,7 @@ type ListNftResultOut = , authorPkh :: String -- PubKeyHash , authorShare :: BigInt -- Share , marketplaceScript :: String -- ValidatorHash - , marketplaceShare :: BigInt -- share + , marketplaceShare :: BigInt -- Share , ownerPkh :: String -- PubKeyHash , ownerPrice :: BigInt --Natural } @@ -152,6 +180,14 @@ type ListNftResultOut = } } +type MintArgs = + { imageUri :: String + , tokenNameString :: String + , name :: String + , description :: String + , price :: BigInt -- Natural + } + buildContractConfig :: ContractConfiguration -> Aff (ContractConfig (projectId :: String)) buildContractConfig cfg = do @@ -163,6 +199,8 @@ buildContractConfig cfg = do $ UInt.fromInt' cfg.datumCachePort networkId <- liftM (error "Invalid network id") $ intToNetworkId cfg.networkId + logLevel <- liftM (error "Invalid log level") + $ stringToLogLevel cfg.logLevel wallet <- Just <$> mkNamiWalletAff mkContractConfig $ ConfigParams @@ -182,19 +220,29 @@ buildContractConfig cfg = do , secure: cfg.serverSecureConn } , networkId: networkId - , slotConfig: defaultSlotConfig - , logLevel: cfg.logLevel + , logLevel: logLevel , extraConfig: { projectId: cfg.projectId } , wallet } -buildNftList :: ListNftResult -> ListNftResultOut +stringToLogLevel :: String -> Maybe LogLevel +stringToLogLevel "Trace" = Just Trace +stringToLogLevel "Debug" = Just Debug +stringToLogLevel "Info" = Just Info +stringToLogLevel "Warn" = Just Warn +stringToLogLevel "Error" = Just Error +stringToLogLevel _ = Nothing + +buildNftList :: NetworkId -> NftResult -> ListNftResultOut buildNftList + network { input: TransactionInput input, output: TransactionOutput output, metadata } = let transactionId = byteArrayToHex $ unwrap input.transactionId inputIndex = UInt.toInt input.index - address = addressBech32 output.address + -- TODO: What do we do if this fails? + address = + addressBech32 $ unsafePartial $ fromPlutusAddress network output.address dataHash = fromMaybe mempty $ byteArrayToHex <<< unwrap <$> output.dataHash ipfsHash = metadata.ipfsHash seabugMetadata = convertSeabugMetaData metadata.seabugMetadata @@ -204,12 +252,8 @@ buildNftList , metadata: { ipfsHash, seabugMetadata } } where - convertValue :: Cardano.Types.Value.Value -> ValueOut - convertValue v = - let - (Identity val) = toPlutusType v - in - mkValueRecord <$> flattenNonAdaAssets val + convertValue :: Value -> ValueOut + convertValue val = mkValueRecord <$> flattenNonAdaAssets val mkValueRecord :: (CurrencySymbol /\ TokenName /\ BigInt) @@ -222,18 +266,20 @@ buildNftList convertSeabugMetaData :: SeabugMetadata -> _ convertSeabugMetaData (SeabugMetadata m) = - { policyId: scriptHashToBech32Unsafe "policy_vkh" $ unwrap m.policyId -- or the prefix should just be 'script' - , mintPolicy: byteArrayToHex m.mintPolicy - , collectionNftCS: byteArrayToHex $ Cardano.Types.Value.getCurrencySymbol $ - m.collectionNftCS + { policyId: scriptHashToBech32Unsafe "policy_vkh" $ unwrap $ + currencyMPSHash m.policyId -- or the prefix should just be 'script' + , mintPolicy: m.mintPolicy + , collectionNftCS: byteArrayToHex $ getCurrencySymbol m.collectionNftCS , collectionNftTN: byteArrayToHex $ getTokenName m.collectionNftTN , lockingScript: scriptHashToBech32Unsafe "script" $ unwrap m.lockingScript - , authorPkh: byteArrayToHex $ ed25519KeyHashToBytes $ unwrap m.authorPkh + , authorPkh: byteArrayToHex $ unwrap $ ed25519KeyHashToBytes $ unwrap + m.authorPkh , authorShare: unShare m.authorShare , marketplaceScript: scriptHashToBech32Unsafe "script" $ unwrap m.marketplaceScript , marketplaceShare: unShare m.marketplaceShare - , ownerPkh: byteArrayToHex $ ed25519KeyHashToBytes $ unwrap m.ownerPkh + , ownerPkh: byteArrayToHex $ unwrap $ ed25519KeyHashToBytes $ unwrap + m.ownerPkh , ownerPrice: toBigInt m.ownerPrice } @@ -252,7 +298,7 @@ buildNftData { nftCollectionArgs, nftIdArgs } = do owner <- note (error $ "Invalid owner: " <> r.owner) $ wrap <<< wrap - <$> (ed25519KeyHashFromBytes =<< hexToByteArray r.owner) + <$> (ed25519KeyHashFromBytes <<< wrap =<< hexToByteArray r.owner) pure $ NftId { collectionNftTn: tn , price @@ -266,7 +312,7 @@ buildNftData { nftCollectionArgs, nftIdArgs } = do lockLockupEnd <- note (error $ "Invalid nft lockLockupEnd: " <> show r.lockLockupEnd) $ Slot - <$> (UInt.fromString $ BigInt.toString r.lockLockupEnd) + <$> (BigNum.fromString $ BigInt.toString r.lockLockupEnd) lockingScript <- note (error $ "Invalid nft lockingScript: " <> r.lockingScript) $ wrap @@ -274,7 +320,7 @@ buildNftData { nftCollectionArgs, nftIdArgs } = do author <- note (error $ "Invalid author: " <> r.author) $ wrap <<< wrap - <$> (ed25519KeyHashFromBytes =<< hexToByteArray r.author) + <$> (ed25519KeyHashFromBytes <<< wrap =<< hexToByteArray r.author) authorShare <- note (error $ "Invalid authorShare: " <> show r.authorShare) $ Nat.fromBigInt r.authorShare daoScript <- note (error $ "Invalid nft daoScript: " <> r.daoScript) @@ -292,3 +338,37 @@ buildNftData { nftCollectionArgs, nftIdArgs } = do , daoScript , daoShare } + +buildMintArgs :: MintArgs -> Either Error (MintCnftParams /\ MintParams) +buildMintArgs + { imageUri + , tokenNameString + , name + , description + , price + } = do + price' <- note (error $ "Invalid price: " <> show price) + $ Nat.fromBigInt price + let + mintCnftParams = wrap { imageUri, tokenNameString, name, description } + -- TODO: Put these hard coded params in a better place, see + -- https://github.com/mlabs-haskell/seabug-contracts/issues/25 + mintParams = wrap + { authorShare: Nat.fromInt' 1000 + , daoShare: Nat.fromInt' 1000 + , price: price' + , lockLockup: BigInt.fromInt 5 + , lockLockupEnd: Slot $ BigNum.fromInt 5 + , feeVaultKeys: [] + } + pure (mintCnftParams /\ mintParams) + +buildTransactionInput :: TransactionInputOut -> Either Error TransactionInput +buildTransactionInput input = do + transactionId <- + note (error $ "Invalid transaction id: " <> input.transactionId) + $ wrap + <$> hexToByteArray input.transactionId + index <- note (error $ "Invalid input index: " <> show input.inputIndex) $ + UInt.fromInt' input.inputIndex + pure $ wrap { transactionId, index } diff --git a/src/Seabug/CnftMintPolicy.js b/src/Seabug/CnftMintPolicy.js new file mode 100644 index 0000000..25a7ba9 --- /dev/null +++ b/src/Seabug/CnftMintPolicy.js @@ -0,0 +1,6 @@ +exports._cnftMintingPolicy = { + mintingPolicy: { + getMintingPolicy: +"5908be010000323322333222323233223322323233322232333222323333333322222222323332223233332222323233223233322232323233223322323233333222223322332233223322332233223322332223003300200122232325335302f330050043333573466e1cd55cea8012400046601464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc060cd40988c8c8cccd5cd19b8735573aa004900011980f181b1aba15002302b357426ae8940088c98d4c158cd5ce02d02b82a82a09aab9e5001137540026ae854028cd409809cd5d0a804999aa816bae502c35742a010666aa05aeb940b0d5d0a80399a81301f9aba15006335026335505004875a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a8101919191999ab9a3370e6aae7540092000233502833503e75a6ae854008c10cd5d09aba25002232635305a3357380bc0b60b20b026aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a04c66a07ceb4d5d0a80118219aba135744a004464c6a60b466ae7017816c1641604d55cf280089baa001357426ae8940088c98d4c158cd5ce02d02b82a82a09aab9e5001137540026ae854010cd4099d71aba15003335026335505075c40026ae854008c0d4d5d09aba2500223263530523357380ac0a60a20a026ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d400520062301d3037357426aae79400c8cccd5cd19b875002480108c070c104d5d09aab9e500423333573466e1d400d20022301c302c357426aae7940148cccd5cd19b875004480008c07cdd71aba135573ca00c464c6a609a66ae7014413813012c1281241204d55cea80089baa001357426ae8940088c98d4c118cd5ce025023822822082309931a982299ab9c49010350543500046044135573ca00226ea80048c8894cd4c0b8ccd54c12448004c8cd413c88ccd4d402000c88008008004d4d401800488004cd4018894cd4c0c000840c840040bc8cc894cd4c0c4ccd5cd19b8f35302800222002353028001220020330321333573466e1cd4c0a000888004d4c0a0004880040cc0c840c8d4c03000488008010d4c024d4c01c00488008888888888802840c04cd5ce249115554784f206e6f7420636f6e73756d65640002f30210011221233001003002120012212330010030022001222222222212333333333300100b00a00900800700600500400300220012212330010030022001122123300100300212001122123300100300212001122123300100300212001212222300400521222230030052122223002005212222300100520011232230023758002640026aa070446666aae7c004940e08cd40dcc010d5d080118019aba200203023232323333573466e1cd55cea801a4000466600e6464646666ae68cdc39aab9d5002480008cc034c0b8d5d0a80119a8080151aba135744a004464c6a606866ae700e00d40cc0c84d55cf280089baa00135742a006666aa016eb94028d5d0a80119a8063ae357426ae8940088c98d4c0c0cd5ce01a01881781709aba25001135573ca00226ea800488848ccc00401000c00880048848cc00400c00880044cd54005d73ad112232230023756002640026aa06444646666aae7c008940cc8cd40c8cd540b8c018d55cea80118029aab9e500230043574400605626ae84004488c8c8cccd5cd19b875001480008d4020c014d5d09aab9e500323333573466e1d4009200225008232635302a33573805c05605205004e26aae7540044dd5000890911801001889100089000919191999ab9a3370e6aae7540092000233006300735742a0046eb4d5d09aba25002232635302433573805004a04604426aae7940044dd500091091980080180110009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931a981019ab9c02402101f01e1375400224464646666ae68cdc3a800a40084a00e46666ae68cdc3a8012400446a014600c6ae84d55cf280211999ab9a3370ea00690001280511931a981199ab9c02702402202102001f135573aa00226ea8004484888c00c0104488800844888004480048c8cccd5cd19b8750014800880188cccd5cd19b8750024800080188c98d4c06ccd5ce00f80e00d00c80c09aab9d37540022440042440024002464646464646666ae68cdc3a800a4018401646666ae68cdc3a80124014401a46666ae68cdc3a801a40104660166eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc034dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a9002119809180a1aba15009375c6ae84d5d1280491999ab9a3370ea00c90011180a180a9aba135573ca01646666ae68cdc3a803a400046026602c6ae84d55cf280611931a981019ab9c02402101f01e01d01c01b01a019018135573aa00826aae79400c4d55cf280109aab9e500113754002424444444600e01044244444446600c012010424444444600a010244444440082444444400644244444446600401201044244444446600201201040024646464646666ae68cdc3a800a400446660106eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d400920002300a300b357426aae7940188c98d4c044cd5ce00a80900800780709aab9d5003135744a00226aae7940044dd5000909118010019110911998008028020019000919191999ab9a3370ea0029001118031bae357426aae79400c8cccd5cd19b875002480008c020dd71aba135573ca008464c6a601666ae7003c0300280240204d55cea80089baa001212230020032122300100320011122232323333573466e1cd55cea80124000466aa016600c6ae854008c014d5d09aba25002232635300833573801801200e00c26aae7940044dd5000a4c240024002224424660020060042240029210350543100320013550062211222533535006001135350090032200122133353500b0052200230040023335530071200100500400111220021221223300100400312001122123300100300212001112323001001223300330020020011", + } +} diff --git a/src/Seabug/CnftMintPolicy.purs b/src/Seabug/CnftMintPolicy.purs new file mode 100644 index 0000000..535db90 --- /dev/null +++ b/src/Seabug/CnftMintPolicy.purs @@ -0,0 +1,24 @@ +module Seabug.CnftMintPolicy (mkCnftMintingPolicy) where + +import Contract.Prelude + +import Contract.Monad (Contract, liftContractE) +import Contract.PlutusData (toData) +import Contract.Scripts (MintingPolicy, applyArgs) +import Contract.Transaction (TransactionInput) +import Data.Argonaut (Json, JsonDecodeError) +import QueryM as QueryM +import Seabug.Helpers (jsonReader) + +mkCnftMintingPolicy + :: forall (r :: Row Type) + . TransactionInput + -> Contract r (Either QueryM.ClientError MintingPolicy) +mkCnftMintingPolicy oref = do + p <- liftContractE cnftMintingPolicy + applyArgs p [ toData oref ] + +cnftMintingPolicy :: Either JsonDecodeError MintingPolicy +cnftMintingPolicy = jsonReader "mintingPolicy" _cnftMintingPolicy + +foreign import _cnftMintingPolicy :: Json diff --git a/src/Seabug/Contract/CnftMint.purs b/src/Seabug/Contract/CnftMint.purs new file mode 100644 index 0000000..35d0f0e --- /dev/null +++ b/src/Seabug/Contract/CnftMint.purs @@ -0,0 +1,86 @@ +module Seabug.Contract.CnftMint where + +import Contract.Prelude + +import Contract.Address + ( getNetworkId + , ownPaymentPubKeyHash + , ownStakePubKeyHash + , payPubKeyHashBaseAddress + ) +import Contract.AuxiliaryData (setTxMetadata) +import Contract.Monad (Contract, liftContractM, liftedE, liftedM) +import Contract.Prim.ByteArray (hexToByteArray) +import Contract.ScriptLookups as Lookups +import Contract.Scripts (mintingPolicyHash) +import Contract.Transaction (TransactionHash, balanceAndSignTxE, submit) +import Contract.TxConstraints as Constraints +import Contract.Utxos (utxosAt) +import Contract.Value + ( CurrencySymbol + , TokenName + , mkTokenName + , scriptCurrencySymbol + , singleton + ) +import Data.Array (head) +import Data.Map as Map +import Data.NonEmpty as NonEmpty +import Metadata.Cip25 (Cip25Metadata(..), Cip25MetadataEntry(..)) +import Seabug.CnftMintPolicy (mkCnftMintingPolicy) +import Seabug.Types (MintCnftParams(..)) + +-- | Mint a collection NFT +mintCnft + :: forall (r :: Row Type) + . MintCnftParams + -> Contract r (TransactionHash /\ (CurrencySymbol /\ TokenName)) +mintCnft (MintCnftParams params) = do + owner <- liftedM "Cannot get PaymentPubKeyHash" ownPaymentPubKeyHash + ownerStake <- liftedM "Cannot get StakePubKeyHash" ownStakePubKeyHash + networkId <- getNetworkId + addr <- liftContractM "Cannot get user address" $ + payPubKeyHashBaseAddress networkId owner ownerStake + utxos <- liftedM "Cannot get user utxos" $ utxosAt addr + oref /\ _ <- liftContractM "Cannot find user utxo" + $ head + $ Map.toUnfoldableUnordered (unwrap utxos) + policy <- liftedE $ mkCnftMintingPolicy oref + curr <- liftedM "Could not get currency symbol" $ liftAff $ + scriptCurrencySymbol policy + -- TODO: figure out how to encode the token name (base64 maybe), see + -- https://github.com/mlabs-haskell/seabug-contracts/issues/26 + tn <- liftContractM "Invalid token name" + $ mkTokenName + =<< hexToByteArray params.tokenNameString + let + value = singleton curr tn one + lookups = mconcat + [ Lookups.mintingPolicy policy + , Lookups.unspentOutputs $ unwrap utxos + ] + + constraints :: Constraints.TxConstraints Unit Unit + constraints = mconcat + [ Constraints.mustMintValue value + , Constraints.mustSpendPubKeyOutput oref + , Constraints.mustPayToPubKeyAddress owner ownerStake value + ] + unbalancedTx <- liftedE $ Lookups.mkUnbalancedTx lookups constraints + policyHash <- liftedM "Could not get minting policy hash" $ liftAff $ + mintingPolicyHash policy + unbalancedTxWithMetadata <- setTxMetadata unbalancedTx $ Cip25Metadata + [ Cip25MetadataEntry + { policyId: policyHash + , assetName: tn + , imageUris: NonEmpty.singleton params.imageUri + , mediaType: Nothing + , description: [ params.name, params.description ] + , files: [] + } + ] + signedTx <- liftedE $ balanceAndSignTxE unbalancedTxWithMetadata + transactionHash <- submit signedTx + log $ "CNFT Mint transaction successfully submitted with hash: " + <> show transactionHash + pure (transactionHash /\ curr /\ tn) diff --git a/src/Seabug/Contract/Common.purs b/src/Seabug/Contract/Common.purs new file mode 100644 index 0000000..fc032c0 --- /dev/null +++ b/src/Seabug/Contract/Common.purs @@ -0,0 +1,12 @@ +module Seabug.Contract.Common + ( NftResult + ) where + +import Contract.Transaction (TransactionInput, TransactionOutput) +import Seabug.Metadata (FullSeabugMetadata) + +type NftResult = + { input :: TransactionInput + , output :: TransactionOutput + , metadata :: FullSeabugMetadata + } diff --git a/src/Seabug/Contract/MarketPlaceBuy.purs b/src/Seabug/Contract/MarketPlaceBuy.purs index b20383b..071e8e4 100644 --- a/src/Seabug/Contract/MarketPlaceBuy.purs +++ b/src/Seabug/Contract/MarketPlaceBuy.purs @@ -1,50 +1,34 @@ -module Seabug.Contract.MarketPlaceBuy - ( marketplaceBuy - , mkMarketplaceTx - ) where +module Seabug.Contract.MarketPlaceBuy (marketplaceBuy) where import Contract.Prelude -import Contract.Address - ( getNetworkId - , ownPaymentPubKeyHash - , payPubKeyHashBaseAddress +import Contract.Address (getNetworkId, ownPaymentPubKeyHash) +import Contract.Monad (Contract, liftContractE, liftContractM, liftedE, liftedM) +import Contract.Numeric.Natural (toBigInt) +import Contract.PlutusData + ( Datum(Datum) + , Redeemer(Redeemer) + , toData + , unitRedeemer ) - import Contract.ScriptLookups (UnattachedUnbalancedTx, mkUnbalancedTx) import Contract.ScriptLookups ( mintingPolicy - , otherScript + , validator , ownPaymentPubKeyHash , typedValidatorLookups , unspentOutputs ) as ScriptLookups -import Contract.Monad - ( Contract - , liftContractM - , liftContractE - , liftedE - , liftedM - ) -import Contract.Numeric.Natural (toBigInt) -import Contract.PlutusData - ( Datum(Datum) - , Redeemer(Redeemer) - , toData - , unitRedeemer - ) -import Contract.ProtocolParameters.Alonzo (minAdaTxOut) -import Contract.Scripts (applyArgs, typedValidatorEnterpriseAddress) +import Contract.Scripts (typedValidatorEnterpriseAddress) import Contract.Transaction - ( BalancedSignedTransaction(BalancedSignedTransaction) - , TxOut - , balanceAndSignTx + ( TransactionOutput(TransactionOutput) + , balanceAndSignTxE , submit ) import Contract.TxConstraints ( TxConstraints , mustMintValueWithRedeemer - , mustPayToOtherScript + , mustPayToScript , mustPayWithDatumToPubKey , mustSpendScriptOutput ) @@ -52,104 +36,85 @@ import Contract.Utxos (utxosAt) import Contract.Value as Value import Contract.Wallet (getWalletAddress) import Data.Array (find) as Array +import Data.Bifunctor (lmap) import Data.BigInt (BigInt, fromInt) -import Data.Identity (Identity(Identity)) import Data.Map (insert, toUnfoldable) -import Plutus.ToPlutusType (toPlutusType) +import Seabug.Contract.Util (minAdaOnlyUTxOValue, setSeabugMetadata) import Seabug.MarketPlace (marketplaceValidator) -import Seabug.MintingPolicy (mintingPolicy) -import Seabug.Token (mkTokenName) +import Seabug.Metadata.Share (maxShare) +import Seabug.MintingPolicy (mkMintingPolicy, mkTokenName) import Seabug.Types ( MarketplaceDatum(MarketplaceDatum) , MintAct(ChangeOwner) - , NftData(NftData) + , NftData(..) , NftId(NftId) ) -import Types.TokenName (TokenName) --- TODO docstring +-- | Attempts to submit a transaction where the current user purchases +-- | the passed NFT. marketplaceBuy :: forall (r :: Row Type). NftData -> Contract r Unit marketplaceBuy nftData = do - unattachedBalancedTx /\ curr /\ newName <- mkMarketplaceTx nftData - -- `balanceAndSignTx` does the following: - -- 1) Balance a transaction - -- 2) Reindex `Spend` redeemers after finalising transaction inputs. - -- 3) Attach datums and redeemers to transaction. - -- 3) Sign tx, returning the Cbor-hex encoded `ByteArray`. - BalancedSignedTransaction { signedTxCbor } <- liftedM - "marketplaceBuy: Cannot balance, reindex redeemers, attach datums/redeemers\ - \ and sign" - (balanceAndSignTx unattachedBalancedTx) - -- Submit transaction using Cbor-hex encoded `ByteArray` - transactionHash <- submit signedTxCbor + unattachedBalancedTx /\ curr /\ newName <- mkMarketplaceBuyTx nftData + signedTx <- liftedE + ( lmap + ( \e -> + "marketplaceBuy: Cannot balance, reindex redeemers, attach datums/redeemers\ + \ and sign: " <> show e + ) + <$> balanceAndSignTxE unattachedBalancedTx + ) + transactionHash <- submit signedTx log $ "marketplaceBuy: Transaction successfully submitted with hash: " <> show transactionHash log $ "marketplaceBuy: Buy successful: " <> show (curr /\ newName) -- https://github.com/mlabs-haskell/plutus-use-cases/blob/927eade6aa9ad37bf2e9acaf8a14ae2fc304b5ba/mlabs/src/Mlabs/EfficientNFT/Contract/MarketplaceBuy.hs -- rev: 2c9ce295ccef4af3f3cb785982dfe554f8781541 --- The `MintingPolicy` may be decoded as Json, although I'm not sure as we don't --- have `mkMintingPolicyScript`. Otherwise, it's an policy that hasn't been --- applied to arguments. See `Seabug.Token.policy` --- TODO docstring -mkMarketplaceTx +mkMarketplaceBuyTx :: forall (r :: Row Type) . NftData -> Contract r (UnattachedUnbalancedTx /\ Value.CurrencySymbol /\ Value.TokenName) -mkMarketplaceTx (NftData nftData) = do +mkMarketplaceBuyTx (NftData nftData) = do let nftCollection = unwrap nftData.nftCollection pkh <- liftedM "marketplaceBuy: Cannot get PaymentPubKeyHash" ownPaymentPubKeyHash - policy' <- liftedE $ pure mintingPolicy - policy <- liftedE $ applyArgs policy' - [ toData nftCollection.collectionNftCs - , toData nftCollection.lockingScript - , toData nftCollection.author - , toData nftCollection.authorShare - , toData nftCollection.daoScript - , toData nftCollection.daoShare - ] + policy <- liftedE $ mkMintingPolicy $ wrap nftCollection curr <- liftedM "marketplaceBuy: Cannot get CurrencySymbol" - $ Value.scriptCurrencySymbol - $ policy - -- curr <- liftContractM "marketplaceBuy: Cannot get CurrencySymbol" - -- $ mkCurrencySymbol - -- $ Value.getCurrencySymbol currSym + $ liftAff + $ Value.scriptCurrencySymbol policy - -- Read in the typed validator: marketplaceValidator' <- unwrap <$> liftContractE marketplaceValidator networkId <- getNetworkId let nft = nftData.nftId nft' = unwrap nft newNft = NftId nft' { owner = pkh } - scriptAddr = - typedValidatorEnterpriseAddress networkId $ wrap marketplaceValidator' + scriptAddr <- + liftContractM "marketplaceBuy: Cannot convert validator hash to address" + $ typedValidatorEnterpriseAddress networkId + $ wrap marketplaceValidator' oldName <- liftedM "marketplaceBuy: Cannot hash old token" $ mkTokenName nft newName <- liftedM "marketplaceBuy: Cannot hash new token" $ mkTokenName newNft let oldNftValue = Value.singleton curr oldName $ negate one - newNftValue = Value.singleton curr oldName one + newNftValue = Value.singleton curr newName one nftPrice = nft'.price valHash = marketplaceValidator'.validatorHash mintRedeemer = Redeemer $ toData $ ChangeOwner nft pkh - containsNft :: forall (a :: Type). (a /\ TxOut) -> Boolean - containsNft (_ /\ tx) = - let - (Identity amt) = toPlutusType (unwrap tx).amount - in - Value.valueOf amt curr oldName == one + containsNft :: forall (a :: Type). (a /\ TransactionOutput) -> Boolean + containsNft (_ /\ TransactionOutput out) = + Value.valueOf out.amount curr oldName == one getShare :: BigInt -> BigInt - getShare share = (toBigInt nftPrice * share) `div` fromInt 10_000 + getShare share = (toBigInt nftPrice * share) `div` fromInt maxShare shareToSubtract :: BigInt -> BigInt shareToSubtract v - | v < unwrap minAdaTxOut = zero + | v < minAdaOnlyUTxOValue = zero | otherwise = v filterLowValue @@ -157,7 +122,7 @@ mkMarketplaceTx (NftData nftData) = do -> (Value.Value -> TxConstraints Unit Unit) -> TxConstraints Unit Unit filterLowValue v t - | v < unwrap minAdaTxOut = mempty + | v < minAdaOnlyUTxOValue = mempty | otherwise = t (Value.lovelaceValueOf v) authorShare = getShare $ toBigInt nftCollection.authorShare @@ -167,7 +132,7 @@ mkMarketplaceTx (NftData nftData) = do - shareToSubtract authorShare - shareToSubtract daoShare datum = Datum $ toData $ curr /\ oldName - userAddr <- liftedM "marketplaceBuy: Cannot get user addr" $ getWalletAddress + userAddr <- liftedM "marketplaceBuy: Cannot get user addr" getWalletAddress userUtxos <- liftedM "marketplaceBuy: Cannot get user Utxos" $ utxosAt userAddr scriptUtxos <- @@ -178,20 +143,19 @@ mkMarketplaceTx (NftData nftData) = do $ toUnfoldable $ unwrap scriptUtxos let + utxosForTx = insert utxo utxoIndex $ unwrap userUtxos lookup = mconcat [ ScriptLookups.mintingPolicy policy , ScriptLookups.typedValidatorLookups $ wrap marketplaceValidator' - , ScriptLookups.otherScript marketplaceValidator'.validator - , ScriptLookups.unspentOutputs $ insert utxo utxoIndex $ unwrap userUtxos + , ScriptLookups.validator marketplaceValidator'.validator + , ScriptLookups.unspentOutputs utxosForTx , ScriptLookups.ownPaymentPubKeyHash pkh ] - minAdaVal = Value.lovelaceValueOf $ fromInt 2_000_000 - constraints = filterLowValue daoShare - (mustPayToOtherScript nftCollection.daoScript datum) + (mustPayToScript nftCollection.daoScript datum) <> filterLowValue authorShare (mustPayWithDatumToPubKey nftCollection.author datum) @@ -199,16 +163,15 @@ mkMarketplaceTx (NftData nftData) = do [ mustMintValueWithRedeemer mintRedeemer (newNftValue <> oldNftValue) , mustSpendScriptOutput utxo unitRedeemer , mustPayWithDatumToPubKey nft'.owner datum ownerShare - , mustPayToOtherScript + , mustPayToScript valHash ( Datum $ toData $ MarketplaceDatum { getMarketplaceDatum: curr /\ newName } ) - ( newNftValue <> minAdaVal - ) + newNftValue ] - -- Created unbalanced tx which stripped datums and redeemers with tx inputs, - -- the datums and redeemers will be reattached using a server with redeemers - -- reindexed also. txDatumsRedeemerTxIns <- liftedE $ mkUnbalancedTx lookup constraints - pure $ txDatumsRedeemerTxIns /\ curr /\ newName + txWithMetadata <- + setSeabugMetadata (wrap nftData { nftId = newNft }) curr + txDatumsRedeemerTxIns + pure $ txWithMetadata /\ curr /\ newName diff --git a/src/Seabug/Contract/MarketPlaceFetchNft.purs b/src/Seabug/Contract/MarketPlaceFetchNft.purs new file mode 100644 index 0000000..493035b --- /dev/null +++ b/src/Seabug/Contract/MarketPlaceFetchNft.purs @@ -0,0 +1,38 @@ +-- | Contract to fetch a single NFT +module Seabug.Contract.MarketPlaceFetchNft + ( marketPlaceFetchNft + ) where + +import Contract.Prelude + +import Contract.Monad (Contract, liftContractM, liftedE, liftedM, logWarn') +import Contract.PlutusData (fromData, getDatumByHash) +import Contract.Transaction (TransactionInput, TransactionOutput(..)) +import Contract.Utxos (getUtxo) +import Control.Monad.Reader (asks) +import Seabug.Contract.Common (NftResult) +import Seabug.Metadata (getFullSeabugMetadataWithBackoff) +import Seabug.Types (MarketplaceDatum(..)) + +-- | Fetch the info for a single NFT identified by a utxo +-- | (`TransactionInput`). Returns `Nothing` if the given transaction +-- | input has been spent (for example if the NFT has been bought). +marketPlaceFetchNft + :: forall (r :: Row Type) + . TransactionInput + -> Contract (projectId :: String | r) (Maybe NftResult) +marketPlaceFetchNft ref = do + getUtxo ref >>= case _ of + Nothing -> do + logWarn' "Could not find NFT utxo, it may have been spent" + pure Nothing + Just output@(TransactionOutput nftTxOut) -> do + datumHash <- liftContractM "Datum hash not available for NFT" + nftTxOut.dataHash + MarketplaceDatum { getMarketplaceDatum: datum } <- + liftedM "Could not get datum for NFT" $ getDatumByHash datumHash <#> + (_ >>= unwrap >>> fromData) + projectId <- asks $ unwrap >>> _.projectId + metadata <- liftedE $ liftAff $ + getFullSeabugMetadataWithBackoff datum projectId + pure $ Just { input: ref, output, metadata } diff --git a/src/Seabug/Contract/MarketPlaceListNft.purs b/src/Seabug/Contract/MarketPlaceListNft.purs index b985d35..1c19cde 100644 --- a/src/Seabug/Contract/MarketPlaceListNft.purs +++ b/src/Seabug/Contract/MarketPlaceListNft.purs @@ -1,59 +1,63 @@ -- | Helper to list the utxo with relevant NFT at the market validator script module Seabug.Contract.MarketPlaceListNft - ( ListNftResult - , marketPlaceListNft + ( marketPlaceListNft ) where import Contract.Prelude import Contract.Address (getNetworkId, typedValidatorEnterpriseAddress) -import Contract.Monad (Contract, liftContractE, liftedM) -import Contract.PlutusData (fromData, getDatumByHash) -import Contract.Transaction - ( TransactionInput - , TransactionOutput(TransactionOutput) - ) +import Contract.Monad (Contract, liftContractE, liftContractM, liftedM) +import Contract.Numeric.Natural as Natural +import Contract.PlutusData (fromData, getDatumsByHashes) +import Contract.Transaction (TransactionOutput(TransactionOutput)) import Contract.Utxos (utxosAt) import Contract.Value (valueOf) import Control.Alternative (guard) import Control.Monad.Maybe.Trans (MaybeT(MaybeT), runMaybeT) -import Data.Array (catMaybes) -import Data.Identity (Identity(Identity)) +import Control.Monad.Reader (asks) +import Control.Parallel (parTraverse) +import Data.Array (catMaybes, mapMaybe) import Data.Map as Map -import Plutus.ToPlutusType (toPlutusType) +import Seabug.Contract.Common (NftResult) +import Seabug.Contract.Util (minAdaOnlyUTxOValue) import Seabug.MarketPlace (marketplaceValidator) -import Seabug.Metadata (FullSeabugMetadata, getFullSeabugMetadata) +import Seabug.Metadata (getFullSeabugMetadataWithBackoff) import Seabug.Types (MarketplaceDatum(MarketplaceDatum)) -type ListNftResult = - { input :: TransactionInput - , output :: TransactionOutput - , metadata :: FullSeabugMetadata - } - -- | Lists the utxos at the script address that contain a datum of type -- | `MarketplaceDatum` with unit value. It currently doesn't have any logic -- | on matching `CurrencySymbol` and `TokenName`. marketPlaceListNft :: forall (r :: Row Type) - . Contract (projectId :: String | r) (Array ListNftResult) + . Contract (projectId :: String | r) (Array NftResult) marketPlaceListNft = do marketplaceValidator' <- unwrap <$> liftContractE marketplaceValidator networkId <- getNetworkId - let - scriptAddr = - typedValidatorEnterpriseAddress networkId $ wrap marketplaceValidator' + projectId <- asks $ unwrap >>> _.projectId + scriptAddr <- + liftContractM "marketPlaceListNft: Cannot convert validator hash to address" + $ typedValidatorEnterpriseAddress networkId + $ wrap marketplaceValidator' scriptUtxos <- Map.toUnfoldable <<< unwrap <$> - liftedM "marketPlaceListNft: Cannot get script Utxos" (utxosAt scriptAddr) - withMetadata <- for scriptUtxos $ + liftedM "marketPlaceListNft: Cannot get script Utxos" + (utxosAt scriptAddr) + datums <- getDatumsByHashes + $ mapMaybe (snd >>> unwrap >>> _.dataHash) scriptUtxos + withMetadata <- liftAff $ (flip parTraverse) scriptUtxos $ \(input /\ output@(TransactionOutput out)) -> runMaybeT $ do - datumHash <- MaybeT $ pure $ out.dataHash - plutusData <- MaybeT $ getDatumByHash datumHash MarketplaceDatum { getMarketplaceDatum: curr /\ name } <- - MaybeT $ pure $ fromData plutusData - let (Identity amt) = toPlutusType out.amount - guard $ valueOf amt curr name == one - metadata <- MaybeT $ map hush $ getFullSeabugMetadata $ curr /\ name + MaybeT $ pure $ (fromData <<< unwrap) + =<< (_ `Map.lookup` datums) + =<< out.dataHash + guard $ valueOf out.amount curr name == one + metadata <- MaybeT $ map hush $ + getFullSeabugMetadataWithBackoff (curr /\ name) projectId + -- TODO: this is a temporary solution to only show NFTs known + -- to work. This filter catches a couple new nfts whose price + -- I put too low. The old nfts are caught above because their + -- metadata won't be parsed. + guard $ (unwrap metadata.seabugMetadata # _.ownerPrice) >= + (Natural.fromBigInt' minAdaOnlyUTxOValue) pure { input, output, metadata } pure $ catMaybes withMetadata diff --git a/src/Seabug/Contract/Mint.purs b/src/Seabug/Contract/Mint.purs new file mode 100644 index 0000000..c506db2 --- /dev/null +++ b/src/Seabug/Contract/Mint.purs @@ -0,0 +1,123 @@ +module Seabug.Contract.Mint where + +import Contract.Prelude + +import Contract.Address + ( Slot + , getNetworkId + , ownPaymentPubKeyHash + , ownStakePubKeyHash + , payPubKeyHashBaseAddress + ) +import Contract.Chain (ChainTip(..), Tip(..), getTip) +import Contract.Monad (Contract, liftContractE, liftContractM, liftedE, liftedM) +import Contract.PlutusData (toData) +import Contract.ScriptLookups as Lookups +import Contract.Scripts (validatorHash) +import Contract.Time (from, getEraSummaries, getSystemStart, slotToPosixTime) +import Contract.Transaction (TransactionHash, balanceAndSignTxE, submit) +import Contract.TxConstraints as Constraints +import Contract.Utxos (utxosAt) +import Contract.Value + ( CurrencySymbol + , TokenName + , scriptCurrencySymbol + , singleton + ) +import Seabug.Contract.Util (setSeabugMetadata) +import Seabug.Lock (mkLockScript) +import Seabug.MarketPlace (marketplaceValidator) +import Seabug.MintingPolicy as MintingPolicy +import Seabug.Types + ( LockDatum(..) + , MarketplaceDatum(..) + , MintAct(..) + , MintParams(..) + , NftCollection(..) + , NftData(..) + , NftId(..) + ) +import Types.BigNum as BigNum + +-- | TODO: Use `currentSlot` instead, see +-- | https://github.com/mlabs-haskell/seabug-contracts/issues/27 +slotFromTip :: Tip -> Slot +slotFromTip TipAtGenesis = wrap $ BigNum.zero +slotFromTip (Tip (ChainTip { slot })) = slot + +-- | Mint the self-governed NFT for the given collection. +mintWithCollection + :: forall (r :: Row Type) + . CurrencySymbol /\ TokenName + -> MintParams + -> Contract r TransactionHash +mintWithCollection + (collectionNftCs /\ collectionNftTn) + ( MintParams + { price, lockLockup, lockLockupEnd, authorShare, daoShare } + ) = do + owner <- liftedM "Cannot get PaymentPubKeyHash" ownPaymentPubKeyHash + ownerStake <- liftedM "Cannot get StakePubKeyHash" ownStakePubKeyHash + networkId <- getNetworkId + addr <- liftContractM "Cannot get user address" $ + payPubKeyHashBaseAddress networkId owner ownerStake + utxos <- liftedM "Cannot get user utxos" $ utxosAt addr + currentSlot <- slotFromTip <$> getTip + marketplaceValidator' <- unwrap <$> liftContractE marketplaceValidator + lockingScript <- liftedE $ mkLockScript collectionNftCs lockLockup + lockLockupEnd + lockingScriptHash <- liftedM "Could not get locking script hash" $ liftAff $ + validatorHash lockingScript + let + nft = NftId { collectionNftTn, price, owner } + collection = NftCollection + { collectionNftCs + , lockLockup + , lockLockupEnd + , lockingScript: lockingScriptHash + , author: owner + , authorShare + , daoScript: marketplaceValidator'.validatorHash + , daoShare + } + policy <- liftedE $ MintingPolicy.mkMintingPolicy collection + curr <- liftedM "Could not get currency symbol" $ liftAff $ + scriptCurrencySymbol policy + tn <- liftedM "Could not get token name" $ MintingPolicy.mkTokenName nft + eraSummaries <- getEraSummaries + systemStart <- getSystemStart + now <- liftedE $ liftAff $ liftEffect $ + slotToPosixTime eraSummaries systemStart currentSlot + let + nftValue = singleton curr tn one + lookups = mconcat + [ Lookups.mintingPolicy policy, Lookups.unspentOutputs (unwrap utxos) ] + + constraints :: Constraints.TxConstraints Unit Unit + constraints = mconcat + [ Constraints.mustMintValueWithRedeemer (wrap $ toData $ MintToken nft) + nftValue + , Constraints.mustPayToScript marketplaceValidator'.validatorHash + ( wrap $ toData $ MarketplaceDatum $ + { getMarketplaceDatum: curr /\ tn } + ) + nftValue + , Constraints.mustPayToScript lockingScriptHash + ( wrap $ toData $ LockDatum + { sgNft: curr + , entered: currentSlot + , underlyingTn: collectionNftTn + } + ) $ singleton collectionNftCs collectionNftTn one + , Constraints.mustValidateIn $ from now + ] + unbalancedTx <- liftedE $ Lookups.mkUnbalancedTx lookups constraints + unbalancedTxWithMetadata <- setSeabugMetadata + (NftData { nftId: nft, nftCollection: collection }) + curr + unbalancedTx + signedTx <- liftedE $ balanceAndSignTxE unbalancedTxWithMetadata + transactionHash <- submit signedTx + log $ "Mint transaction successfully submitted with hash: " <> show + transactionHash + pure transactionHash diff --git a/src/Seabug/Contract/Util.purs b/src/Seabug/Contract/Util.purs new file mode 100644 index 0000000..1c79f11 --- /dev/null +++ b/src/Seabug/Contract/Util.purs @@ -0,0 +1,50 @@ +module Seabug.Contract.Util + ( minAdaOnlyUTxOValue + , setSeabugMetadata + ) where + +import Contract.Prelude + +import Contract.AuxiliaryData (setTxMetadata) +import Contract.Monad (Contract, liftContractM) +import Contract.Numeric.Natural (toBigInt) +import Contract.ScriptLookups (UnattachedUnbalancedTx) +import Contract.Value (CurrencySymbol) +import Data.BigInt (BigInt) +import Data.BigInt as BigInt +import Seabug.Metadata.Share (mkShare) +import Seabug.Metadata.Types (SeabugMetadata(..)) +import Seabug.Types (NftData(..)) + +minAdaOnlyUTxOValue :: BigInt +minAdaOnlyUTxOValue = BigInt.fromInt 2_000_000 + +-- | Set metadata on the transaction for the given NFT +setSeabugMetadata + :: forall (r :: Row Type) + . NftData + -> CurrencySymbol -- | The currency symbol of the self-governed nft + -> UnattachedUnbalancedTx + -> Contract r UnattachedUnbalancedTx +setSeabugMetadata (NftData nftData) sgNftCurr tx = do + let + nftCollection = unwrap nftData.nftCollection + nftId = unwrap nftData.nftId + natToShare nat = liftContractM "Invalid share" + $ mkShare + =<< BigInt.toInt (toBigInt nat) + authorShareValidated <- natToShare nftCollection.authorShare + marketplaceShareValidated <- natToShare nftCollection.daoShare + setTxMetadata tx $ SeabugMetadata + { policyId: sgNftCurr + , mintPolicy: "V1" + , collectionNftCS: nftCollection.collectionNftCs + , lockingScript: nftCollection.lockingScript + , collectionNftTN: nftId.collectionNftTn + , authorPkh: unwrap nftCollection.author + , authorShare: authorShareValidated + , marketplaceScript: nftCollection.daoScript + , marketplaceShare: marketplaceShareValidated + , ownerPkh: unwrap nftId.owner + , ownerPrice: nftId.price + } diff --git a/src/Seabug/Helpers.purs b/src/Seabug/Helpers.purs index 26e839b..a22dad2 100644 --- a/src/Seabug/Helpers.purs +++ b/src/Seabug/Helpers.purs @@ -2,23 +2,26 @@ module Seabug.Helpers ( jsonReader ) where +import Aeson + ( class DecodeAeson + , caseAesonObject + , getField + , jsonToAeson + ) import Contract.Prelude import Data.Argonaut ( Json - , class DecodeJson , JsonDecodeError(TypeMismatch) - , caseJsonObject - , getField ) -import Foreign.Object (Object) -- | Helper to decode the local inputs such as unapplied minting policy and -- | typed validator jsonReader :: forall (a :: Type) - . DecodeJson a + . DecodeAeson a => String -> Json -> Either JsonDecodeError a -jsonReader field = caseJsonObject (Left $ TypeMismatch "Expected Object") - $ flip getField field +jsonReader field = jsonToAeson >>> caseAesonObject + (Left $ TypeMismatch "Expected Object") + (flip getField field) diff --git a/src/Seabug/Lock.js b/src/Seabug/Lock.js new file mode 100644 index 0000000..b79fde2 --- /dev/null +++ b/src/Seabug/Lock.js @@ -0,0 +1,6 @@ +exports._unappliedLockScript = { + validator: { + getValidator: + "590d0f01000032333222323322323233223332223232332233322232323332223322332232323233223332223332223333322222323322332233223322323233332222332233223322332232323322323232333322223232222333222232223232323232323353049008225335306153353061533535057300b353022500722222222220072106310631063133573892010e43616e6e6f74206d696e742073670006215335306153353061332233355302f1200135048504723535503500122333553032120013504b504a23535503800122333535501d00123304d4800000488cc1380080048cc13400520000013355301c12001235355035001223355038002333535501a0012335530201200123535503900122335503c0023550210010012233355501b0640020012335530201200123535503900122335503c00235501f00100133355501605f00200135303035302e5335350573530200092235302400222222222223303800a00b21001132635305a335738921114f776e20696e707574206d697373696e670005b01f2200122200235303050082220021063133573892011a56616c75657320696e20434f2063616e6e6f74206368616e676500062153353061533530613322353024002222222222253353506333355303912001504225335306e333573466e3c0300041c01bc4d41980045419400c841c041b9401c008418c4cd5ce24811f4f776e6572206d757374207369676e20746865207472616e73616374696f6e000621533530615335306133355302d1200135019501b2333573466e1cccc050d4c0c4004888008d4c17c03488800cc13cccc154d4c17c03488800400800d2002064063353022500722222222220091063133573892119496e70757420646f6573206e6f7420636f6e7461696e20736700062153353061333573466e20d4c17803088800803418c18854cd4c1854cd4c1854010418c4cd5ce2492343757272656e7420736c6f7420736d616c6c6572207468616e206c6f636b7570456e64000621533530613305c35305e00c22233306200301000150061063133573892112496e636f6e73697374656e7420646174756d000621062153353061533530615003106313357389212843757272656e7420736c6f7420736d616c6c6572207468616e206c6f636b75702b656e7465726564000621533530613305c35305e00c222333062003337006a60c201e444004022002a00c20c6266ae7124112496e636f6e73697374656e7420646174756d0006210621062106210621062225335306153353061333355302d1200133504822230033002001200122064301e00906310631335738920112434f206d757374206e6f74206578697374730006215335306153353061333573466e1cccc04cd4c089401c888888888801cd4c17803088800cc138ccc150d4c17803088800400400920010630621063133573892011473674e4654206d757374206265206275726e656400062153353061333573466e20d4c17803088800803418c18854cd4c1854010418c4cd5ce2492343757272656e7420736c6f7420736d616c6c6572207468616e206c6f636b7570456e64000621533530615003106313357389212843757272656e7420736c6f7420736d616c6c6572207468616e206c6f636b75702b656e746572656400062106210621333573466e254008cdc00059a982d80491100102f8300999ab9a33712a0020120bc0be266e0ccdc09a9a8109a9a80f9a980ea801111111111100211001112999a9a8128011080089931a982b99ab9c49012456616c69642072616e676520626567696e6e696e67206d7573742062652066696e6974650005801c132635305733573892012456616c69642072616e676520626567696e6e696e67206d7573742062652066696e6974650005801c483c2032323cd7120d00f153353505132323232323333333574800a46666ae68cdc39aab9d5005480008cccd55cfa8029282d11999aab9f50052505b233335573ea00a4a0b846666aae7cd5d128031299a9a82e182d9aba150092153353505d32333333357480024a0c04a0c04a0c046a0c26eb400894180188d5d0a80490a99a9a82f182e9aba1500921350613330670030020011505f1505e1505d2505d05f05e05d05c2505901f2505825058250582505805a135744a00226ae8940044d55cf280089baa001533535051332235301e001222222222253353505d33355303312001503c235355039001225335306a333573466e3c00803c1b01ac4d418800c5418400884d4180d4d540e400488004541794cd4d4144d4c0a94008888004840044c98d4c150cd5ce249194d697373696e67206f757470757420646174756d2068617368000550195001210011326353054335738921144d697373696e67206f757470757420646174756d0005501921001132635305433573892117496e76616c696420434f20646174756d20666f726d6174000550191353019002220021533535048301600113263530523357389201054e6f20434f0005301722153353504a0011002221326353056335738921104d6f7265207468616e206f6e6520434f0005701b32001355059225335350470011504f2213535502b002225335305c3305800235305900722200313505400113006003375c0066eb4008dd680091119191800802990009aa82a9119a9a821800a4000446a6aa04e00444a66a60b0666ae68cdc780100482d02c8980380089803001990009aa82a1119a9a821000a4000446a6aa04c00444a66a60ae666ae68cdc780100382c82c080089803001888911199aa981f09000a82019aa98048900091a9aa8110009119aa8128011aa805000999aa981f09000911a9aa81180111299a982a199aa9810090009a806280711a9aa81300091198050010028030801899a822002001a82080099aa98048900091a9aa811000911919aa8130019800802990009aa82b11299a9a82200089aa8050019109a9aa81400111299a982c99806001004099aa80780380089803001801089091118018020891091119801002802089091118008020890008919a81811199a9a803001910010010009a9a80200091000990009aa825110891299a9a81d0008a81e11099a81e980200119aa980309000802000899a80111299a98240010825080082389109198008018010900091a9801800911a98038011111111111299a9a8231980d805005909a980f000911a9811000911199aa982209000911a98138011111a9817004111a98180029119299a983019a981f002919a981f8021299a9831199ab9a3371e0040020c80c62a00620c640c6466a607e00840c64a66a60c4666ae68cdc78010008320318a8018831899a82800500488048a99a9a82a80190a99a9a82b0011099a981e001119a981e801119a9820801119a98210011198308010009033119a9821001103311983080100091103311119a981f8021033111299a9833999ab9a3370e00c0060d20d02a66a60ce666ae68cdc38028010348340998250020008834083408308a99a9a82a800908308830a82380789931a982499ab9c491024c660004a00e4988848cc00400c0088004888888888848cccccccccc00402c02802402001c01801401000c008800448848cc00400c0084800448848cc00400c00848004484888c00c01044888008448880044800488cccd4c034004940bc940bc940bc8ccd54c0104800540348d4c018004894cd4c0ed4cd4c0ecccd5cd19b8f35301c0022200235301c0042200203d03c1333573466e1cd4c07000888004d4c070010880040f40f040f04d40cc00c540c800cc8004d540dc88448894cd4d40a00044d4d407c00c88004884ccd4d408401488008c010008ccd54c01c480040140100048848cc00400c008800488848ccc00401000c0088004448848cc00400c0084480048848cc00400c00880044cd4048894cd4d408c0088400c40054088848888c010014848888c00c014848888c008014848888c00401480048488c00800c888488ccc00401401000c80048488c00800c8488c00400c80048848cc00400c008800488ccd5cd19b870020010210201335005225335301e0021001101f01e12335003223335350060032200200200135350040012200112212330010030021200112212330010030021200122122330020040032212233001004003200123728666aa600424002e28020cc88cc008c8dca1980b0008059a9804001911001198011b943530080032220013300237286a6010006444006002a008a00a640026aa02a4422444a66a6a00c00220044426600a004666aa600e2400200a00800222440042442446600200800624002444246660020080060044002911002333333357480024a0084a0084a0084a00846a00a6eb800801848488c00800c44880044800448004800488d4c010008888d4c01c0108894cd4c034ccd5cd19b8f00600300f00e15335300d333573466e1c01400803c0384cc0240100044038403888ccd5cd19b8f0020010080072221233300100400300220013200135500422253353004333573466e2000920800400600513371600400226600666e0c0092080043371666e180092080040011220021220012001112323001001223300330020020011" + } +} diff --git a/src/Seabug/Lock.purs b/src/Seabug/Lock.purs new file mode 100644 index 0000000..316b3cf --- /dev/null +++ b/src/Seabug/Lock.purs @@ -0,0 +1,28 @@ +module Seabug.Lock where + +import Contract.Prelude + +import Contract.Address (Slot) +import Contract.Monad (Contract, liftContractE) +import Contract.PlutusData (toData) +import Contract.Scripts (Validator, applyArgs) +import Contract.Value (CurrencySymbol) +import Data.Argonaut (Json, JsonDecodeError) +import Data.BigInt (BigInt) +import QueryM as QueryM +import Seabug.Helpers (jsonReader) + +mkLockScript + :: forall (r :: Row Type) + . CurrencySymbol + -> BigInt + -> Slot + -> Contract r (Either QueryM.ClientError Validator) +mkLockScript collectionNftCs lockup lockupEnd = do + script <- liftContractE unappliedLockScript + applyArgs script [ toData collectionNftCs, toData lockup, toData lockupEnd ] + +unappliedLockScript :: Either JsonDecodeError Validator +unappliedLockScript = jsonReader "validator" _unappliedLockScript + +foreign import _unappliedLockScript :: Json diff --git a/src/Seabug/MarketPlace.js b/src/Seabug/MarketPlace.js index ff944fa..4677bc0 100644 --- a/src/Seabug/MarketPlace.js +++ b/src/Seabug/MarketPlace.js @@ -1,14 +1,14 @@ exports._marketplaceValidator = { typedValidator: { - validator: - "5908f801000033232332233223232333222323332223233333333222222223233322232333322223232332232333222323332223232332233223232333332222233223322332233223322332233222222323253353033333006300800530070043333573466e1cd55cea8012400046601664646464646464646464646666ae68cdc39aab9d500a480008cccccccccc064cd409c8c8c8cccd5cd19b8735573aa004900011980f981d1aba15002302c357426ae8940088c98d4c168cd5ce02f02d82c82c09aab9e5001137540026ae854028cd409c0a0d5d0a804999aa8173ae502d35742a010666aa05ceb940b4d5d0a80399a8138219aba15006335027335505404c75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a8109919191999ab9a3370e6aae7540092000233502933504275a6ae854008c11cd5d09aba25002232635305e3357380c40be0ba0b826aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a04e66a084eb4d5d0a80118239aba135744a004464c6a60bc66ae7018817c1741704d55cf280089baa001357426ae8940088c98d4c168cd5ce02f02d82c82c09aab9e5001137540026ae854010cd409dd71aba15003335027335505475c40026ae854008c0e4d5d09aba2500223263530563357380b40ae0aa0a826ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d400520062301e303b357426aae79400c8cccd5cd19b875002480108c074c114d5d09aab9e500423333573466e1d400d20022301d3030357426aae7940148cccd5cd19b875004480008c080dd71aba135573ca00c464c6a60a266ae7015414814013c1381341304d55cea80089baa001357426ae8940088c98d4c128cd5ce027025824824082509931a982499ab9c4901035054350004a048135573ca00226ea8004cd540fdd73ae20012212330010030022001222222222212333333333300100b00a00900800700600500400300220012212330010030022001122123300100300212001122123300100300212001122123300100300212001212222300400521222230030052122223002005212222300100520011232230023758002640026aa06a446666aae7c004940388cd4034c010d5d080118019aba200203323232323333573466e1cd55cea801a4000466600e6464646666ae68cdc39aab9d5002480008cc034c0c4d5d0a80119a8098169aba135744a004464c6a606e66ae700ec0e00d80d44d55cf280089baa00135742a006666aa016eb94028d5d0a80119a807bae357426ae8940088c98d4c0cccd5ce01b81a01901889aba25001135573ca00226ea800488848ccc00401000c00880048848cc00400c00880044cd54005d73ad112232230023756002640026aa05e44646666aae7c008940248cd4020cd540c4c018d55cea80118029aab9e500230043574400605c26ae840044488008488488cc00401000c48004488c8c8cccd5cd19b875001480008d4020c014d5d09aab9e500323333573466e1d4009200225008232635302a33573805c05605205004e26aae7540044dd5000890911801001889100089000919191999ab9a3370e6aae7540092000233006300735742a0046eb4d5d09aba25002232635302433573805004a04604426aae7940044dd500091091980080180110009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931a981019ab9c02402101f01e1375400224464646666ae68cdc3a800a40084a00e46666ae68cdc3a8012400446a014600c6ae84d55cf280211999ab9a3370ea00690001280511931a981199ab9c02702402202102001f135573aa00226ea8004484888c00c0104488800844888004480048c8cccd5cd19b8750014800880188cccd5cd19b8750024800080188c98d4c06ccd5ce00f80e00d00c80c09aab9d37540022440042440024002464646464646666ae68cdc3a800a4018401646666ae68cdc3a80124014401a46666ae68cdc3a801a40104660166eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc034dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a9002119809180a1aba15009375c6ae84d5d1280491999ab9a3370ea00c90011180a180a9aba135573ca01646666ae68cdc3a803a400046026602c6ae84d55cf280611931a981019ab9c02402101f01e01d01c01b01a019018135573aa00826aae79400c4d55cf280109aab9e500113754002424444444600e01044244444446600c012010424444444600a010244444440082444444400644244444446600401201044244444446600201201040024646464646666ae68cdc3a800a400446660106eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d400920002300a300b357426aae7940188c98d4c044cd5ce00a80900800780709aab9d5003135744a00226aae7940044dd5000909118010019110911998008028020019000919191999ab9a3370ea0029001118031bae357426aae79400c8cccd5cd19b875002480008c020dd71aba135573ca008464c6a601666ae7003c0300280240204d55cea80089baa001212230020032122300100320011122232323333573466e1cd55cea80124000466aa016600c6ae854008c014d5d09aba25002232635300833573801801200e00c26aae7940044dd5000a4c2400240022244246600200600422400292010350543100112323001001223300330020020013233223332223322332233322222253353004333573466e1cd4d5403800c88ccc888c8c8c004014c8004d5405888cd4d404c005200022353550180022253353010333573466e3c0080240480444c01c0044c01800cc8004d5405488cd4d404800520002235355017002225335300f333573466e3c00801c04404040044c01800cd4c02cd4c02400c88008888888888801c008005200100600510061335738920121416c6c207370656e7420746f6b656e73206d7573742062652072656d696e7465640000512200212200120012212330010030022001222222222212333333333300100b00a009008007006005004003002200111220021221223300100400312001112212330010030021120011123230010012233003300200200101", - validatorHash: { - getScriptHash: "df4def976c66c24bb32f2bdf63da44bd4d77757811e670457b27690b", + validator: { + getValidator: "5908f801000033232332233223232333222323332223233333333222222223233322232333322223232332232333222323332223232332233223232333332222233223322332233223322332233222222323253353033333006300800530070043333573466e1cd55cea8012400046601664646464646464646464646666ae68cdc39aab9d500a480008cccccccccc064cd409c8c8c8cccd5cd19b8735573aa004900011980f981d1aba15002302c357426ae8940088c98d4c168cd5ce02f02d82c82c09aab9e5001137540026ae854028cd409c0a0d5d0a804999aa8173ae502d35742a010666aa05ceb940b4d5d0a80399a8138219aba15006335027335505404c75a6ae854014c8c8c8cccd5cd19b8735573aa0049000119a8109919191999ab9a3370e6aae7540092000233502933504275a6ae854008c11cd5d09aba25002232635305e3357380c40be0ba0b826aae7940044dd50009aba150023232323333573466e1cd55cea80124000466a04e66a084eb4d5d0a80118239aba135744a004464c6a60bc66ae7018817c1741704d55cf280089baa001357426ae8940088c98d4c168cd5ce02f02d82c82c09aab9e5001137540026ae854010cd409dd71aba15003335027335505475c40026ae854008c0e4d5d09aba2500223263530563357380b40ae0aa0a826ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150023232323333573466e1d400520062301e303b357426aae79400c8cccd5cd19b875002480108c074c114d5d09aab9e500423333573466e1d400d20022301d3030357426aae7940148cccd5cd19b875004480008c080dd71aba135573ca00c464c6a60a266ae7015414814013c1381341304d55cea80089baa001357426ae8940088c98d4c128cd5ce027025824824082509931a982499ab9c4901035054350004a048135573ca00226ea8004cd540fdd73ae20012212330010030022001222222222212333333333300100b00a00900800700600500400300220012212330010030022001122123300100300212001122123300100300212001122123300100300212001212222300400521222230030052122223002005212222300100520011232230023758002640026aa06a446666aae7c004940388cd4034c010d5d080118019aba200203323232323333573466e1cd55cea801a4000466600e6464646666ae68cdc39aab9d5002480008cc034c0c4d5d0a80119a8098169aba135744a004464c6a606e66ae700ec0e00d80d44d55cf280089baa00135742a006666aa016eb94028d5d0a80119a807bae357426ae8940088c98d4c0cccd5ce01b81a01901889aba25001135573ca00226ea800488848ccc00401000c00880048848cc00400c00880044cd54005d73ad112232230023756002640026aa05e44646666aae7c008940248cd4020cd540c4c018d55cea80118029aab9e500230043574400605c26ae840044488008488488cc00401000c48004488c8c8cccd5cd19b875001480008d4020c014d5d09aab9e500323333573466e1d4009200225008232635302a33573805c05605205004e26aae7540044dd5000890911801001889100089000919191999ab9a3370e6aae7540092000233006300735742a0046eb4d5d09aba25002232635302433573805004a04604426aae7940044dd500091091980080180110009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931a981019ab9c02402101f01e1375400224464646666ae68cdc3a800a40084a00e46666ae68cdc3a8012400446a014600c6ae84d55cf280211999ab9a3370ea00690001280511931a981199ab9c02702402202102001f135573aa00226ea8004484888c00c0104488800844888004480048c8cccd5cd19b8750014800880188cccd5cd19b8750024800080188c98d4c06ccd5ce00f80e00d00c80c09aab9d37540022440042440024002464646464646666ae68cdc3a800a4018401646666ae68cdc3a80124014401a46666ae68cdc3a801a40104660166eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc034dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a9002119809180a1aba15009375c6ae84d5d1280491999ab9a3370ea00c90011180a180a9aba135573ca01646666ae68cdc3a803a400046026602c6ae84d55cf280611931a981019ab9c02402101f01e01d01c01b01a019018135573aa00826aae79400c4d55cf280109aab9e500113754002424444444600e01044244444446600c012010424444444600a010244444440082444444400644244444446600401201044244444446600201201040024646464646666ae68cdc3a800a400446660106eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d400920002300a300b357426aae7940188c98d4c044cd5ce00a80900800780709aab9d5003135744a00226aae7940044dd5000909118010019110911998008028020019000919191999ab9a3370ea0029001118031bae357426aae79400c8cccd5cd19b875002480008c020dd71aba135573ca008464c6a601666ae7003c0300280240204d55cea80089baa001212230020032122300100320011122232323333573466e1cd55cea80124000466aa016600c6ae854008c014d5d09aba25002232635300833573801801200e00c26aae7940044dd5000a4c2400240022244246600200600422400292010350543100112323001001223300330020020013233223332223322332233322222253353004333573466e1cd4d5403800c88ccc888c8c8c004014c8004d5405888cd4d404c005200022353550180022253353010333573466e3c0080240480444c01c0044c01800cc8004d5405488cd4d404800520002235355017002225335300f333573466e3c00801c04404040044c01800cd4c02cd4c02400c88008888888888801c008005200100600510061335738920121416c6c207370656e7420746f6b656e73206d7573742062652072656d696e7465640000512200212200120012212330010030022001222222222212333333333300100b00a009008007006005004003002200111220021221223300100400312001112212330010030021120011123230010012233003300200200101", + }, + validatorHash: "df4def976c66c24bb32f2bdf63da44bd4d77757811e670457b27690b", + forwardingMPS: { + getMintingPolicy: "5908c0010000332332233322232323322332232323332223233322232333333332222222232333222323333222232323322323332223232323322332232323333322222332233223322332233223322332222232325335302f332235300a0012235300e002222222222233335302200b203f2333553059120013233505f223335350180032200200200135350160012200133501622533530400021042100103f235302b35301c0012200122235303000322335305500220462333573466e3c00406c11c11802c80fc80fccccd5cd19b8735573a6ea801120002047232635304633573809408e08a0886666ae68cdc39aab9d5002480008cc028c8c8c8c8c8c8c8c8c8c8c8cccd5cd19b8735573aa01490001199999999980c19a813119191999ab9a3370e6aae754009200023301e303635742a00460566ae84d5d1280111931a982b19ab9c05a057055054135573ca00226ea8004d5d0a80519a8130139aba150093335502d75ca0586ae854020ccd540b5d728161aba1500733502603f35742a00c66a04c66aa0a0090eb4d5d0a8029919191999ab9a3370e6aae754009200023350203232323333573466e1cd55cea80124000466a05066a07ceb4d5d0a80118219aba135744a004464c6a60b466ae7017816c1641604d55cf280089baa00135742a0046464646666ae68cdc39aab9d5002480008cd4098cd40f9d69aba150023043357426ae8940088c98d4c168cd5ce02f02d82c82c09aab9e5001137540026ae84d5d1280111931a982b19ab9c05a057055054135573ca00226ea8004d5d0a80219a8133ae35742a00666a04c66aa0a0eb88004d5d0a801181a9aba135744a004464c6a60a466ae7015814c1441404d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a0046464646666ae68cdc3a800a400c4603a606e6ae84d55cf280191999ab9a3370ea00490021180e18209aba135573ca00846666ae68cdc3a801a40044603860586ae84d55cf280291999ab9a3370ea00890001180f9bae357426aae7940188c98d4c134cd5ce02882702602582502482409aab9d5001137540026ae84d5d1280111931a982319ab9c04a0470450441046132635304533573892010350543500046044135573ca00226ea800448848cc00400c008480048848cc00400c0088004888888888848cccccccccc00402c02802402001c01801401000c00880048848cc00400c008800448848cc00400c0084800448848cc00400c0084800448848cc00400c00848004848888c010014848888c00c014848888c008014848888c004014800448c88c008dd6000990009aa81c111999aab9f00125038233503730043574200460066ae880080c08c8c8c8cccd5cd19b8735573aa006900011998039919191999ab9a3370e6aae754009200023300d302e35742a00466a0200546ae84d5d1280111931a981a19ab9c038035033032135573ca00226ea8004d5d0a801999aa805bae500a35742a00466a018eb8d5d09aba25002232635303033573806806205e05c26ae8940044d55cf280089baa00122212333001004003002200122123300100300220011335500175ceb44488c88c008dd5800990009aa81911191999aab9f002250332335032335502e300635573aa004600a6aae794008c010d5d100181589aba100112232323333573466e1d400520002350083005357426aae79400c8cccd5cd19b87500248008940208c98d4c0a8cd5ce01701581481401389aab9d500113754002242446004006224400224002464646666ae68cdc39aab9d5002480008cc018c01cd5d0a8011bad357426ae8940088c98d4c090cd5ce01401281181109aab9e50011375400244246600200600440024646666ae68cdc39aab9d5001480008dd71aba135573ca004464c6a604066ae7009008407c0784dd500089119191999ab9a3370ea00290021280391999ab9a3370ea004900111a80518031aba135573ca00846666ae68cdc3a801a40004a014464c6a604666ae7009c09008808408007c4d55cea80089baa00112122230030041122200211222001120012323333573466e1d40052002200623333573466e1d400920002006232635301b33573803e03803403203026aae74dd50008910010910009000919191919191999ab9a3370ea0029006100591999ab9a3370ea0049005100691999ab9a3370ea00690041198059bae35742a00a6eb4d5d09aba2500523333573466e1d4011200623300d375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846602460286ae854024dd71aba135744a01246666ae68cdc3a8032400446028602a6ae84d55cf280591999ab9a3370ea00e900011809980b1aba135573ca018464c6a604066ae7009008407c07807407006c0680640604d55cea80209aab9e5003135573ca00426aae7940044dd500090911111118038041109111111198030048041091111111802804091111110020911111100191091111111980100480411091111111980080480410009191919191999ab9a3370ea002900111998041bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c028c02cd5d09aab9e5006232635301133573802a02402001e01c26aae75400c4d5d1280089aab9e5001137540024244600400644424466600200a0080064002464646666ae68cdc3a800a40044600c6eb8d5d09aab9e500323333573466e1d4009200023008375c6ae84d55cf280211931a980599ab9c00f00c00a009008135573aa00226ea80048488c00800c8488c00400c800444888c8c8cccd5cd19b8735573aa0049000119aa80598031aba150023005357426ae8940088c98d4c020cd5ce00600480380309aab9e5001137540029309000900088910919800801801089000a490350543100320013550062211222533535006001135350090032200122133353500b0052200230040023335530071200100500400111220021221223300100400312001122123300100300212001112323001001223300330020020014891cdf4def976c66c24bb32f2bdf63da44bd4d77757811e670457b27690b0001", }, - forwardingMPS: - "5908c0010000332332233322232323322332232323332223233322232333333332222222232333222323333222232323322323332223232323322332232323333322222332233223322332233223322332222232325335302f332235300a0012235300e002222222222233335302200b203f2333553059120013233505f223335350180032200200200135350160012200133501622533530400021042100103f235302b35301c0012200122235303000322335305500220462333573466e3c00406c11c11802c80fc80fccccd5cd19b8735573a6ea801120002047232635304633573809408e08a0886666ae68cdc39aab9d5002480008cc028c8c8c8c8c8c8c8c8c8c8c8cccd5cd19b8735573aa01490001199999999980c19a813119191999ab9a3370e6aae754009200023301e303635742a00460566ae84d5d1280111931a982b19ab9c05a057055054135573ca00226ea8004d5d0a80519a8130139aba150093335502d75ca0586ae854020ccd540b5d728161aba1500733502603f35742a00c66a04c66aa0a0090eb4d5d0a8029919191999ab9a3370e6aae754009200023350203232323333573466e1cd55cea80124000466a05066a07ceb4d5d0a80118219aba135744a004464c6a60b466ae7017816c1641604d55cf280089baa00135742a0046464646666ae68cdc39aab9d5002480008cd4098cd40f9d69aba150023043357426ae8940088c98d4c168cd5ce02f02d82c82c09aab9e5001137540026ae84d5d1280111931a982b19ab9c05a057055054135573ca00226ea8004d5d0a80219a8133ae35742a00666a04c66aa0a0eb88004d5d0a801181a9aba135744a004464c6a60a466ae7015814c1441404d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a0046464646666ae68cdc3a800a400c4603a606e6ae84d55cf280191999ab9a3370ea00490021180e18209aba135573ca00846666ae68cdc3a801a40044603860586ae84d55cf280291999ab9a3370ea00890001180f9bae357426aae7940188c98d4c134cd5ce02882702602582502482409aab9d5001137540026ae84d5d1280111931a982319ab9c04a0470450441046132635304533573892010350543500046044135573ca00226ea800448848cc00400c008480048848cc00400c0088004888888888848cccccccccc00402c02802402001c01801401000c00880048848cc00400c008800448848cc00400c0084800448848cc00400c0084800448848cc00400c00848004848888c010014848888c00c014848888c008014848888c004014800448c88c008dd6000990009aa81c111999aab9f00125038233503730043574200460066ae880080c08c8c8c8cccd5cd19b8735573aa006900011998039919191999ab9a3370e6aae754009200023300d302e35742a00466a0200546ae84d5d1280111931a981a19ab9c038035033032135573ca00226ea8004d5d0a801999aa805bae500a35742a00466a018eb8d5d09aba25002232635303033573806806205e05c26ae8940044d55cf280089baa00122212333001004003002200122123300100300220011335500175ceb44488c88c008dd5800990009aa81911191999aab9f002250332335032335502e300635573aa004600a6aae794008c010d5d100181589aba100112232323333573466e1d400520002350083005357426aae79400c8cccd5cd19b87500248008940208c98d4c0a8cd5ce01701581481401389aab9d500113754002242446004006224400224002464646666ae68cdc39aab9d5002480008cc018c01cd5d0a8011bad357426ae8940088c98d4c090cd5ce01401281181109aab9e50011375400244246600200600440024646666ae68cdc39aab9d5001480008dd71aba135573ca004464c6a604066ae7009008407c0784dd500089119191999ab9a3370ea00290021280391999ab9a3370ea004900111a80518031aba135573ca00846666ae68cdc3a801a40004a014464c6a604666ae7009c09008808408007c4d55cea80089baa00112122230030041122200211222001120012323333573466e1d40052002200623333573466e1d400920002006232635301b33573803e03803403203026aae74dd50008910010910009000919191919191999ab9a3370ea0029006100591999ab9a3370ea0049005100691999ab9a3370ea00690041198059bae35742a00a6eb4d5d09aba2500523333573466e1d4011200623300d375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846602460286ae854024dd71aba135744a01246666ae68cdc3a8032400446028602a6ae84d55cf280591999ab9a3370ea00e900011809980b1aba135573ca018464c6a604066ae7009008407c07807407006c0680640604d55cea80209aab9e5003135573ca00426aae7940044dd500090911111118038041109111111198030048041091111111802804091111110020911111100191091111111980100480411091111111980080480410009191919191999ab9a3370ea002900111998041bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c028c02cd5d09aab9e5006232635301133573802a02402001e01c26aae75400c4d5d1280089aab9e5001137540024244600400644424466600200a0080064002464646666ae68cdc3a800a40044600c6eb8d5d09aab9e500323333573466e1d4009200023008375c6ae84d55cf280211931a980599ab9c00f00c00a009008135573aa00226ea80048488c00800c8488c00400c800444888c8c8cccd5cd19b8735573aa0049000119aa80598031aba150023005357426ae8940088c98d4c020cd5ce00600480380309aab9e5001137540029309000900088910919800801801089000a490350543100320013550062211222533535006001135350090032200122133353500b0052200230040023335530071200100500400111220021221223300100400312001122123300100300212001112323001001223300330020020014891cdf4def976c66c24bb32f2bdf63da44bd4d77757811e670457b27690b0001", forwardingMPSHash: { - getScriptHash: "487bb18c7e68bbb8f32e1f4da4ca734f1c4303474bcdb2d2967c6dc4", + getMintingPolicyHash: "487bb18c7e68bbb8f32e1f4da4ca734f1c4303474bcdb2d2967c6dc4", }, }, }; diff --git a/src/Seabug/Metadata.purs b/src/Seabug/Metadata.purs index 6ca7fb0..989bc45 100644 --- a/src/Seabug/Metadata.purs +++ b/src/Seabug/Metadata.purs @@ -1,39 +1,44 @@ module Seabug.Metadata - ( FullSeabugMetadata + ( BlockfrostFetchError(..) + , FullSeabugMetadata , Hash , getFullSeabugMetadata + , getFullSeabugMetadataWithBackoff ) where import Contract.Prelude +import Aeson as Aeson +import Affjax (printError) import Affjax as Affjax import Affjax.RequestHeader as Affjax.RequestHeader import Affjax.ResponseFormat as Affjax.ResponseFormat -import Cardano.Types.Value as Cardano.Types.Value -import Contract.Monad (Contract) import Contract.Prim.ByteArray (byteArrayToHex) -import Contract.Transaction - ( ClientError(ClientHttpError, ClientDecodeJsonError) - ) import Contract.Value ( CurrencySymbol , TokenName , getCurrencySymbol , getTokenName - , mkCurrencySymbol ) import Control.Alternative (guard) +import Control.Monad.Error.Class (throwError) import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) +import Control.Monad.Reader (ReaderT, runReaderT) import Control.Monad.Reader.Trans (asks) import Control.Monad.Trans.Class (lift) -import Data.Argonaut (class DecodeJson) -import Data.Argonaut as Json -import Data.Bifunctor (bimap, lmap) +import Data.Argonaut as Argonaut +import Data.Array (head) +import Data.Bifunctor (lmap) import Data.Function (on) import Data.HTTP.Method (Method(GET)) import Data.Newtype (unwrap) -import Metadata.Seabug (SeabugMetadata(SeabugMetadata)) -import Partial.Unsafe (unsafePartial) +import Effect.Aff (delay) +import Effect.Random (randomRange) +import Seabug.Metadata.Types + ( SeabugMetadata(SeabugMetadata) + , decodeSeabugMetadataAeson + , metadataBytesString + ) type Hash = String @@ -42,97 +47,147 @@ type FullSeabugMetadata = , ipfsHash :: Hash } +data BlockfrostFetchError + = BlockfrostRateLimit + | BlockfrostOtherError String + +derive instance Generic BlockfrostFetchError _ + +instance Show BlockfrostFetchError where + show = genericShow + +type BlockfrostFetch a = ExceptT BlockfrostFetchError + (ReaderT { projectId :: String } Aff) + a + +-- | Tries to get the metadata for the given asset using +-- | Blockfrost. If the rate limit is hit, retries after a random +-- | delay, up to 5 times. Uses a very simple back-off mechanism. +-- | Instead of relying on this, refactor so the rate limit isn't hit. +getFullSeabugMetadataWithBackoff + :: CurrencySymbol /\ TokenName + -> String + -> Aff (Either BlockfrostFetchError FullSeabugMetadata) +getFullSeabugMetadataWithBackoff asset projectId = go 1.0 + where + go n = do + r <- getFullSeabugMetadata asset projectId + case r of + Left BlockfrostRateLimit + | n < 5.0 -> do + let n' = n + 1.0 + log "Blockfrost rate limit hit, backing off" + -- Wait a random amount of time in the range of [1, 3 * + -- (attempt + 1)) seconds, this is just a heuristic based + -- on my testing + delay <<< wrap <<< (_ * 1000.0) =<< + (liftEffect $ randomRange 1.0 (3.0 * n')) + log $ "Retrying metadata query, attempt #" <> show n' + go n' + _ -> pure r + getFullSeabugMetadata - :: forall (r :: Row Type) - . CurrencySymbol /\ TokenName - -> Contract (projectId :: String | r) (Either ClientError FullSeabugMetadata) -getFullSeabugMetadata a@(currSym /\ _) = runExceptT $ do - seabugMetadata <- getMintingTxSeabugMetadata currSym =<< getMintingTxHash a - ipfsHash <- getIpfsHash seabugMetadata - pure { seabugMetadata, ipfsHash } + :: CurrencySymbol /\ TokenName + -> String + -> Aff (Either BlockfrostFetchError FullSeabugMetadata) +getFullSeabugMetadata a@(currSym /\ _) projectId = + flip runReaderT { projectId } <<< runExceptT $ do + seabugMetadata <- + getMintingTxSeabugMetadata currSym =<< getMintingTxHash a + ipfsHash <- getIpfsHash seabugMetadata + pure { seabugMetadata, ipfsHash } getIpfsHash - :: forall (r :: Row Type) - . SeabugMetadata - -> ExceptT ClientError (Contract (projectId :: String | r)) Hash + :: SeabugMetadata + -> BlockfrostFetch Hash getIpfsHash (SeabugMetadata { collectionNftCS, collectionNftTN }) = do - except <<< (decodeField "image" <=< decodeField "onchain_metadata") - =<< mkGetRequest ("assets/" <> mkAsset curr collectionNftTN) + r <- mkGetRequest ("assets/" <> mkAsset collectionNftCS collectionNftTN) + imageArray <- except $ + ( decodeField "image" <=< decodeField tokenNameKey + <=< decodeField currSymKey + <=< decodeField "onchain_metadata" + ) r + except $ note (BlockfrostOtherError "Empty image array") $ head imageArray where - curr :: CurrencySymbol - curr = unsafePartial $ fromJust $ mkCurrencySymbol $ - Cardano.Types.Value.getCurrencySymbol collectionNftCS + currSymKey :: String + currSymKey = metadataBytesString $ getCurrencySymbol collectionNftCS + + tokenNameKey :: String + tokenNameKey = metadataBytesString $ getTokenName collectionNftTN getMintingTxSeabugMetadata :: forall (r :: Row Type) . CurrencySymbol -> Hash - -> ExceptT ClientError (Contract (projectId :: String | r)) SeabugMetadata + -> BlockfrostFetch SeabugMetadata getMintingTxSeabugMetadata currSym txHash = do - j <- mkGetRequest $ "txs/" <> txHash <> "/metadata" + res <- mkGetRequest $ "txs/" <> txHash <> "/metadata" ms <- except - $ lmap ClientDecodeJsonError - $ Json.caseJsonArray - (Left (Json.TypeMismatch "Expected array of objects")) + $ lmap (BlockfrostOtherError <<< show) + $ Aeson.caseAesonArray + (Left (Argonaut.TypeMismatch "Expected array of objects")) Right - j + res except - $ note (ClientDecodeJsonError (Json.UnexpectedValue j)) + $ note (BlockfrostOtherError ("Unexpected JSON: " <> show res)) $ findSeabugMetadata ms where - findSeabugMetadata :: Array Json.Json -> Maybe SeabugMetadata - findSeabugMetadata = findMap $ Json.caseJsonObject Nothing $ \o -> do - label <- hush $ Json.getField o "label" + findSeabugMetadata :: Array Aeson.Aeson -> Maybe SeabugMetadata + findSeabugMetadata = findMap $ Aeson.caseAesonObject Nothing $ \o -> do + label <- hush $ Aeson.getField o "label" guard $ label == "727" - hush $ do - md <- Json.getField o "json_metadata" - Json.decodeJson =<< Json.getField md currSymKey - - currSymKey :: String - currSymKey = byteArrayToHex $ getCurrencySymbol currSym + hush $ decodeSeabugMetadataAeson currSym + =<< Aeson.getField o "json_metadata" getMintingTxHash :: forall (r :: Row Type) . CurrencySymbol /\ TokenName - -> ExceptT ClientError (Contract (projectId :: String | r)) Hash + -> BlockfrostFetch Hash getMintingTxHash a = except <<< decodeField "initial_mint_tx_hash" =<< mkGetRequest ("assets/" <> uncurry mkAsset a) mkAsset :: CurrencySymbol -> TokenName -> String mkAsset currSym tname = - ((<>) `on` byteArrayToHex) (getCurrencySymbol currSym) (getTokenName tname) + ((<>) `on` byteArrayToHex) (getCurrencySymbol currSym) + (getTokenName tname) decodeField :: forall (a :: Type) - . DecodeJson a + . Aeson.DecodeAeson a => String - -> Json.Json - -> Either ClientError a -decodeField field = lmap ClientDecodeJsonError <<< - ( Json.decodeJson - <=< Json.caseJsonObject - (Left (Json.TypeMismatch "Expected Object")) - (flip Json.getField field) - ) + -> Aeson.Aeson + -> Either BlockfrostFetchError a +decodeField field = do + lmap (BlockfrostOtherError <<< show) <<< + ( Aeson.decodeAeson + <=< Aeson.caseAesonObject + (Left (Argonaut.TypeMismatch "Expected Object")) + (flip Aeson.getField field) + ) mkGetRequest :: forall (r :: Row Type) . String - -> ExceptT ClientError (Contract (projectId :: String | r)) Json.Json + -> BlockfrostFetch Aeson.Aeson mkGetRequest path = do - projectId <- lift $ asks $ _.projectId <<< unwrap + projectId <- lift $ asks $ _.projectId let - req :: Affjax.Request Json.Json + req :: Affjax.Request String req = Affjax.defaultRequest { url = mkUrl - , responseFormat = Affjax.ResponseFormat.json + , responseFormat = Affjax.ResponseFormat.string , method = Left GET , headers = [ Affjax.RequestHeader.RequestHeader "project_id" projectId ] } - ExceptT $ liftAff $ Affjax.request req <#> bimap ClientHttpError _.body + res <- ExceptT $ liftAff $ Affjax.request req + <#> lmap (BlockfrostOtherError <<< printError) + when (unwrap res.status == 429) $ throwError $ BlockfrostRateLimit + except $ + lmap (BlockfrostOtherError <<< (("Error parsing JSON: " <> _) <<< show)) + (Aeson.parseJsonStringToAeson res.body) where mkUrl :: String mkUrl = "https://cardano-testnet.blockfrost.io/api/v0/" <> path diff --git a/src/Seabug/Metadata/Share.purs b/src/Seabug/Metadata/Share.purs new file mode 100644 index 0000000..8a7a441 --- /dev/null +++ b/src/Seabug/Metadata/Share.purs @@ -0,0 +1,56 @@ +module Seabug.Metadata.Share + ( Share + , maxShare + , mkShare + , unShare + ) where + +import Prelude + +import Data.BigInt (BigInt) +import Data.BigInt as BigInt +import Data.Maybe (Maybe(Just, Nothing)) +import FromData (class FromData) +import Metadata.FromMetadata (class FromMetadata) +import Metadata.ToMetadata (class ToMetadata, toMetadata) +import ToData (class ToData) +import Types.Int (toBigInt) as Int +import Types.PlutusData (PlutusData(Integer)) +import Types.TransactionMetadata (TransactionMetadatum(Int)) as Metadata + +-- | A number between 0 and 10000 (inclusive) representing percentage +-- | of the price. Note that this differs from Maks' original +-- | self-governed NFTs paper, which specifies the range [0, 1000] +-- | instead. +newtype Share = Share BigInt + +derive newtype instance ToData Share + +instance FromData Share where + fromData (Integer n) = BigInt.toInt n >>= mkShare + fromData _ = Nothing + +instance ToMetadata Share where + -- Must be safe when `Share` is built using `mkShare` smart constructor. + toMetadata = toMetadata <<< unShare + +instance FromMetadata Share where + fromMetadata (Metadata.Int n) = + BigInt.toInt (Int.toBigInt n) >>= mkShare + fromMetadata _ = Nothing + +instance Show Share where + show (Share share) = "(mkShare (" <> show share <> "))" + +derive instance Eq Share + +maxShare :: Int +maxShare = 10_000 + +mkShare :: Int -> Maybe Share +mkShare n + | n >= 0 && n <= maxShare = Just $ Share $ BigInt.fromInt n + | otherwise = Nothing + +unShare :: Share -> BigInt +unShare (Share n) = n diff --git a/src/Seabug/Metadata/Types.purs b/src/Seabug/Metadata/Types.purs new file mode 100644 index 0000000..4783e13 --- /dev/null +++ b/src/Seabug/Metadata/Types.purs @@ -0,0 +1,310 @@ +module Seabug.Metadata.Types + ( SeabugMetadata(..) + , SeabugMetadataDelta(..) + , decodeSeabugMetadataAeson + , metadataBytesString + ) where + +import Contract.Prelude + +import Aeson (Aeson, JsonDecodeError(..), caseAesonObject, getField, (.:)) +import Contract.Prim.ByteArray (ByteArray, byteArrayToHex) +import Contract.Value (CurrencySymbol, getCurrencySymbol, mkCurrencySymbol) +import Data.BigInt (fromInt) as BigInt +import Data.Either (Either(Left), note) +import Data.Generic.Rep (class Generic) +import Data.Map (toUnfoldable) as Map +import Data.Maybe (Maybe(Nothing)) +import Data.Newtype (class Newtype, wrap) +import Data.Show.Generic (genericShow) +import Data.String (Pattern(..), stripPrefix) +import Data.Tuple (Tuple(Tuple)) +import Data.Tuple.Nested ((/\)) +import FromData (class FromData, fromData) +import Metadata.FromMetadata (class FromMetadata, fromMetadata) +import Metadata.Helpers (unsafeMkKey, lookupKey, lookupMetadata) +import Metadata.MetadataType (class MetadataType, metadataLabel) +import Metadata.ToMetadata (class ToMetadata, toMetadata) +import Partial.Unsafe (unsafePartial) +import Plutus.Types.AssocMap (Map(Map)) as AssocMap +import Seabug.Metadata.Share (Share, mkShare) +import Serialization.Hash + ( ScriptHash + , ed25519KeyHashFromBytes + , scriptHashFromBytes + ) +import ToData (class ToData, toData) +import Type.Proxy (Proxy(Proxy)) +import Types.Natural (Natural) +import Types.PlutusData (PlutusData(Map)) +import Types.PubKeyHash (PubKeyHash) +import Types.RawBytes (RawBytes, hexToRawBytes) +import Types.Scripts (ValidatorHash) +import Types.TokenName (TokenName, mkTokenName) +import Types.TransactionMetadata (TransactionMetadatum(MetadataMap)) + +newtype SeabugMetadata = SeabugMetadata + { policyId :: CurrencySymbol + , mintPolicy :: String + , collectionNftCS :: CurrencySymbol + , collectionNftTN :: TokenName + , lockingScript :: ValidatorHash + , authorPkh :: PubKeyHash + , authorShare :: Share + , marketplaceScript :: ValidatorHash + , marketplaceShare :: Share + , ownerPkh :: PubKeyHash + , ownerPrice :: Natural + } + +derive instance Generic SeabugMetadata _ +derive instance Newtype SeabugMetadata _ +derive instance Eq SeabugMetadata + +instance Show SeabugMetadata where + show = genericShow + +instance MetadataType SeabugMetadata where + metadataLabel _ = wrap (BigInt.fromInt 727) + +instance ToMetadata SeabugMetadata where + toMetadata (SeabugMetadata meta) = toMetadata + [ meta.policyId /\ + [ "mintPolicy" /\ toMetadata meta.mintPolicy + , "collectionNftCS" /\ toMetadata meta.collectionNftCS + , "collectionNftTN" /\ toMetadata meta.collectionNftTN + , "lockingScript" /\ toMetadata meta.lockingScript + , "authorPkh" /\ toMetadata meta.authorPkh + , "authorShare" /\ toMetadata meta.authorShare + , "marketplaceScript" /\ toMetadata meta.marketplaceScript + , "marketplaceShare" /\ toMetadata meta.marketplaceShare + , "ownerPkh" /\ toMetadata meta.ownerPkh + , "ownerPrice" /\ toMetadata meta.ownerPrice + ] + ] + +instance FromMetadata SeabugMetadata where + fromMetadata (MetadataMap mp) = do + policyId /\ contents <- case Map.toUnfoldable mp of + [ policyId /\ contents ] -> + Tuple <$> fromMetadata policyId <*> pure contents + _ -> Nothing + mintPolicy <- + lookupMetadata "mintPolicy" contents >>= fromMetadata + collectionNftCS <- + lookupMetadata "collectionNftCS" contents >>= fromMetadata + collectionNftTN <- + lookupMetadata "collectionNftTN" contents >>= fromMetadata + lockingScript <- + lookupMetadata "lockingScript" contents >>= fromMetadata + authorPkh <- + lookupMetadata "authorPkh" contents >>= fromMetadata + authorShare <- + lookupMetadata "authorShare" contents >>= fromMetadata + marketplaceScript <- + lookupMetadata "marketplaceScript" contents >>= fromMetadata + marketplaceShare <- + lookupMetadata "marketplaceShare" contents >>= fromMetadata + ownerPkh <- + lookupMetadata "ownerPkh" contents >>= fromMetadata + ownerPrice <- + lookupMetadata "ownerPrice" contents >>= fromMetadata + pure $ SeabugMetadata + { policyId + , mintPolicy + , collectionNftCS + , collectionNftTN + , lockingScript + , authorPkh + , authorShare + , marketplaceScript + , marketplaceShare + , ownerPkh + , ownerPrice + } + fromMetadata _ = Nothing + +instance ToData SeabugMetadata where + toData (SeabugMetadata meta) = unsafePartial $ toData $ AssocMap.Map + [ unsafeMkKey "727" /\ AssocMap.Map + [ meta.policyId /\ AssocMap.Map + [ unsafeMkKey "mintPolicy" /\ toData meta.mintPolicy + , unsafeMkKey "collectionNftCS" /\ toData meta.collectionNftCS + , unsafeMkKey "collectionNftTN" /\ toData meta.collectionNftTN + , unsafeMkKey "lockingScript" /\ toData meta.lockingScript + , unsafeMkKey "authorPkh" /\ toData meta.authorPkh + , unsafeMkKey "authorShare" /\ toData meta.authorShare + , unsafeMkKey "marketplaceScript" /\ toData meta.marketplaceScript + , unsafeMkKey "marketplaceShare" /\ toData meta.marketplaceShare + , unsafeMkKey "ownerPkh" /\ toData meta.ownerPkh + , unsafeMkKey "ownerPrice" /\ toData meta.ownerPrice + ] + ] + ] + +instance FromData SeabugMetadata where + fromData sm = unsafePartial do + policyId /\ contents <- lookupKey "727" sm >>= case _ of + Map [ policyId /\ contents ] -> + Tuple <$> fromData policyId <*> fromData contents + _ -> Nothing + mintPolicy <- lookupKey "mintPolicy" contents >>= fromData + collectionNftCS <- lookupKey "collectionNftCS" contents >>= fromData + collectionNftTN <- lookupKey "collectionNftTN" contents >>= fromData + lockingScript <- lookupKey "lockingScript" contents >>= fromData + authorPkh <- lookupKey "authorPkh" contents >>= fromData + authorShare <- lookupKey "authorShare" contents >>= fromData + marketplaceScript <- lookupKey "marketplaceScript" contents >>= fromData + marketplaceShare <- lookupKey "marketplaceShare" contents >>= fromData + ownerPkh <- lookupKey "ownerPkh" contents >>= fromData + ownerPrice <- lookupKey "ownerPrice" contents >>= fromData + pure $ SeabugMetadata + { policyId + , mintPolicy + , collectionNftCS + , collectionNftTN + , lockingScript + , authorPkh + , authorShare + , marketplaceScript + , marketplaceShare + , ownerPkh + , ownerPrice + } + +-- | Convert a byte array into a string as represented in the metadata +-- | json, i.e. hex encoded with "0x" prepended. +metadataBytesString :: ByteArray -> String +metadataBytesString = ("0x" <> _) <<< byteArrayToHex + +-- | Attempt to decode seabug metadata at the key specified by the +-- | passed in `CurrencySymbol` (the `policyId`) +decodeSeabugMetadataAeson + :: CurrencySymbol -> Aeson -> Either JsonDecodeError SeabugMetadata +decodeSeabugMetadataAeson policyId = + caseAesonObject (Left (TypeMismatch "Expected object")) + $ (_ .: policyIdField) + >=> caseAesonObject (Left (TypeMismatch "Expected object")) parseMd + where + policyIdField = metadataBytesString $ getCurrencySymbol policyId + + parseMd o = do + collectionNftCS <- + ( note (TypeMismatch "Invalid CurrencySymbol") + <<< mkCurrencySymbol + <<< unwrap + <=< decodeMetadataBytes + ) + =<< getField o "collectionNftCS" + collectionNftTN <- + ( note (TypeMismatch "expected ASCII-encoded `TokenName`") + <<< mkTokenName + <<< unwrap + <=< decodeMetadataBytes + ) + =<< getField o "collectionNftTN" + lockingScript <- + map wrap + <<< decodeScriptHash + =<< getField o "lockingScript" + authorPkh <- decodePkh =<< getField o "authorPkh" + authorShare <- decodeShare =<< getField o "authorShare" + marketplaceScript <- map wrap <<< decodeScriptHash + =<< getField o "marketplaceScript" + marketplaceShare <- decodeShare =<< getField o "marketplaceShare" + ownerPkh <- decodePkh =<< getField o "ownerPkh" + ownerPrice <- getField o "ownerPrice" + mintPolicy <- getField o "mintPolicy" + pure $ SeabugMetadata + { -- Not used in the endpoints where we parse the metadata, so we + -- can set a dummy value + policyId + , mintPolicy + , collectionNftCS + , collectionNftTN + , lockingScript + , authorPkh + , authorShare + , marketplaceScript + , marketplaceShare + , ownerPkh + , ownerPrice + } + + decodePkh :: String -> Either JsonDecodeError PubKeyHash + decodePkh = + map wrap + <<< note (TypeMismatch "Invalid Ed25519KeyHash") + <<< ed25519KeyHashFromBytes + <=< decodeMetadataBytes + + decodeShare :: Int -> Either JsonDecodeError Share + decodeShare = note (TypeMismatch "Expected int between 0 and 10000") + <<< mkShare + + decodeScriptHash :: String -> Either JsonDecodeError ScriptHash + decodeScriptHash = + note (TypeMismatch "Expected hex-encoded script hash") + <<< scriptHashFromBytes + <=< decodeMetadataBytes + + decodeMetadataBytes :: String -> Either JsonDecodeError RawBytes + decodeMetadataBytes = + note (TypeMismatch "Invalid hex string in bytes field") <<< hexToRawBytes + <=< note (TypeMismatch "Expected 0x prefix in bytes field") + <<< stripPrefix (Pattern "0x") + +newtype SeabugMetadataDelta = SeabugMetadataDelta + { policyId :: CurrencySymbol + , ownerPkh :: PubKeyHash + , ownerPrice :: Natural + } + +derive instance Generic SeabugMetadataDelta _ +derive instance Newtype SeabugMetadataDelta _ +derive instance Eq SeabugMetadataDelta + +instance Show SeabugMetadataDelta where + show = genericShow + +instance MetadataType SeabugMetadataDelta where + metadataLabel _ = metadataLabel (Proxy :: Proxy SeabugMetadata) + +instance ToMetadata SeabugMetadataDelta where + toMetadata (SeabugMetadataDelta meta) = toMetadata + [ meta.policyId /\ + [ "ownerPkh" /\ toMetadata meta.ownerPkh + , "ownerPrice" /\ toMetadata meta.ownerPrice + ] + ] + +instance FromMetadata SeabugMetadataDelta where + fromMetadata (MetadataMap mp) = do + policyId /\ contents <- case Map.toUnfoldable mp of + [ policyId /\ contents ] -> + Tuple <$> fromMetadata policyId <*> pure contents + _ -> Nothing + ownerPkh <- lookupMetadata "ownerPkh" contents >>= fromMetadata + ownerPrice <- lookupMetadata "ownerPrice" contents >>= fromMetadata + pure $ SeabugMetadataDelta { policyId, ownerPkh, ownerPrice } + fromMetadata _ = Nothing + +instance ToData SeabugMetadataDelta where + toData (SeabugMetadataDelta meta) = unsafePartial $ toData $ AssocMap.Map + [ unsafeMkKey "727" /\ AssocMap.Map + [ meta.policyId /\ AssocMap.Map + [ unsafeMkKey "ownerPkh" /\ toData meta.ownerPkh + , unsafeMkKey "ownerPrice" /\ toData meta.ownerPrice + ] + ] + ] + +instance FromData SeabugMetadataDelta where + fromData sm = unsafePartial do + policyId /\ contents <- lookupKey "727" sm >>= case _ of + Map [ policyId /\ contents ] -> + Tuple <$> fromData policyId <*> fromData contents + _ -> Nothing + ownerPkh <- lookupKey "ownerPkh" contents >>= fromData + ownerPrice <- lookupKey "ownerPrice" contents >>= fromData + pure $ SeabugMetadataDelta { policyId, ownerPkh, ownerPrice } diff --git a/src/Seabug/MintingPolicy.js b/src/Seabug/MintingPolicy.js index 19565a3..8d2b9f9 100644 --- a/src/Seabug/MintingPolicy.js +++ b/src/Seabug/MintingPolicy.js @@ -1,3 +1,7 @@ exports._mintingPolicy = { - mintingPolicy: "5912ef0100003233322232323232323322332232323233223233322232333222323333333322222222323233332222323233223233322232333222323233223322323233223232323232323232332232333332222233333222223322332233223322332233223232323222222223232323232232323333333322222222323232323232323530253530230082200222222222223233335303f01425335308b015335308b013335304b12001223535507f0022235355081010032253353091013305400400213305300300110920133505b335507e30480013370210e029001282e299a9a82f18078011080089931a98410099ab9c49010b756e726561636861626c65000830108001108d011335738921124e4654206d757374206265206275726e65640008c0115335308b015335308b013302c501135308401001222001108d0113357389211f4f776e6572206d757374207369676e20746865207472616e73616374696f6e0008c0115335308b0133355302e1200135045504f25335308c015335308c013304d35305500122200333058307b01b5060108d01108e011333573466e1cccc0b0d4c154004888008070d4c2140400888800d200208e0108d01108d0135303150112222222222009108d01133573892011f556e6465726c79696e67204e4654206d75737420626520756e6c6f636b65640008c01108c01108c012323232323225335309101533530910133301300735308a0100722200200110930113357389213e45786163746c79206f6e65206e657720746f6b656e206d757374206265206d696e74656420616e642065786163746c79206f6e65206f6c64206275726e7400092011533530910153353091013300550033305d30800101d5065153353091013300550023305d30810101f50651333553034120013504b5055330063305d30810135308a0100722200150653370266e054010c238054008c23805400d4058424804424804424c044cd5ce248113526f79616c6974696573206e6f742070616964000920110920113370666e09400807120a09c0113370666e09400406520a09c01135308601003222002225335308e01333573466e20008230042400423c044240044ccd54c0c448004d41214148cc00c004009404c888d4c15c0048894cd4c24404cc14801800c54cd4c24404ccd5cd19b8700533303100204f04f093010920115335350645335350640012132353039001222222222253353507033355304012001503f2353550900100122533530a001333573466e3c00803c28804284044d41d400c541d000884d41ccd4d542400400488004541c540605419484c8ccd5cd19baf0020010950109401323535508501001223374a900019aba0375200466ae80dd48009bb108a01335508501501a304f008109201109201109201225335308c015335308c0133300e00200135308501002222001108e0113357389213e45786163746c79206f6e65206e657720746f6b656e206d757374206265206d696e74656420616e642065786163746c79206f6e65206f6c64206275726e740008d0115335308c013302d501235308501002222001108e0113357389211f4f776e6572206d757374207369676e20746865207472616e73616374696f6e0008d01108d0125335308b015335308b0153353505a53353505e30120022100113263530820133573892010b756e726561636861626c65000830108001108c012213535507f0022253353505e00315335308f01333573466e3c008c13001424404240044ccd5cd19b87001480082440424004424004884248044234044cd5ce2491e45786163746c79206f6e65204e4654206d757374206265206d696e7465640008c0115335308b0133355302e1200135045504f25335308c013304d35305500122200333058307b01b50601333573466e1cccc0b0d4c154004888008070d4c2140400888800d200208e0108d01108d0135303150112222222222009108d01133573892011d556e6465726c79696e67204e4654206d757374206265206c6f636b65640008c01108c0135302f500f222222222200723222325335350565335350563006353029500922222222220072135059001150572153353505300110850122135355078002225335350570031089012213535507c0022253353505b00315335308c015335308c013304f006500d13304f002500a108d0115335308c01333573466e1c015200108e0108d011333573466e1c005200208e0108d01108d0115335308c015335308c013304f002500d13304f006500a108d0115335308c01333573466e1c005200108e0108d011333573466e1c015200208e0108d01108d01108d0122108f011084011303f35307b00422233307f0030050041303c00132001355080012253353504e001150532213535507300222533530830133046002500b135058001130060033200135507f2253353504d001150522213535507200222533530820133045002500a13505700113006003135302150012222222222009135301e003220023200135507c2253353504a0011504f2213535506f002225335307f33042002500713505400113006003135301c0012233335302a0012326353072335738921024c6800073070200123263530723357389201024c680007307023263530723357389201024c6800073070375c01e6eb8038dd700698358061bae00b306b00a3333573466e1d40112000230273065500623333573466e1d401520062302b3066500723333573466e1d4019200223302a30675008306e500923333573466e1d401d200423302c30685009375ca014464c6a60d666ae701a81b01a41a019c198194cccd5cd19b8735573aa004900011980b19191919191919191919191999ab9a3370e6aae754029200023333333333024335044232323333573466e1cd55cea8012400046605460ae6ae854008c124d5d09aba2500223263530783357380ee0f20ec0ea26aae7940044dd50009aba1500a33504404535742a012666aa096eb94128d5d0a804199aa825bae504a35742a00e66a0880ba6ae854018cd4110cd541b8199d69aba150053232323333573466e1cd55cea80124000466a0586464646666ae68cdc39aab9d5002480008cd40d0cd417dd69aba150023064357426ae8940088c98d4c1f0cd5ce03d83e83d03c89aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa0049000119a81919a82fbad35742a00460c86ae84d5d1280111931a983e19ab9c07b07d07a079135573ca00226ea8004d5d09aba2500223263530783357380ee0f20ec0ea26aae7940044dd50009aba1500433504475c6ae85400ccd4110cd541b9d710009aba150023056357426ae8940088c98d4c1d0cd5ce03983a83903889aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aab9e5001137540026ae854008c8c8c8cccd5cd19b875001480188c0a4c154d5d09aab9e500323333573466e1d4009200423028305f357426aae7940108cccd5cd19b875003480088c0a0c134d5d09aab9e500523333573466e1d401120002302b375c6ae84d55cf280311931a983799ab9c06e07006d06c06b06a069135573aa00226ea8004d5d09aba2500223263530683357380ce0d20cc0ca26aae7940044dd500089aab9d5004135742a00426ae84d5d1280089aab9e5001137540024446464600200a640026aa0ce4466a6a06a0029000111a9aa82d00111299a9835199ab9a3371e0040120d80d62600e0022600c006640026aa0cc4466a6a0680029000111a9aa82c80111299a9834999ab9a3371e00400e0d60d420022600c006446a600e0044444444444a66a6a07c666aa601c24002a01a4a66a60d8666ae68cdc780600083703689a8208008a820001908370836099a80d11299a9a819801108018800a819190009aa8301108911299a9a81880089a9a80e80191000910999a9a80f802910011802001199aa9803890008028020009109198008018011000911111111109199999999980080580500480400380300280200180110009109198008018011000891091980080180109000891091980080180109000891091980080180109000909111180200290911118018029091111801002909111180080290009091111802002910911119801803002910911119801003002909111180080290008919a80191199a9a807001910010010009a9a8060009100089109198008018010900091b9433355300312001714004664466004646e50cc118004014d4c0fc00c888008cc008dca1a981f801911000998011b9435303f00322200300150145015489003200135504422112225335350150011002221330050023335530071200100500400132001355043221222533535014002153353501400110472210482215335350160031048221533530493300700400213335300912001007003001104a2235300c0022235300e0032232335303400523353035004253353048333573466e3c0080041281245400c412481248cd4c0d4010812494cd4c120ccd5cd19b8f00200104a04915003104915335350180032153353501900221335303100223353032002233530370022335303800223300e002001204c2335303800220v4c23300e00200122204c2223353034004204c2225335304d333573466e1c01800c13c13854cd4c134ccd5cd19b8700500204f04e13300f004001104e104e1047153353501800121047104722333573466e1c00800410810488ccd5cd19b8f0020010410401335002225335303e0021040100103d1221233001003002120011232230023758002640026aa07a446666aae7c004940388cd4034c010d5d080118019aba200203423232323333573466e1cd55cea801a4000466600e6464646666ae68cdc39aab9d5002480008cc034c0b8d5d0a80119a8098151aba135744a004464c6a607066ae700dc0e40d80d44d55cf280089baa00135742a006666aa016eb94028d5d0a80119a807bae357426ae8940088c98d4c0d0cd5ce01981a81901889aba25001135573ca00226ea800488848ccc00401000c00880048848cc00400c00880044cd54005d73ad112232230023756002640026aa06e44646666aae7c008940248cd4020cd540acc018d55cea80118029aab9e500230043574400605e26ae840044488008488488cc00401000c48004488c8c8cccd5cd19b875001480008d4020c014d5d09aab9e500323333573466e1d4009200225008232635302b33573805405805205004e26aae7540044dd5000890911801001889100089000919191999ab9a3370e6aae7540092000233006300735742a0046eb4d5d09aba25002232635302533573804804c04604426aae7940044dd500091091980080180110009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931a981099ab9c02002201f01e1375400224464646666ae68cdc3a800a40084a00e46666ae68cdc3a8012400446a014600c6ae84d55cf280211999ab9a3370ea00690001280511931a981219ab9c02302502202102001f135573aa00226ea8004484888c00c0104488800844888004480048c8cccd5cd19b8750014800880988cccd5cd19b8750024800080988c98d4c070cd5ce00d80e80d00c80c09aab9d3754002464646464646666ae68cdc3a800a4018401646666ae68cdc3a80124014401a46666ae68cdc3a801a40104660166eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc034dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a9002119809180a1aba15009375c6ae84d5d1280491999ab9a3370ea00c90011180a180a9aba135573ca01646666ae68cdc3a803a400046026602c6ae84d55cf280611931a981219ab9c02302502202102001f01e01d01c01b135573aa00826aae79400c4d55cf280109aab9e500113754002424444444600e01044244444446600c012010424444444600a010244444440082444444400644244444446600401201044244444446600201201040024646464646666ae68cdc3a800a400446660106eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d400920002300a300b357426aae7940188c98d4c054cd5ce00a00b00980900889aab9d5003135744a00226aae7940044dd5000909118010019110911998008028020019000919191999ab9a3370ea0029001118031bae357426aae79400c8cccd5cd19b875002480008c020dd71aba135573ca008464c6a601e66ae7003804003403002c4d55cea80089baa001212230020032122300100320011122232323333573466e1cd55cea80124000466aa010600c6ae854008c014d5d09aba25002232635300c33573801601a01401226aae7940044dd50008891091980080180108900091919191999ab9a3370e6aae75400d2000233300b375c6ae85400cc030d5d0a8011bae357426ae8940088c98d4c020cd5ce00380480300289aba25001135573ca00226ea8005264901035054310012001200122212333001004003002200123253353007333573466e21400400c02402058540044dd6800a40004a66a6008666ae68cdc40008010030028a400020029040497a00990009aa802111299a9802199ab9a33710004904002003002899b8b0020011330033370600490400219b8b3370c00490400200089100109100090008891918008009119801980100100081" + mintingPolicy: { + getMintingPolicy: + "5912eb01000032323332223232323233223233223232332232323233322233322233322233223233322232323232332232333332222232323333333322222222333322223322332233223322332233223322332232323232323232323232323232323233333222223322222222322323232323223232533530703300a3333573466e1d40112000230473066500623333573466e1d401520062304b3067500723333573466e1d4019200223304a30685008306f500923333573466e1d401d200423304c30695009375ca014464c6a60d666ae701b41b01a81a41a019c198cccd5cd19b8735573aa004900011980999191919191919191919191999ab9a3370e6aae754029200023333333333035335025232323333573466e1cd55cea80124000466076605c6ae854008c0a8d5d09aba2500223263530783357380f40f20ee0ec26aae7940044dd50009aba1500a33502502635742a012666aa050eb9409cd5d0a804199aa8143ae502735742a00e66a04a05c6ae854018cd4094cd540c40bdd69aba150053232323333573466e1cd55cea80124000466a0866464646666ae68cdc39aab9d5002480008cd412ccd40d1d69aba150023035357426ae8940088c98d4c1f0cd5ce03f03e83d83d09aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa0049000119a82499a81a3ad35742a004606a6ae84d5d1280111931a983e19ab9c07e07d07b07a135573ca00226ea8004d5d09aba2500223263530783357380f40f20ee0ec26aae7940044dd50009aba1500433502575c6ae85400ccd4094cd540c5d710009aba15002302b357426ae8940088c98d4c1d0cd5ce03b03a83983909aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aab9e5001137540026ae854008c8c8c8cccd5cd19b875001480188c070c098d5d09aab9e500323333573466e1d400920042301b3028357426aae7940108cccd5cd19b875003480088c06cc090d5d09aab9e500523333573466e1d401120002301e375c6ae84d55cf280311931a983799ab9c07107006e06d06c06b06a135573aa00226ea8004d5d09aba2500223263530683357380d40d20ce0cc20d0264c6a60ce66ae7124010350543500068066135573ca00226ea80044d55cea80209aba150021357426ae8940044d55cf280089baa001333333222222223232323232323235302c3530160082200222222222223233335305501425335308101533530810133353061120012235355040002223535504200322533530870133078004002133077003001108801335063335503f305e001337020fc90012832299a9a83418078011080089931a983c19ab9c49010b756e726561636861626c65000790771083011335738921124e4654206d757374206265206275726e6564000820115335308101533530810133037501135307b00122200110830113357389211f4f776e6572206d757374207369676e20746865207472616e73616374696f6e000820115335308101333553055120013505b50732533530820153353082013306635303d00122200333068307001b506a1083011084011333573466e1cccc0dcd4c0f4004888008070d4c1f000888800d2002084010830110830135303850112222222222009108301133573892011f556e6465726c79696e67204e4654206d75737420626520756e6c6f636b65640008201108201108201232323232322533530870153353087013330130073530810100722200200110890113357389213e45786163746c79206f6e65206e657720746f6b656e206d757374206265206d696e74656420616e642065786163746c79206f6e65206f6c64206275726e7400088011533530870153353087013300550033306d307501d506f153353087013300550023306d307601f506f133355305b12001350615079330063306d307635308101007222001506f3370266e054010c218054008c21805400d40584220044220044224044cd5ce248113526f79616c6974696573206e6f742070616964000880110880113370666e09400807120a09c0113370666e09400406520a09c01135307d003222002225335308401333573466e2000821c0421804214044218044ccd54c16048004d417941d8cc00c004009404c888d4c0fc0048894cd4c21c04cc1ac01800c54cd4c21c04ccd5cd19b8700533303c0020650650890108801153353506e53353506e0012132353040001222222222253353507a333553067120015066235355051001225335309601333573466e3c00803c2600425c044d41fc00c541f800884d41f4d4d5414400488004541ed4060541bc84c8ccd5cd19baf00200108b0108a013235355046001223374a900019aba0375200466ae80dd48009bb1081013355046501a3065008108801108801108801225335308201533530820133300e00200135307c00222200110840113357389213e45786163746c79206f6e65206e657720746f6b656e206d757374206265206d696e74656420616e642065786163746c79206f6e65206f6c64206275726e7400083011533530820133038501235307c00222200110840113357389211f4f776e6572206d757374207369676e20746865207472616e73616374696f6e0008301108301253353081015335308101533535062533535068301200221001132635307833573892010b756e726561636861626c6500079077108201221353550400022253353506600315335308501333573466e3c008c18801421c04218044ccd5cd19b870014800821c042180442180488422004420c044cd5ce2491e45786163746c79206f6e65204e4654206d757374206265206d696e746564000820115335308101333553055120013505b5073253353082013306635303d00122200333068307001b506a1333573466e1cccc0dcd4c0f4004888008070d4c1f000888800d2002084010830110830135303850112222222222009108301133573892011d556e6465726c79696e67204e4654206d757374206265206c6f636b65640008201108201353036500f222222222200723222325335350605335350603006353030500922222222220072135063001150612153353505b001107b221353550390022253353505f003107f2213535503d0022253353506300315335308201533530820133073006500d133073002500a10830115335308201333573466e1c015200108401083011333573466e1c0052002084010830110830115335308201533530820133073002500d133073006500a10830115335308201333573466e1c005200108401083011333573466e1c0152002084010830110830110830122108501107a130553530720042223330760030050041305200132001355077225335350560011505d2213535503400222533530793306a002500b1350620011300600332001355076225335350550011505c22135355033002225335307833069002500a1350610011300600313530285001222222222200913530110032200232001355073225335350520011505922135355030002225335307533066002500713505e00113006003135300f001223333530130012326353068335738921024c6800069067200123263530683357389201024c680006906723263530683357389201024c6800069067375c00c6eb8014dd700218310019bae00230620012212330010030022001212222300400521222230030052122223002005212222300100520011232230023758002640026aa0ba446666aae7c004940fc8cd40f8c010d5d080118019aba200205323232323333573466e1cd55cea801a400046660306464646666ae68cdc39aab9d5002480008cc118c04cd5d0a80119a8060091aba135744a004464c6a60ae66ae701641601581544d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4c14ccd5ce02a82a02902889aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa0b644646666aae7c008940f88cd40f4cd54064c018d55cea80118029aab9e50023004357440060a426ae84004488c8c8cccd5cd19b875001480008d4108c014d5d09aab9e500323333573466e1d400920022504223263530513357380a60a40a009e09c26aae7540044dd5000919191999ab9a3370e6aae7540092000233017300535742a0046eb4d5d09aba25002232635304e3357380a009e09a09826aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931a982619ab9c04e04d04b04a1375400224464646666ae68cdc3a800a40084a03c46666ae68cdc3a8012400446a042600c6ae84d55cf280211999ab9a3370ea00690001281091931a982799ab9c05105004e04d04c04b135573aa00226ea80048c8cccd5cd19b8750014800881548cccd5cd19b8750024800081548c98d4c12ccd5ce02682602502482409aab9d3754002464646464646666ae68cdc3a800a4018404846666ae68cdc3a80124014404c46666ae68cdc3a801a40104660486eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc098dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211981598061aba15009375c6ae84d5d1280491999ab9a3370ea00c90011181698069aba135573ca01646666ae68cdc3a803a400046058601c6ae84d55cf280611931a982999ab9c05505405205105004f04e04d04c04b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466607e6eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d40092000230413008357426aae7940188c98d4c130cd5ce02702682582502489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea00290011181f9bae357426aae79400c8cccd5cd19b875002480008c104dd71aba135573ca008464c6a609266ae7012c12812011c1184d55cea80089baa0011122232323333573466e1cd55cea80124000466aa020600c6ae854008c014d5d09aba25002232635304933573809609409008e26aae7940044dd500091119191800802990009aa8299119a9a819000a4000446a6aa02000444a66a60aa666ae68cdc780100482b82b0980380089803001990009aa8291119a9a818800a4000446a6aa01e00444a66a60a8666ae68cdc780100382b02a880089803001911a98018011111111111299a9a81e999aa981509000a8149299a982b999ab9a3371e0180020b20b026a0800022a07e006420b220ae444444444424666666666600201601401201000e00c00a008006004400244246600200600440024442466600200800600440022244246600200600422400244246600200600440022442466002006004240022442466002006004240022442466002006004240022424446006008224440042244400224002424444444600e01044244444446600c012010424444444600a01024444444008244444440064424444444660040120104424444444660020120104002266a01244a66a6a02c004420062002a02a640026aa0604422444a66a6a02400226a6a01800644002442666a6a01c00a440046008004666aa600e2400200a008002424444600800a44244446600600c00a44244446600400c00a424444600200a40022466a00644666a6a038006440040040026a6a0340024400224424660020060042400246e50ccd54c00c48005c500119a803191b943302300100335301e00122200233500637286a603c00244400266a00c6e50d4c07800488800d401d2201003200135502522112225335350070011002221330050023335530071200100500400132001355024221222533535006002153353500600110272210282215335350080031028221533530293300700400213335300912001007003001102a1122002122122330010040031200122353003002223530050032232335301000523353011004253353025333573466e3c00800409c0985400c409880988cd4c044010809894cd4c094ccd5cd19b8f00200102702615003102615335350090032153353500a00221335300e0022335300f00223353013002233530140022330190020012029233530140022029233019002001222029222335301100420292225335302a333573466e1c01800c0b00ac54cd4c0a8ccd5cd19b8700500202c02b13301a004001102b102b1024153353500900121024102422123300100300220011212230020031122001120012122300200322212233300100500400320012122300200321223001003200122333573466e1c00800405004c88ccd5cd19b8f002001013012133500222533530100021012100100f12212330010030021200123232323333573466e1cd55cea801a400046660166eb8d5d0a80198061aba15002375c6ae84d5d1280111931a980399ab9c009008006005135744a00226aae7940044dd5000a4c2400240029201035054310022212333001004003002200123253353006333573466e21400400c02001c58540044dd6800a4000640026aa00c444a66a600a666ae68cdc4001241000800e00c266e2c0080044cc00ccdc1801241000866e2ccdc300124100080024a66a6004666ae68cdc40008028020018a4000200224400424400240029040497a00889191800800911980198010010009" + }, }; + diff --git a/src/Seabug/MintingPolicy.purs b/src/Seabug/MintingPolicy.purs index c641ce6..4fc4216 100644 --- a/src/Seabug/MintingPolicy.purs +++ b/src/Seabug/MintingPolicy.purs @@ -1,13 +1,49 @@ module Seabug.MintingPolicy - ( mintingPolicy + ( mkMintingPolicy + , mkTokenName + , unappliedMintingPolicy ) where import Contract.Prelude -import Contract.Scripts (MintingPolicy) + +import Contract.Monad (Contract, liftContractE) +import Contract.PlutusData (toData) +import Contract.Scripts (MintingPolicy, applyArgs) +import Contract.Value (TokenName) +import Contract.Value as Value import Data.Argonaut (Json, JsonDecodeError) +import QueryM as QueryM import Seabug.Helpers (jsonReader) +import Seabug.Types (NftCollection(..), NftId, hash) + +mkTokenName :: forall (r :: Row Type). NftId -> Contract r (Maybe TokenName) +mkTokenName nftId = hash nftId <#> maybe Nothing Value.mkTokenName + +mkMintingPolicy + :: forall (r :: Row Type) + . NftCollection + -> Contract r (Either QueryM.ClientError MintingPolicy) +mkMintingPolicy + ( NftCollection + { collectionNftCs + , lockingScript + , author + , authorShare + , daoScript + , daoShare + } + ) = do + p <- liftContractE unappliedMintingPolicy + applyArgs p + [ toData collectionNftCs + , toData lockingScript + , toData author + , toData authorShare + , toData daoScript + , toData daoShare + ] -mintingPolicy :: Either JsonDecodeError MintingPolicy -mintingPolicy = jsonReader "mintingPolicy" _mintingPolicy +unappliedMintingPolicy :: Either JsonDecodeError MintingPolicy +unappliedMintingPolicy = jsonReader "mintingPolicy" _mintingPolicy foreign import _mintingPolicy :: Json diff --git a/src/Seabug/Seabug.purs b/src/Seabug/Seabug.purs new file mode 100644 index 0000000..870df5f --- /dev/null +++ b/src/Seabug/Seabug.purs @@ -0,0 +1,40 @@ +module Seabug + ( module Seabug.CallContract + , module QueryM.Utxos + , mint + ) where + +import Contract.Prelude + +import Control.Promise (Promise) +import Data.BigInt as BigInt +import QueryM.Utxos (getWalletBalance) +import Seabug.CallContract + ( callMarketPlaceBuy + , callMarketPlaceListNft + , callMarketPlaceFetchNft + , callMint + ) + +mint :: Effect (Promise Unit) +mint = callMint + { serverHost: "ctl.localho.st" + , serverPort: 8080 + , serverSecureConn: false + , ogmiosHost: "localho.st" + , ogmiosPort: 1337 + , ogmiosSecureConn: false + , datumCacheHost: "localho.st" + , datumCachePort: 9999 + , datumCacheSecureConn: false + , networkId: 0 + , projectId: "testnetu7qDM8q2XT1S6gEBSicUIqXB6QN60l7B" + , logLevel: "Trace" + } + { -- base36 ipfs cid obtained from mint-nft.sh + imageUri: "ipfs://k2cwuebwvb6kdiwob6sb2yqnz38r0yv72q1xijbts9ep5lq3nm8rw3i4" + , tokenNameString: "abcdef" + , name: "Piaggio Ape" + , description: "Seabug Testing" + , price: BigInt.fromInt (12 * 1000000) + } diff --git a/src/Seabug/Test.purs b/src/Seabug/Test.purs index 3020b0f..ee43be2 100644 --- a/src/Seabug/Test.purs +++ b/src/Seabug/Test.purs @@ -4,7 +4,7 @@ import Contract.Prelude import Contract.Monad ( Contract - , defaultContractConfig + , defaultTestnetContractConfig , liftContractM , runContract_ ) @@ -16,7 +16,6 @@ import Contract.Prim.ByteArray import Contract.Time (Slot(Slot)) import Contract.Value (mkCurrencySymbol, mkTokenName) import Data.BigInt as BigInt -import Data.UInt as UInt import Effect.Aff (launchAff_) import Seabug.Contract.MarketPlaceBuy (marketplaceBuy) import Seabug.Types @@ -25,10 +24,11 @@ import Seabug.Types , NftId(NftId) ) import Serialization.Hash (ed25519KeyHashFromBytes, scriptHashFromBytes) +import Types.BigNum as BigNum main :: Effect Unit main = launchAff_ $ do - cfg <- defaultContractConfig + cfg <- defaultTestnetContractConfig runContract_ cfg $ do marketplaceBuy =<< testNftData @@ -41,6 +41,7 @@ testNftData :: forall (r :: Row Type). Contract r NftData testNftData = do kh <- liftContractM "`Ed25519KeyHash`" $ ed25519KeyHashFromBytes + <<< wrap =<< hexToByteArray "3f3464650beb5324d0e463ebe81fbe1fd519b6438521e96d0d35bd75" collectionNftCs <- liftContractM "`CurrencySymbol`" @@ -49,10 +50,12 @@ testNftData = do "cf0c1cbf47537f238f756fc1be191abf76009e1988910092184c4b7f" lockingScript <- liftContractM "`ScriptHash`" $ scriptHashFromBytes + <<< wrap =<< hexToByteArray "6c1039b6973bb0e7ad42de5b16a691ede3e0265cd58caf070ff15ef3" daoScript <- liftContractM "`ScriptHash`" $ scriptHashFromBytes + <<< wrap =<< hexToByteArray "9da8fa76a2a0f52aa5df10fb7b81f9afe4b20e9068b3f95fadc7477a" tokenName <- liftContractM "`TokenName`" @@ -62,7 +65,7 @@ testNftData = do { nftCollection: NftCollection { collectionNftCs , lockLockup: BigInt.fromInt 5 - , lockLockupEnd: Slot $ UInt.fromInt 5 + , lockLockupEnd: Slot $ BigNum.fromInt 5 , lockingScript: wrap lockingScript , author: wrap $ wrap kh , authorShare: fromBigInt' $ BigInt.fromInt 1000 diff --git a/src/Seabug/Token.js b/src/Seabug/Token.js deleted file mode 100644 index a3482eb..0000000 --- a/src/Seabug/Token.js +++ /dev/null @@ -1,4 +0,0 @@ -exports._unappliedMintingPolicy = { - mintingPolicy: - "590a9a010000323332223232323232332232332232323332223332223332223322323332223232332232323322323333322222332233333222223322332233223232323232222222223235300f0022235301300222223222222233335302901023232323232300100e3200135505a2253353503e0011533530593335303d12001051500332635302e3357389210b756e726561636861626c650002f01f150051500422135355054002225335305d333573466e3c009406417c17854cd4c174ccd4c10448004155401c00454024540204c01800c4cd40f0cd54140c0d4010cdc0a40009001281e8a99a982a99ab9c4901124e4654206d757374206265206275726e6564000561500110561533530543301b00f3530350022220011500115335305433573892011f4f776e6572206d757374207369676e20746865207472616e73616374696f6e0005515001105515335305333355301c120013502f50482353022001222533530573303f00333041304901a504310581333573466e1cccc07000806cd4c0e001488800d200205905800b105513357389211f556e6465726c79696e67204e4654206d75737420626520756e6c6f636b656400054232323232323225335305a33300f00835303b0082220020011500215335305a33573892013e45786163746c79206f6e65206e657720746f6b656e206d757374206265206d696e74656420616e642065786163746c79206f6e65206f6c64206275726e740005b15002105b15335305833004500233042304a018504415335305833004500133042304b01a50441533530583335530211200135034504d3300533042304b35303900622200150443370266e05400cc1514004c151400804041685415854158541584cdc199b8250020184828270044cdc199b8250010154828270044d4c0d800c888008894cd4c158ccd5cd19b880020530580571058133355301f1200135032504b3300300100200e2223530240012225335305933041006003153353059333573466e1c014ccc0780080e40e416c16854cd4d4110004854cd4d4114d4c09805488888888894cd4d413cccd54c0b44800540b08d4d54178004894cd4c19cccd5cd19b8f00200e0690681350540031505300221350523535505e00122001150502132333573466ebc008004178174c8d4d5415400488cdd2a400066ae80dd480119aba037520026ec4090cd54155405cc0e8024416c4168416841688c894cd4c154ccc02800c004d4c0d800c8880045400854cd4c154cd5ce2493e45786163746c79206f6e65206e657720746f6b656e206d757374206265206d696e74656420616e642065786163746c79206f6e65206f6c64206275726e74000561500210561533530533301a00e353034001222001105513357389211f4f776e6572206d757374207369676e20746865207472616e73616374696f6e00054232323232300100d320013550592253353503d001153353503d32635302d3357389210b756e726561636861626c650002e01e150042213300500200122135355053002225335305c333573466e3c009406017817454cd4d410400454020884cc0240080044c01800c88d4d54140008894cd4d40f800c54cd4c164ccd5cd19b8f002303800705b05a153353059333573466e1c005200205b05a150061500515005221500715335305433573892011e45786163746c79206f6e65204e4654206d757374206265206d696e7465640005515001105515335305333355301c120013502f50482353022001222533530573303f00333041304901a50431333573466e1cccc07000806cd4c0e001488800d2002059058105800b105513357389211d556e6465726c79696e67204e4654206d757374206265206c6f636b6564000542322232323001007320013550532253353503700110532213535504d0022253353056333573466e3c009404816015c54cd4d40ec004415c884d4d54144008894cd4d40fc00c416c884d4d5415400888c94cd4d411001054cd4c17cccd5cd19b8f007501306106015335305f333573466e3c00d404018418054cd4c17cccd5cd19b87006480041841804ccd5cd19b87002480081841804180540045400488418854cd4c178ccd5cd19b8f002501206005f15335305e333573466e3c019403c18017c54cd4c178ccd5cd19b870014800418017c4ccd5cd19b870054800818017c417c417c417c4c01800c4c0b8d4c0c0010888ccc0d000c0140104c0ac0044d4c03800488cccd4c0580048c98d4c070cd5ce249024c680001d00d2001232635301c3357389201024c680001d00d232635301c3357389201024c680001d00d222323230010053200135504222335350260014800088d4d540f0008894cd4c114ccd5cd19b8f00200904704613007001130060033200135504122335350250014800088d4d540ec008894cd4c110ccd5cd19b8f00200704604510011300600349888d4c01c00888888888894cd4d40c0ccd54c03848005403494cd4c118ccd5cd19b8f00c0010480471350330011503200321048104613350162253353502500221003100150243200135503a2211222533535021001135350190032200122133353501b005220023004002333553007120010050040012212330010030022001222222222212333333333300100b00a009008007006005004003002200122212333001004003002200121222230040052122223003005212222300200521222230010052001120012001212222300400522122223300300600522122223300200600521222230010052001123350032233353501d00322002002001353501b0012200112212330010030021200123724666aa600a24002e28008cc88cc008c8dc9198120008029a9802801911001198011b923530050032220013300237246a600a006444006002a010a01291100222123330010040030022001320013550202211222533535007001100222133005002333553007120010050040013200135501f22122253353500600215335350060011023221024221533535008003102422153353025330070040021333530091200100700300110261122002122122330010040031200122353003002223530050032232335301000523353011004253353021333573466e3c00800408c0885400c408880888cd4c044010808894cd4c084ccd5cd19b8f00200102302215003102215335350090032153353500a00221335300e0022335300f002233530130022335301400223301800200120252335301400220252330180020012220252223353011004202522253353026333573466e1c01800c0a009c54cd4c098ccd5cd19b87005002028027133021004001102710271020153353500900121020102022123300100300220011212230020031122001120012122300200322212233300100500400320012122300200321223001003200122333573466e3c00800404003c4cd4008894cd4c034008403c400403048848cc00400c0084800488d4d5400c00888d4d5401400c894cd4c038ccd5cd19b8f00400201000f133009003001100f1122123300100300211200122333573466e1c00800402402094cd4c014ccd5cd19b880010020070061480004005208092f401133573892113526f79616c6974696573206e6f742070616964000033200135500422253353004333573466e2000920800400600513371600400226600666e0c0092080043371666e180092080040011220021220012001112323001001223300330020020011", -}; diff --git a/src/Seabug/Token.purs b/src/Seabug/Token.purs deleted file mode 100644 index f07aec2..0000000 --- a/src/Seabug/Token.purs +++ /dev/null @@ -1,58 +0,0 @@ -module Seabug.Token - ( mkTokenName - , policy - , unappliedMintingPolicy - ) where - -import Contract.Prelude -import Contract.Monad (Contract) -import Contract.PlutusData (toData) -import Contract.Scripts (MintingPolicy, applyArgsM) -import Contract.Value (mkTokenName) as Value -import Contract.Value (TokenName) -import Data.Argonaut (Json, JsonDecodeError) -import Seabug.Helpers (jsonReader) -import Seabug.Types (NftCollection(NftCollection), NftId, hash) - --- rev: 2c9ce295ccef4af3f3cb785982dfe554f8781541 -mkTokenName :: forall (r :: Row Type). NftId -> Contract r (Maybe TokenName) -mkTokenName nftId = hash nftId <#> maybe Nothing Value.mkTokenName - --- rev: 2c9ce295ccef4af3f3cb785982dfe554f8781541 --- Apply arguments to an unapplied `MintingPolicy` to give a `MintingPolicy`. --- It's possible this is given as JSON since we don't have --- `mkMintingPolicyScript`. -policy - :: forall (r :: Row Type) - . NftCollection - -> MintingPolicy - -> Contract r (Maybe MintingPolicy) -policy - ( NftCollection - { collectionNftCs -- CurrencySymbol - , lockingScript -- ValidatorHash - , author -- PaymentPubKeyHash - , authorShare -- Natural - , daoScript -- ValidatorHash - , daoShare -- Natural - } - ) - mph = - let - pd = - [ toData collectionNftCs - , toData lockingScript - , toData author - , toData authorShare - , toData daoScript - , toData daoShare - ] - in - applyArgsM mph pd - --- This is read in locally as a minting policy with unapplied arguments. We --- may prefer to change this to a fully appllied MintingPolicy. -unappliedMintingPolicy :: Either JsonDecodeError MintingPolicy -unappliedMintingPolicy = jsonReader "mintingPolicy" _unappliedMintingPolicy - -foreign import _unappliedMintingPolicy :: Json diff --git a/src/Seabug/Types.purs b/src/Seabug/Types.purs index cc5790f..0efdfb6 100644 --- a/src/Seabug/Types.purs +++ b/src/Seabug/Types.purs @@ -1,30 +1,22 @@ module Seabug.Types ( MarketplaceDatum(..) + , LockDatum(..) , MintAct(..) , MintParams(..) , NftCollection(..) , NftData(..) , NftId(..) + , MintCnftParams(..) , class Hashable , hash ) where import Contract.Prelude -import Affjax as Affjax -import Affjax.RequestBody as Affjax.RequestBody -import Affjax.ResponseFormat as Affjax.ResponseFormat -import Cardano.Types.Value as Cardano.Types.Value -import Contract.Value - ( CurrencySymbol - , TokenName - , getCurrencySymbol - , getTokenName - , mkCurrencySymbol - ) -import Contract.Monad (Contract(Contract), mkHttpUrl) import Contract.Address (PaymentPubKeyHash, PubKeyHash) -import Contract.Aeson (caseAesonObject, getField, jsonToAeson) as Aeson +import Contract.Aeson as Aeson +import Contract.Monad (Contract) +import Contract.Numeric.Natural (Natural, toBigInt) import Contract.PlutusData ( class FromData , class ToData @@ -32,50 +24,45 @@ import Contract.PlutusData , fromData , toData ) -import Contract.Prim.ByteArray - ( ByteArray - , byteArrayFromIntArrayUnsafe - , byteArrayToHex - ) -import Contract.Numeric.Natural (Natural, toBigInt) -import Contract.Scripts - ( ValidatorHash - , ed25519KeyHashToBytes - , scriptHashToBytes - ) +import Contract.Prim.ByteArray (ByteArray, byteArrayFromIntArrayUnsafe) +import Contract.Scripts (ValidatorHash) import Contract.Time (Slot) -import Control.Monad.Reader.Trans (asks) +import Contract.Value + ( CurrencySymbol + , TokenName + , getCurrencySymbol + , getTokenName + ) import Data.Argonaut as Json -import Data.Argonaut.Encode.Encoders (encodeString) -import Data.Bifunctor (bimap, lmap) import Data.BigInt (BigInt, fromInt, toInt) +import Hashing (blake2b256Hash) import Partial.Unsafe (unsafePartial) +import Serialization.Hash (ed25519KeyHashToBytes, scriptHashToBytes) + +newtype MintCnftParams = MintCnftParams + { imageUri :: String + -- | The token name of the collection nft + , tokenNameString :: String + , name :: String + , description :: String + } + +derive instance Generic MintCnftParams _ +derive instance Newtype MintCnftParams _ +derive newtype instance Eq MintCnftParams + +instance Show MintCnftParams where + show = genericShow -blake2bHash :: forall (r :: Row Type). ByteArray -> Contract r (Maybe ByteArray) -blake2bHash bytes = Contract $ do - url <- asks $ (_ <> "/" <> "blake2b") <<< mkHttpUrl <<< _.serverConfig - let - reqBody :: Maybe Affjax.RequestBody.RequestBody - reqBody = Just - $ Affjax.RequestBody.Json - $ encodeString - $ byteArrayToHex bytes - liftAff (Affjax.post Affjax.ResponseFormat.json url reqBody) - <#> either (const Nothing) (hush <<< Json.decodeJson <<< _.body) - --- Field names have been simplified due to row polymorphism. Please let me know --- if the field names must be exact. -- | Parameters that need to be submitted when minting a new NFT. newtype MintParams = MintParams - { -- | Shares retained by author. - authorShare :: Natural + { authorShare :: Natural , daoShare :: Natural , -- | Listing price of the NFT, in Lovelace. price :: Natural , lockLockup :: BigInt , lockLockupEnd :: Slot - , fakeAuthor :: Maybe PaymentPubKeyHash - , feeVaultKeys :: Array PubKeyHash -- `List` is also an option + , feeVaultKeys :: Array PubKeyHash } derive instance Generic MintParams _ @@ -86,14 +73,13 @@ instance Show MintParams where show = genericShow instance FromData MintParams where - fromData (Constr n [ as, ds, pr, ll, lle, fa, fvk ]) | n == zero = + fromData (Constr n [ as, ds, pr, ll, lle, fvk ]) | n == zero = MintParams <$> ( { authorShare: _ , daoShare: _ , price: _ , lockLockup: _ , lockLockupEnd: _ - , fakeAuthor: _ , feeVaultKeys: _ } <$> fromData as @@ -101,7 +87,6 @@ instance FromData MintParams where <*> fromData pr <*> fromData ll <*> fromData lle - <*> fromData fa <*> fromData fvk ) fromData _ = Nothing @@ -114,7 +99,6 @@ instance ToData MintParams where , price , lockLockup , lockLockupEnd - , fakeAuthor , feeVaultKeys } ) = @@ -124,7 +108,6 @@ instance ToData MintParams where , toData price , toData lockLockup , toData lockLockupEnd - , toData fakeAuthor , toData feeVaultKeys ] @@ -156,8 +139,6 @@ instance ToData NftId where toData (NftId { collectionNftTn, price, owner }) = Constr zero [ toData collectionNftTn, toData price, toData owner ] --- Field names have been simplified due to row polymorphism. Please let me know --- if the field names must be exact. newtype NftCollection = NftCollection { collectionNftCs :: CurrencySymbol , lockLockup :: BigInt @@ -174,33 +155,20 @@ derive instance Newtype NftCollection _ derive newtype instance Eq NftCollection derive newtype instance Ord NftCollection --- Note the renaming of fields from their Plutus equivalents, e.g. --- "nftCollection'collectionNftCs" to "collectionNftCs". -instance Json.DecodeJson NftCollection where - decodeJson j = - Json.caseJsonObject +instance Aeson.DecodeAeson NftCollection where + decodeAeson j = + Aeson.caseAesonObject (Left $ Json.TypeMismatch "Expected Json Object") ( \o -> do - collectionNftCs <- do - nftCs <- Json.getField o "nftCollection'collectionNftCs" - note (Json.TypeMismatch "expected currency symbol") - $ mkCurrencySymbol - $ Cardano.Types.Value.getCurrencySymbol nftCs - - lockLockupEnd <- Json.getField o "nftCollection'lockLockupEnd" - lockingScript <- Json.getField o "nftCollection'lockingScript" - author <- Json.getField o "nftCollection'author" - authorShare <- Json.getField o "nftCollection'authorShare" - daoScript <- Json.getField o "nftCollection'daoScript" - daoShare <- Json.getField o "nftCollection'daoShare" - -- Is the more efficient way to do this? Leave this until the end incase - -- we fail earlier. - let aeson = Aeson.jsonToAeson j - lockLockup <- Aeson.caseAesonObject - (Left $ Json.TypeMismatch "Expected Aeson Object") - (flip Aeson.getField "nftCollection'lockLockup") - aeson + collectionNftCs <- Aeson.getField o "nftCollection'collectionNftCs" + lockLockupEnd <- Aeson.getField o "nftCollection'lockLockupEnd" + lockingScript <- Aeson.getField o "nftCollection'lockingScript" + author <- Aeson.getField o "nftCollection'author" + authorShare <- Aeson.getField o "nftCollection'authorShare" + daoScript <- Aeson.getField o "nftCollection'daoScript" + daoShare <- Aeson.getField o "nftCollection'daoShare" + lockLockup <- Aeson.getField o "nftCollection'lockLockup" pure $ NftCollection { collectionNftCs , lockLockup @@ -359,7 +327,7 @@ class Hashable (a :: Type) where -> Contract r (Maybe ByteArray) -- Plutus BuiltinByteString instance Hashable ByteArray where - hash = blake2bHash + hash = map Just <<< liftAff <<< blake2b256Hash instance Hashable Natural where hash = hash <<< toBin <<< toBigInt @@ -394,10 +362,10 @@ instance Hashable TokenName where hash = hash <<< getTokenName instance Hashable ValidatorHash where - hash = hash <<< scriptHashToBytes <<< unwrap + hash = hash <<< unwrap <<< scriptHashToBytes <<< unwrap instance Hashable PaymentPubKeyHash where - hash = hash <<< ed25519KeyHashToBytes <<< unwrap <<< unwrap + hash = hash <<< unwrap <<< ed25519KeyHashToBytes <<< unwrap <<< unwrap instance (Hashable a, Hashable b) => Hashable (a /\ b) where hash (a /\ b) = ((<>) <$> hash a <*> hash b) >>= maybe (pure Nothing) hash diff --git a/test/Fixtures.purs b/test/Fixtures.purs new file mode 100644 index 0000000..898eb35 --- /dev/null +++ b/test/Fixtures.purs @@ -0,0 +1,107 @@ +-- Feel free to update binary fixtures if they do not match the results you are +-- getting in tests. However, make sure you understand the reason why they +-- don't match. +-- To update the fixture, simply copy the value from failing test output. +-- +-- Or construct a value using CSL and get the hex string: +-- +-- ``` +-- const byteArrayToHex = arr => Buffer.from(arr).toString('hex'); +-- console.log(byteArrayToHex(something.to_bytes())) +-- ``` +module Test.Fixtures + ( seabugMetadataDeltaFixture1 + , seabugMetadataFixture1 + ) where + +import Prelude + +import Contract.Address (Ed25519KeyHash, PubKeyHash(..)) +import Contract.Numeric.Natural as Natural +import Contract.Prelude (fromJust) +import Contract.Prim.ByteArray (hexToByteArrayUnsafe) +import Contract.Scripts (ScriptHash, ValidatorHash(..)) +import Contract.Value + ( CurrencySymbol + , TokenName + , mkCurrencySymbol + , mkTokenName + , scriptHashAsCurrencySymbol + ) +import Data.BigInt as BigInt +import Partial.Unsafe (unsafePartial) +import Seabug.Metadata.Share (Share, mkShare) +import Seabug.Metadata.Types (SeabugMetadata(..), SeabugMetadataDelta(..)) +import Serialization.Hash (ed25519KeyHashFromBytes, scriptHashFromBytes) +import Types.RawBytes (hexToRawBytesUnsafe) + +currencySymbol1 :: CurrencySymbol +currencySymbol1 = unsafePartial $ fromJust $ mkCurrencySymbol $ + hexToByteArrayUnsafe + "1d6445ddeda578117f393848e685128f1e78ad0c4e48129c5964dc2e" + +tokenName1 :: TokenName +tokenName1 = unsafePartial $ fromJust $ mkTokenName $ + hexToByteArrayUnsafe "4974657374546f6b656e" + +ed25519KeyHashFixture1 :: Ed25519KeyHash +ed25519KeyHashFixture1 = + -- $ Bech32 "hstk_1rsf0q0q77t5nttxrtmpwd7tvv58a80a686t92pgy65ekz0s8ncu" + unsafePartial $ fromJust + $ ed25519KeyHashFromBytes + $ hexToRawBytesUnsafe + "1c12f03c1ef2e935acc35ec2e6f96c650fd3bfba3e96550504d53361" + +ed25519KeyHashFixture2 :: Ed25519KeyHash +ed25519KeyHashFixture2 = + -- "hbas_1xranhpfej50zdup5jy995dlj9juem9x36syld8wm465hz92acfp" + unsafePartial $ fromJust + $ ed25519KeyHashFromBytes + $ hexToRawBytesUnsafe + "30fb3b8539951e26f034910a5a37f22cb99d94d1d409f69ddbaea971" + +scriptHash1 :: ScriptHash +scriptHash1 = unsafePartial $ fromJust $ scriptHashFromBytes $ + hexToRawBytesUnsafe + "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" + +scriptHash2 :: ScriptHash +scriptHash2 = unsafePartial $ fromJust $ scriptHashFromBytes $ + hexToRawBytesUnsafe + "00000000005bb21ce6d8c7502aca70b9316d10e958611f3c6b758f60" + +policyId :: CurrencySymbol +policyId = scriptHashAsCurrencySymbol scriptHash1 + +validatorHashFixture1 :: ValidatorHash +validatorHashFixture1 = ValidatorHash scriptHash1 + +validatorHashFixture2 :: ValidatorHash +validatorHashFixture2 = ValidatorHash scriptHash2 + +shareFixture :: Share +shareFixture = unsafePartial $ fromJust $ mkShare 100 + +seabugMetadataFixture1 :: SeabugMetadata +seabugMetadataFixture1 = SeabugMetadata + { policyId: policyId + , mintPolicy: "00000000" + , collectionNftCS: currencySymbol1 + , collectionNftTN: tokenName1 + , lockingScript: validatorHashFixture1 + , authorPkh: PubKeyHash ed25519KeyHashFixture1 + , authorShare: shareFixture + , marketplaceScript: validatorHashFixture2 + , marketplaceShare: shareFixture + , ownerPkh: PubKeyHash ed25519KeyHashFixture2 + , ownerPrice: unsafePartial $ fromJust $ Natural.fromBigInt $ BigInt.fromInt + 10 + } + +seabugMetadataDeltaFixture1 :: SeabugMetadataDelta +seabugMetadataDeltaFixture1 = SeabugMetadataDelta + { policyId: policyId + , ownerPkh: PubKeyHash ed25519KeyHashFixture2 + , ownerPrice: unsafePartial $ fromJust $ Natural.fromBigInt $ BigInt.fromInt + 10 + } diff --git a/test/Main.purs b/test/Main.purs index 7c1d23f..f859310 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,5 +2,13 @@ module Test.Main (main) where import Contract.Prelude +import Contract.Monad (launchAff_) +import Test.Metadata as Metadata +import Test.Util (interpret) +import TestM (TestPlanM) + main :: Effect Unit -main = log "Hello Purescript!" +main = launchAff_ $ interpret unitTestPlan + +unitTestPlan :: TestPlanM Unit +unitTestPlan = Metadata.suite diff --git a/test/Metadata.purs b/test/Metadata.purs new file mode 100644 index 0000000..ae54101 --- /dev/null +++ b/test/Metadata.purs @@ -0,0 +1,31 @@ +module Test.Metadata + ( suite + ) where + +import Prelude + +import Data.Maybe (Maybe(Just)) +import FromData (fromData) +import Metadata.MetadataType (fromGeneralTxMetadata, toGeneralTxMetadata) +import Mote (group, test) +import Test.Fixtures (seabugMetadataFixture1, seabugMetadataDeltaFixture1) +import Test.Spec.Assertions (shouldEqual) +import TestM (TestPlanM) +import ToData (toData) + +suite :: TestPlanM Unit +suite = do + group "Seabug Metadata" $ do + test "MetadataType instance" do + fromGeneralTxMetadata (toGeneralTxMetadata seabugMetadataFixture1) + `shouldEqual` Just seabugMetadataFixture1 + test "FromData / ToData instances" do + fromData (toData seabugMetadataFixture1) `shouldEqual` Just + seabugMetadataFixture1 + group "Seabug Metadata delta" $ do + test "MetadataType instance" do + fromGeneralTxMetadata (toGeneralTxMetadata seabugMetadataDeltaFixture1) + `shouldEqual` Just seabugMetadataDeltaFixture1 + test "FromData / ToData instances" do + fromData (toData seabugMetadataDeltaFixture1) `shouldEqual` Just + seabugMetadataDeltaFixture1 diff --git a/test/TestM.purs b/test/TestM.purs new file mode 100644 index 0000000..c481b35 --- /dev/null +++ b/test/TestM.purs @@ -0,0 +1,10 @@ +module TestM + ( TestPlanM + ) where + +import Prelude +import Data.Const (Const) +import Effect.Aff (Aff) +import Mote (MoteT) + +type TestPlanM a = MoteT (Const Void) (Aff Unit) Aff a diff --git a/test/Util.purs b/test/Util.purs new file mode 100644 index 0000000..3493748 --- /dev/null +++ b/test/Util.purs @@ -0,0 +1,31 @@ +module Test.Util + ( interpret + ) where + +import Prelude + +import Data.Const (Const) +import Data.Foldable (sequence_) +import Data.Maybe (Maybe(Just)) +import Data.Newtype (wrap) +import Effect.Aff (Aff) +import Effect.Aff.Class (liftAff) +import Mote (Plan, foldPlan, planT) +import Test.Spec (Spec, describe, it, pending) +import Test.Spec.Reporter (consoleReporter) +import Test.Spec.Runner (defaultConfig, runSpec') +import TestM (TestPlanM) + +interpret :: TestPlanM Unit -> Aff Unit +interpret spif = do + plan <- planT spif + runSpec' defaultConfig { timeout = Just (wrap 10000.0) } [ consoleReporter ] $ + go plan + where + go :: Plan (Const Void) (Aff Unit) -> Spec Unit + go = + foldPlan + (\x -> it x.label $ liftAff x.value) + pending + (\x -> describe x.label $ go x.value) + sequence_ diff --git a/webpack.config.js b/webpack.config.js index f168b3e..1055157 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -51,7 +51,7 @@ module.exports = { resolve: { modules: [process.env.NODE_PATH], - extensions: [".js"], + extensions: [".js", ".ts"], fallback: { buffer: require.resolve("buffer/"), http: false,