diff --git a/bower.json b/bower.json index 2129866..241dac7 100644 --- a/bower.json +++ b/bower.json @@ -18,23 +18,22 @@ "url": "git://github.com/f-o-a-m/purescript-web3-generator.git" }, "dependencies": { - "purescript-argonaut": "^3.1.0", - "purescript-argonaut-core": "^3.1.0", - "purescript-argonaut-generic-codecs": "^6.0.4", - "purescript-prelude": "^3.1.0", - "purescript-errors": "^3.0.0", - "purescript-yargs": "^3.1.0", - "purescript-ansi": "^4.0.0", - "purescript-node-fs-aff": "^5.0.0", - "purescript-console": "^3.0.0", - "purescript-string-parsers": "^3.0.1", - "purescript-web3": "^0.25.0", - "purescript-mkdirp": "^0.3.0", - "purescript-fixed-points": "^4.0.0", - "purescript-record-extra": "^0.3.0" + "purescript-argonaut": "^4.0.0", + "purescript-ordered-collections": "^1.0.0", + "purescript-prelude": "^4.0.0", + "purescript-errors": "^4.0.0", + "purescript-yargs": "^4.0.0", + "purescript-ansi": "^5.0.0", + "purescript-node-fs-aff": "^6.0.0", + "purescript-console": "^4.0.0", + "purescript-string-parsers": "^4.0.0", + "purescript-web3": "^1.0.0", + "purescript-mkdirp": "joshuahhh/purescript-mkdirp#48ecb4039d5fe3be82d0e82c3a9f2338d1af82d2", + "purescript-fixed-points": "^5.0.0", + "purescript-record-extra": "^1.0.0" }, "devDependencies": { - "purescript-spec": "^2.0.0", - "purescript-psci-support": "^3.0.0" + "purescript-spec": "^3.0.0", + "purescript-psci-support": "^4.0.0" } } diff --git a/package.json b/package.json index 2598eb8..f218c16 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "rlp": "^2.0.0", "secp256k1": "^3.0.1", "psc-package": "^0.2.4-rc1", - "pulp": "^12.0.0", - "purescript": "^0.11.7", + "purescript": "^0.12.0", + "pulp": "^12.2.0", "purescript-psa": "^0.6.0", "yargs": "^8.0.2" } diff --git a/src/Data/AbiParser.purs b/src/Data/AbiParser.purs index 1c03d4b..89aa92f 100644 --- a/src/Data/AbiParser.purs +++ b/src/Data/AbiParser.purs @@ -13,13 +13,14 @@ import Data.Bifunctor (lmap) import Data.Either (Either(..)) import Data.Foldable (all, foldMap) import Data.FunctorWithIndex (mapWithIndex) -import Data.Generic (class Generic, gEq, gShow) +import Data.Generic.Rep (class Generic) +import Data.Generic.Rep.Eq (genericEq) +import Data.Generic.Rep.Show (genericShow) import Data.Int (fromString) import Data.List.Types (List(..), NonEmptyList(..)) import Data.Maybe (Maybe(..)) import Data.NonEmpty ((:|)) -import Data.Record.Extra (showRecord) -import Data.String (fromCharArray) +import Data.String.CodeUnits (fromCharArray) import Data.TacitString as TacitString import Text.Parsing.StringParser (Parser, fail, runParser, try) import Text.Parsing.StringParser.Combinators (choice, lookAhead, manyTill, many1, optionMaybe) @@ -45,13 +46,13 @@ data SolidityType = | SolidityVector (NonEmptyList Int) SolidityType | SolidityArray SolidityType -derive instance genericSolidityType :: Generic SolidityType +derive instance genericSolidityType :: Generic SolidityType _ instance showSolidityType :: Show SolidityType where - show = gShow + show x = genericShow x instance eqSolidityType :: Eq SolidityType where - eq = gEq + eq x = genericEq x instance formatSolidityType :: Format SolidityType where format s = case s of @@ -151,10 +152,10 @@ newtype FunctionInput = , type :: SolidityType } -derive instance genericFunctionInput :: Generic FunctionInput +derive instance genericFunctionInput :: Generic FunctionInput _ instance showFunctionInput :: Show FunctionInput where - show = gShow + show = genericShow instance formatInput :: Format FunctionInput where format (FunctionInput fi) = format fi.type @@ -177,10 +178,10 @@ data SolidityFunction = , isUnCurried :: Boolean } -derive instance genericSolidityFunction :: Generic SolidityFunction +derive instance genericSolidityFunction :: Generic SolidityFunction _ instance showSolidityFunction :: Show SolidityFunction where - show = gShow + show = genericShow instance decodeJsonSolidityFunction :: DecodeJson SolidityFunction where decodeJson json = do @@ -209,10 +210,10 @@ data SolidityConstructor = , isUnCurried :: Boolean } -derive instance genericSolidityConstructor :: Generic SolidityConstructor +derive instance genericSolidityConstructor :: Generic SolidityConstructor _ instance showSolidityConstructor :: Show SolidityConstructor where - show = gShow + show = genericShow instance decodeJsonSolidityConstructor :: DecodeJson SolidityConstructor where decodeJson json = do @@ -233,10 +234,10 @@ data IndexedSolidityValue = , indexed :: Boolean } -derive instance genericSolidityIndexedValue :: Generic IndexedSolidityValue +derive instance genericSolidityIndexedValue :: Generic IndexedSolidityValue _ instance showSolidityIndexedValue :: Show IndexedSolidityValue where - show = gShow + show = genericShow instance formatIndexedSolidityValue :: Format IndexedSolidityValue where format (IndexedSolidityValue v) = format v.type @@ -259,10 +260,10 @@ data SolidityEvent = , inputs :: Array IndexedSolidityValue } -derive instance genericSolidityEvent :: Generic SolidityEvent +derive instance genericSolidityEvent :: Generic SolidityEvent _ instance showSolidityEvent :: Show SolidityEvent where - show = gShow + show = genericShow instance decodeJsonSolidityEvent :: DecodeJson SolidityEvent where decodeJson json = do @@ -277,10 +278,10 @@ instance decodeJsonSolidityEvent :: DecodeJson SolidityEvent where data SolidityFallback = SolidityFallback -derive instance genericSolidityFallback :: Generic SolidityFallback +derive instance genericSolidityFallback :: Generic SolidityFallback _ instance showSolidityFallback :: Show SolidityFallback where - show = gShow + show = genericShow instance decodeJsonSolidityFallback :: DecodeJson SolidityFallback where decodeJson json = do @@ -296,10 +297,10 @@ data AbiType = | AbiEvent SolidityEvent | AbiFallback SolidityFallback -derive instance genericAbiType :: Generic AbiType +derive instance genericAbiType :: Generic AbiType _ instance showAbiType :: Show AbiType where - show = gShow + show = genericShow instance decodeJsonAbiType :: DecodeJson AbiType where decodeJson json = do @@ -336,4 +337,4 @@ instance showAbi :: showFAbiType = map (show >>> TacitString.hush) instance showAbiDecodeError :: Show AbiDecodeError where - show (AbiDecodeError r) = "(AbiDecodeError " <> showRecord r <> ")" + show (AbiDecodeError r) = "(AbiDecodeError " <> show r <> ")" diff --git a/src/Data/CodeGen.purs b/src/Data/CodeGen.purs index 1fc8bd7..9d62fe0 100644 --- a/src/Data/CodeGen.purs +++ b/src/Data/CodeGen.purs @@ -5,11 +5,11 @@ import Prelude import Ansi.Codes (Color(..)) import Ansi.Output (withGraphics, foreground) import Control.Error.Util (note) -import Control.Monad.Aff (Aff, try) -import Control.Monad.Aff.Class (class MonadAff, liftAff) -import Control.Monad.Aff.Console (CONSOLE, log) -import Control.Monad.Eff.Class (liftEff) -import Control.Monad.Eff.Exception (error) +import Effect.Aff (Aff, try) +import Effect.Aff.Class (class MonadAff, liftAff) +import Effect.Console (log) +import Effect.Class (liftEffect) +import Effect.Exception (error) import Control.Monad.Error.Class (throwError) import Control.Monad.State (class MonadState, StateT, evalStateT, get, put) import Control.Monad.Writer (class MonadTell, runWriter, runWriterT, tell) @@ -23,18 +23,17 @@ import Data.Foldable (foldl, for_) import Data.Generator (Imports, ModuleImport(..), ModuleImports, ModuleName, Imported, genCode, mkComment, newLine1) import Data.Identity (Identity(..)) import Data.Lens ((^?)) +import Data.Array as Array import Data.Lens.Index (ix) -import Data.Map (Map, fromFoldableWith, insert, lookup, member, toAscUnfoldable) +import Data.Map (Map, fromFoldableWith, insert, lookup, member, toUnfoldable) import Data.Maybe (Maybe(..), isNothing) -import Data.Monoid (mempty) import Data.Newtype (un) -import Data.Record.Extra (showRecord) -import Data.StrMap as StrMap +import Data.Map as Map import Data.String (Pattern(..), Replacement(..), joinWith, replaceAll, stripPrefix) import Data.Traversable (for) import Data.Tuple (Tuple(..)) import Node.Encoding (Encoding(UTF8)) -import Node.FS.Aff (FS, readTextFile, writeTextFile, readdir, stat) +import Node.FS.Aff (readTextFile, writeTextFile, readdir, stat) import Node.FS.Stats as Stats import Node.FS.Sync.Mkdirp (mkdirp) import Node.Path (FilePath, basenameWithoutExt, extname) @@ -70,7 +69,7 @@ runImports = mergeImports >>> map runImport >>> newLine1 >>> ("import Prelude \n runAcc <<< foldl f { types: mempty, imports: mempty } where runAcc :: ModuleImportsAcc -> Array String - runAcc acc = sort $ nub $ append acc.imports $ (toAscUnfoldable acc.types) >>= resolveCtrImports + runAcc acc = sort $ nub $ append acc.imports $ (toUnfoldable acc.types) >>= resolveCtrImports resolveCtrImports :: Tuple String IsCtrInImports -> Array String resolveCtrImports (Tuple typeName isCtrInImports) = case isCtrInImports of CtrIsInImports -> [] @@ -98,29 +97,29 @@ runImports = mergeImports >>> map runImport >>> newLine1 >>> ("import Prelude \n IOp a -> acc {imports = acc.imports <> [ "(" <> a <> ")" ]} - -- NOTE this also sorts modules as we use toAscUnfoldable + -- NOTE this also sorts modules as we use toUnfoldable which returns ascending order result mergeImports :: Imports -> Imports - mergeImports = fromFoldableWith append >>> toAscUnfoldable + mergeImports = fromFoldableWith append >>> toUnfoldable -generatePS :: forall e . GeneratorOptions -> Aff (fs :: FS, console :: CONSOLE | e) ABIErrors +generatePS :: GeneratorOptions -> Aff ABIErrors generatePS os = do let opts = os { pursDir = os.pursDir <> "/" <> replaceAll (Pattern ".") (Replacement "/") os.modulePrefix } fs <- getAllJsonFiles opts.jsonDir - liftEff $ mkdirp opts.pursDir + liftEffect $ mkdirp opts.pursDir case fs of [] -> throwError <<< error $ "No abi json files found in directory: " <> opts.jsonDir fs' -> do errs <- join <$> for fs' \f -> do let f' = genPSFileName opts f Tuple _ errs <- runWriterT $ writeCodeFromAbi opts f f' - log if null errs + liftEffect $ log if null errs then successCheck <> " contract module for " <> f <> " successfully written to " <> f' else warningCheck <> " (" <> show (length errs) <> ") contract module for " <> f <> " written to " <> f' pure errs unless (null errs) do - log $ errorCheck <> " got " <> show (length errs) <> " error(s) during generation" + liftEffect $ log $ errorCheck <> " got " <> show (length errs) <> " error(s) during generation" for_ errs \(ABIError err) -> - log $ errorCheck <> " while parsing abi type of object at index: " <> show err.idx <> " from: " <> err.abiPath <> " got error:\n " <> err.error + liftEffect $ log $ errorCheck <> " while parsing abi type of object at index: " <> show err.idx <> " from: " <> err.abiPath <> " got error:\n " <> err.error pure errs where successCheck = withGraphics (foreground Green) $ "✔" @@ -134,7 +133,7 @@ type ABIErrors = Array ABIError newtype ABIError = ABIError { abiPath :: FilePath, idx :: Int, error :: String } instance showABIError :: Show ABIError where - show (ABIError r) = "(ABIError " <> showRecord r <> ")" + show (ABIError r) = "(ABIError " <> show r <> ")" generateCodeFromAbi :: GeneratorOptions -> Abi Identity -> FilePath -> String generateCodeFromAbi opts (Abi abi) destFile = @@ -143,8 +142,8 @@ generateCodeFromAbi opts (Abi abi) destFile = # runImported opts destFile -- | read in json abi and write the generated code to a destination file -writeCodeFromAbi :: forall e m - . MonadAff (fs :: FS, console :: CONSOLE | e) m +writeCodeFromAbi :: forall m + . MonadAff m => MonadTell ABIErrors m => GeneratorOptions -> FilePath @@ -166,8 +165,8 @@ maybeAnnotateArity :: Array AbiType -> Array AbiType maybeAnnotateArity abi = let Tuple nonFuncAbi funcAbi = foldMap groupingFunc abi - nameToFunctions = StrMap.fromFoldableWith (<>) $ funcAbi <#> \fun@(SolidityFunction f) -> Tuple f.name [fun] - functionsWithArity = StrMap.values nameToFunctions >>= \fs -> if length fs > 1 then map go fs else fs + nameToFunctions = Map.fromFoldableWith (<>) $ funcAbi <#> \fun@(SolidityFunction f) -> Tuple f.name [fun] + functionsWithArity = Array.fromFoldable (Map.values nameToFunctions) >>= \fs -> if length fs > 1 then map go fs else fs in nonFuncAbi <> map AbiFunction functionsWithArity where @@ -199,8 +198,8 @@ genPSModuleStatement opts fp = comment <> "\n" -- get all the "valid" directories rooted in a filepath getAllDirectories - :: forall eff m. - MonadAff (fs :: FS | eff) m + :: forall m. + MonadAff m => MonadState FilePath m => m (Array FilePath) getAllDirectories = do @@ -211,8 +210,8 @@ getAllDirectories = do -- determine whether or not a directory is valid (basically it's not dotted) validateRootedDir - :: forall eff m. - MonadAff (fs :: FS | eff) m + :: forall m. + MonadAff m => FilePath -- prefix -> FilePath -- dirname -> m (Maybe FilePath) @@ -229,8 +228,8 @@ validateRootedDir prefix dir = liftAff $ do -- | get all files in a directory with a ".json" extension getJsonFilesInDirectory - :: forall eff m. - MonadAff (fs :: FS | eff) m + :: forall m. + MonadAff m => MonadState FilePath m => m (Array FilePath) getJsonFilesInDirectory = do @@ -241,8 +240,8 @@ getJsonFilesInDirectory = do -- | determine whether the file is a .json artifact validateFile - :: forall eff m. - MonadAff (fs :: FS | eff) m + :: forall m. + MonadAff m => FilePath -- dir -> FilePath -- filepath -> m (Maybe FilePath) @@ -258,8 +257,8 @@ validateFile dir f = liftAff $ do else Nothing getAllJsonFiles - :: forall eff m. - MonadAff (fs :: FS | eff) m + :: forall m. + MonadAff m => FilePath -> m (Array FilePath) getAllJsonFiles root = evalStateT getAllJsonFiles' root diff --git a/src/Data/Generator.purs b/src/Data/Generator.purs index 64070d8..b79bba9 100644 --- a/src/Data/Generator.purs +++ b/src/Data/Generator.purs @@ -12,7 +12,8 @@ import Data.List.Types (NonEmptyList(..)) as List import Data.Maybe (Maybe(..)) import Data.Newtype (un) import Data.NonEmpty ((:|)) -import Data.String (drop, fromCharArray, joinWith, singleton, take, toCharArray, toLower, toUpper) +import Data.String.CodeUnits (fromCharArray, toCharArray, singleton) +import Data.String (drop, joinWith, take, toLower, toUpper) import Data.Traversable (for) import Data.Tuple (Tuple(..), uncurry) import Network.Ethereum.Core.HexString (fromByteString) @@ -221,7 +222,7 @@ funToHelperFunction isWhereClause fun@(SolidityFunction f) opts = do let var = if isWhereClause then "y" else "x" constraints = [] - quantifiedVars = ["e"] + quantifiedVars = [] stockVars = if f.isConstructor then [var <> "0", if isWhereClause then "bc'" else "bc"] @@ -275,7 +276,7 @@ funToHelperFunction' fun@(SolidityFunction f) opts = do pure ["TransactionOptions NoPay"] let constraints = [] - quantifiedVars = ["e"] + quantifiedVars = [] stockVars = if f.isConstructor then ["x0", "bc"] else if f.constant @@ -360,7 +361,7 @@ toReturnType constant outputs' = do if not constant then do import' "Network.Ethereum.Web3.Types" [IType "HexString"] - pure "Web3 e HexString" + pure "Web3 HexString" else do import' "Network.Ethereum.Web3.Types" [IType "CallError"] import' "Data.Either" [IType "Either"] @@ -372,7 +373,7 @@ toReturnType constant outputs' = do let tupleType = "Tuple" <> show (length outputs) import' "Network.Ethereum.Web3.Solidity" [IType tupleType] pure $ paren $ tupleType <> " " <> joinWith " " outputs - pure $ "Web3 e " <> paren ("Either CallError " <> out) + pure $ "Web3 " <> paren ("Either CallError " <> out) instance codeHelperFunction :: Code HelperFunction where genCode (CurriedHelperFunction h) opts = diff --git a/src/Data/GeneratorMain.purs b/src/Data/GeneratorMain.purs index 9f13eee..11f8f82 100644 --- a/src/Data/GeneratorMain.purs +++ b/src/Data/GeneratorMain.purs @@ -2,18 +2,15 @@ module Data.GeneratorMain where import Prelude -import Control.Monad.Aff (launchAff_) -import Control.Monad.Eff (Eff) -import Control.Monad.Eff.Console (CONSOLE) -import Control.Monad.Eff.Exception (EXCEPTION) +import Effect.Aff (launchAff_) +import Effect ( Effect) import Data.CodeGen (generatePS) import Data.Either (Either(..)) import Data.Maybe (Maybe(..)) -import Node.FS.Aff (FS) import Node.Yargs.Applicative (yarg, flag, runY) import Node.Yargs.Setup (usage, defaultVersion, defaultHelp, example) -generatorMain :: forall e. Eff (fs :: FS, console :: CONSOLE, exception :: EXCEPTION | e) Unit +generatorMain :: Effect Unit generatorMain = do conf <- runY setup mkConf launchAff_ $ generatePS conf diff --git a/test/Main.purs b/test/Main.purs index be36278..71f4ab4 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,9 +2,8 @@ module Test.Main where import Prelude -import Control.Monad.Eff (Eff) -import Control.Monad.Eff.Console (CONSOLE) -import Control.Monad.Eff.Exception (error) +import Effect ( Effect) +import Effect.Exception (error) import Control.Monad.Error.Class (throwError) import Data.AbiParser (AbiWithErrors, SolidityType(..), parseSolidityType) import Data.Argonaut.Parser (jsonParser) @@ -12,17 +11,17 @@ import Data.Array (null) import Data.CodeGen (generatePS, parseAbi) import Data.Either (Either(..), either, isRight) import Node.Encoding (Encoding(UTF8)) -import Node.FS.Aff (FS, readTextFile) +import Node.FS.Aff (readTextFile) import Test.Spec (Spec, describe, it) import Test.Spec.Assertions (fail, shouldEqual) import Test.Spec.Reporter.Console (consoleReporter) -import Test.Spec.Runner (RunnerEffects, run) +import Test.Spec.Runner (run) -main :: Eff (RunnerEffects (fs :: FS, console :: CONSOLE )) Unit +main :: Effect Unit main = run [consoleReporter] $ do simpleStorageParserSpec -simpleStorageParserSpec :: forall r . Spec (fs :: FS, console :: CONSOLE | r) Unit +simpleStorageParserSpec :: Spec Unit simpleStorageParserSpec = describe "simple storage parser spec" do it "can parse solidity types" do