diff --git a/README.md b/README.md index 3a7453f..cb9f311 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ The configuration values used for these environment variables in the example abo configuration values. A MAINNET Maestro API key is needed, a payment signing key must be generated and a collateral UTxO must be provided after sending funds to the address given by the payment signing key and the (optional) stake address. -In order to determine this address, you could use `cardano-cli address build`, but you can also just run the market maker - the address will be printed to the console in the first line of output: +In order to determine this address, you could use `cardano-cli address build`, but you can also just run the market maker - the address will be printed as the first log of "Info" severity: ``` Genius Yield Market Maker: @@ -133,7 +133,6 @@ https://github.com/geniusyield/market-maker/blob/eeb410f3936e6610797e6402c4dd2fd > Sample mnemonic provided above is a valid one and can be used to toy around with configuration to understand implications better. * `ur_coll` (optional) is the UTxO to be reserved as collateral. Though specifying `ur_coll` is optional but it is advised to set it as then this UTxO would be reserved (i.e., would not be spent) and thus be always available to serve as collateral. It is preferred for `ur_coll` to be pure 5 ADA only UTxO (i.e., no other tokens besides ADA). -* Fields `mbc_fp_nft_policy`, `mbc_fp_order_validator`, `mbc_po_config_addr` and `mbc_po_refs` relate to DEX smart contracts and can be left as it is. See sample files corresponding to the network to know for these values. * `mbc_delay` - Bot in single iteration tries to determine which orders need to be placed and which are needed to be cancelled. Once determined, it tries building the transactions and proceeds with submitting them, completing this single iteration. `mbc_delay` determines time in microseconds that bot must wait before proceeding with next iteration. * `mbc_price_config` gives the configuration on how to get market price using https://docs.gomaestro.org/DefiMarketAPI/mkt-dex-ohlc Maestro endpoint, for a token. * `pc_api_key` is the Maestro API key. diff --git a/cabal.project b/cabal.project index 65a85e7..03dbb5e 100644 --- a/cabal.project +++ b/cabal.project @@ -34,14 +34,17 @@ package strict-containers source-repository-package type: git location: https://github.com/geniusyield/dex-contracts-api - tag: 8087ed4da70512cf2327f353d5a3a590511be0b6 - --sha256: sha256-Fw9OdzGrvteW1asVctmqkZa8k4G6osgvFDleNozYjW4= + tag: d1212bba3112e3057543a159303f0bdec294feca + --sha256: sha256-fgFz50aaEr1uZQTBO1C1Y+G08SQmoZjs0ajqh5pWFzg= + subdir: + geniusyield-dex-api + geniusyield-onchain/geniusyield-common source-repository-package type: git location: https://github.com/maestro-org/haskell-sdk - tag: 392af75cfe55b1847c0a7b8c848a18e039476124 - --sha256: sha256-9ee8hCEIxbRJaXL3bMYkYlQ2gQOPJGRnw4aXFns3dEw= + tag: 609515b3f8861efaa17adf4e599aa1b845775a6d + --sha256: sha256-8se+xlIB1BDEuKGwjaldmW5G4LpCujD1ABgBaY0cY6Y= -- Unfortunately, cardano-node 8.1.2 is constrained with plutus-ledger-api 1.5.0.0 and we would like at least 1.6.0.0. -- This is done in accordance with changes in https://github.com/input-output-hk/cardano-ledger/pull/3430/files. @@ -71,8 +74,8 @@ source-repository-package source-repository-package type: git location: https://github.com/geniusyield/atlas - tag: 1d495bdd45be6afcc41b0e49c8ace99c0eff2efd - --sha256: sha256-C9Pe+u+qVyVMYezMnfyGP0vUe96D0yQLEU4JG5fOTwY= + tag: 105ff78b32935ae5c18c53ccf4fb8462b8c1ca03 + --sha256: sha256-Ee/UIoJ8OYBxgdnSv61hN8DH7CrIOPn4DjqOBxFL3Js= source-repository-package type: git diff --git a/docker-compose.yml b/docker-compose.yml index cab5c7b..c116691 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,14 +30,6 @@ services: "ur_s_key_path": "/root/payment-signing-key.skey", "ur_coll": "${COLLATERAL_UTXO}" }, - "mbc_fp_nft_policy": "compiled-scripts/minting-policy", - "mbc_fp_order_validator": "compiled-scripts/partial-order", - "mbc_po_config_addr": "addr1w9zr09hgj7z6vz3d7wnxw0u4x30arsp5k8avlcm84utptls8uqd0z", - "mbc_po_refs": { - "por_ref_nft": "fae686ea8f21d567841d703dea4d4221c2af071a6f2b433ff07c0af2.4aff78908ef2dce98bfe435fb3fd2529747b1c4564dff5adebedf4e46d0fc63d", - "por_val_ref": "062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea#2", - "por_mint_ref": "062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea#1" - }, "mbc_delay": 120000000, "mbc_price_config": { "pc_api_key": "${MAESTRO_API_KEY}", diff --git a/geniusyield-market-maker/CHANGELOG.md b/geniusyield-market-maker/CHANGELOG.md index ee008e9..af33ad8 100644 --- a/geniusyield-market-maker/CHANGELOG.md +++ b/geniusyield-market-maker/CHANGELOG.md @@ -1,5 +1,10 @@ # Revision history for geniusyield-market-maker +## 0.4.0 -- 2024-05-02 + +* Supports latest version of [`dex-contracts-api`](https://github.com/geniusyield/dex-contracts-api) which adds support of v1.1 family of scripts. +* Updates to latest version of Maestro's Haskell SDK. + ## 0.3.0 -- 2024-04-11 * Adds ability to specify different spread for each (sell & buy) side. The change is backwards compatible with respect to configuration. diff --git a/geniusyield-market-maker/Main.hs b/geniusyield-market-maker/Main.hs index d4e224a..b0f42ef 100644 --- a/geniusyield-market-maker/Main.hs +++ b/geniusyield-market-maker/Main.hs @@ -1,14 +1,19 @@ module Main (main) where import Control.Exception (throwIO) +import GeniusYield.Api.Dex.Constants (dexInfoDefaultMainnet, + dexInfoDefaultPreprod) import GeniusYield.GYConfig +import GeniusYield.MarketMaker.Constants (logNS) import GeniusYield.MarketMaker.MakerBot import GeniusYield.MarketMaker.MakerBotConfig import GeniusYield.MarketMaker.Prices import GeniusYield.MarketMaker.Strategies import GeniusYield.MarketMaker.Utils (addrUser) import GeniusYield.OrderBot.DataSource.Providers (connectDB) -import GeniusYield.Types (addressToText) +import GeniusYield.Types (GYNetworkId (..), + addressToText) +import GeniusYield.Types.Providers (gyLogInfo) import System.Environment ----------------------------------------------------------------------- @@ -37,13 +42,17 @@ main = do coreCfg <- coreConfigIO frameworkCfgPath mbc <- readMBotConfig mBotConfigFile mb <- buildMakerBot mbc - di <- getDexInfo mbc - - putStrLn $ "Genius Yield Market Maker: " - ++ show (addressToText $ addrUser (cfgNetworkId coreCfg) $ mbUser mb) + di <- + case cfgNetworkId coreCfg of + GYTestnetPreprod -> pure dexInfoDefaultPreprod + GYMainnet -> pure dexInfoDefaultMainnet + _ -> throwIO $ userError "Only Preprod and Mainnet are supported." let netId = cfgNetworkId coreCfg - withCfgProviders coreCfg "" $ \providers -> + withCfgProviders coreCfg "" $ \providers -> do + gyLogInfo providers logNS $ + "Genius Yield Market Maker: " + ++ show (addressToText $ addrUser (cfgNetworkId coreCfg) $ mbUser mb) case action of "Run" -> do c <- connectDB netId providers diff --git a/geniusyield-market-maker/geniusyield-market-maker.cabal b/geniusyield-market-maker/geniusyield-market-maker.cabal index 2bdcbee..ef88359 100644 --- a/geniusyield-market-maker/geniusyield-market-maker.cabal +++ b/geniusyield-market-maker/geniusyield-market-maker.cabal @@ -1,6 +1,6 @@ cabal-version: 3.4 name: geniusyield-market-maker -version: 0.3.0 +version: 0.4.0 build-type: Simple extra-doc-files: CHANGELOG.md synopsis: @@ -126,7 +126,6 @@ executable geniusyield-market-maker-exe GeniusYield.MarketMaker.Equity GeniusYield.MarketMaker.MakerBot GeniusYield.MarketMaker.MakerBotConfig - GeniusYield.MarketMaker.Orphans GeniusYield.MarketMaker.Prices GeniusYield.MarketMaker.Spread GeniusYield.MarketMaker.Strategies diff --git a/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBot.hs b/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBot.hs index e991681..e33de22 100644 --- a/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBot.hs +++ b/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBot.hs @@ -7,8 +7,9 @@ import Control.Monad (forM_, forever, when) import Control.Monad.Reader (runReaderT) import Data.List.Split (chunksOf) import qualified Data.Map.Strict as M +import GeniusYield.Api.Dex.Constants (DEXInfo (..)) import GeniusYield.Api.Dex.PartialOrder (PartialOrderInfo (poiOwnerKey), - cancelMultiplePartialOrders, + cancelMultiplePartialOrders', partialOrders, placePartialOrder) import GeniusYield.Imports (printf, (&)) @@ -16,8 +17,7 @@ import GeniusYield.MarketMaker.Constants (awaitTxParams, logNS) import GeniusYield.MarketMaker.Prices import GeniusYield.MarketMaker.Strategies import GeniusYield.MarketMaker.User -import GeniusYield.MarketMaker.Utils (DEXInfo (dexPORefs), - addrUser, pkhUser) +import GeniusYield.MarketMaker.Utils (addrUser, pkhUser) import GeniusYield.Providers.Common (SubmitTxException) import GeniusYield.Transaction (BuildTxException) import GeniusYield.TxBuilder @@ -49,7 +49,7 @@ cancelAllOrders MakerBot {mbUser} netId providers di = do userAddr = addrUser netId mbUser txBody ← runGYTxMonadNode netId providers [userAddr] userAddr (uColl mbUser) - $ runReaderT (cancelMultiplePartialOrders (dexPORefs di) batch) di + $ runReaderT (cancelMultiplePartialOrders' (dexPORefs di) batch) di let signedTx = signGYTxBody' txBody [uSKeyToSomeSigningKey mbUser] tid ← gySubmitTx providers signedTx @@ -70,7 +70,7 @@ buildAndSubmitActions user@User {uColl, uStakeCred} providers netId ua di = flip forM_ (chunksOf 6 cancelActions) $ \cancelChunk -> do logInfo $ "Building for cancel action(s): " <> show cancelChunk - txBody ← runGYTxMonadNode netId providers [userAddr] userAddr uColl $ flip runReaderT di $ cancelMultiplePartialOrders (dexPORefs di) (map coaPoi cancelChunk) + txBody ← runGYTxMonadNode netId providers [userAddr] userAddr uColl $ flip runReaderT di $ cancelMultiplePartialOrders' (dexPORefs di) (map coaPoi cancelChunk) buildCommon txBody forM_ placeActions $ \pa@PlaceOrderAction {..} -> do diff --git a/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBotConfig.hs b/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBotConfig.hs index 9d7940f..fd052e5 100644 --- a/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBotConfig.hs +++ b/geniusyield-market-maker/src/GeniusYield/MarketMaker/MakerBotConfig.hs @@ -7,34 +7,20 @@ import Data.Bifunctor (first) import Data.String (IsString (..)) import qualified Data.Yaml as Yaml import Deriving.Aeson -import GeniusYield.Api.Dex.PartialOrder (PORefs (..)) import GeniusYield.MarketMaker.MakerBot (MakerBot (..)) -import GeniusYield.MarketMaker.Orphans () import GeniusYield.MarketMaker.Prices import GeniusYield.MarketMaker.Strategies import GeniusYield.MarketMaker.User -import GeniusYield.MarketMaker.Utils -import GeniusYield.Types -import PlutusLedgerApi.V1 (Address) -import PlutusLedgerApi.V1.Scripts (ScriptHash) -import PlutusLedgerApi.V1.Value (AssetClass) -import Ply (ScriptRole (..), - TypedScript, - readTypedScript) import System.Envy (FromEnv (fromEnv), decodeEnv, env) import System.FilePath (takeExtension) data MakerBotConfig = MakerBotConfig - { mbcUser ∷ !UserRaw, - mbcFPNftPolicy ∷ !FilePath, - mbcFPOrderValidator ∷ !FilePath, - mbcPOConfigAddr ∷ !GYAddressBech32, - mbcPORefs ∷ !PORefs, - mbcDelay ∷ !Int, - mbcToken ∷ !MMToken, - mbcStrategyConfig ∷ !StrategyConfig, - mbcPriceConfig ∷ !PriceConfig + { mbcUser ∷ !UserRaw, + mbcDelay ∷ !Int, + mbcToken ∷ !MMToken, + mbcStrategyConfig ∷ !StrategyConfig, + mbcPriceConfig ∷ !PriceConfig } deriving stock (Show, Generic) deriving (FromJSON) via CustomJSON '[FieldLabelModifier '[CamelToSnake]] MakerBotConfig @@ -43,10 +29,6 @@ instance FromEnv MakerBotConfig where fromEnv _ = MakerBotConfig <$> (forceFromJson <$> env "MBC_USER") - <*> env "MBC_FP_NFT_POLICY" - <*> env "MBC_FP_ORDER_VALIDATOR" - <*> (forceFromJson <$> env "MBC_PO_CONFIG_ADDR") - <*> (forceFromJson <$> env "MBC_PO_REFS") <*> env "MBC_DELAY" <*> (forceFromJson <$> env "MBC_TOKEN") <*> (forceFromJson <$> env "MBC_STRATEGY_CONFIG") @@ -81,37 +63,3 @@ buildMakerBot mbDelay = mbcDelay, mbToken = mbcToken } - --- | Read the compiled scripts from the paths. -getDexInfo ∷ MakerBotConfig → IO DEXInfo -getDexInfo - MakerBotConfig - { mbcFPNftPolicy, - mbcFPOrderValidator, - mbcPOConfigAddr, - mbcPORefs - } = do - dexMintRaw ← readNftPolicy - dexValRaw ← readOrderValidator - - let porefs = - PORefs - { porRefNft = porRefNft mbcPORefs, - porMintRef = porMintRef mbcPORefs, - porValRef = porValRef mbcPORefs - } - return - DEXInfo - { dexPartialOrderValidator = dexValRaw, - dexNftPolicy = dexMintRaw, - dexPartialOrderConfigAddr = addressFromBech32 mbcPOConfigAddr, - dexPORefs = porefs - } - where - readNftPolicy - ∷ IO (TypedScript 'MintingPolicyRole '[ScriptHash, Address, AssetClass]) - readNftPolicy = readTypedScript mbcFPNftPolicy - - readOrderValidator - ∷ IO (TypedScript 'ValidatorRole '[Address, AssetClass]) - readOrderValidator = readTypedScript mbcFPOrderValidator diff --git a/geniusyield-market-maker/src/GeniusYield/MarketMaker/Orphans.hs b/geniusyield-market-maker/src/GeniusYield/MarketMaker/Orphans.hs deleted file mode 100644 index afd5c72..0000000 --- a/geniusyield-market-maker/src/GeniusYield/MarketMaker/Orphans.hs +++ /dev/null @@ -1,12 +0,0 @@ -{-# OPTIONS_GHC -Wno-orphans #-} - -module GeniusYield.MarketMaker.Orphans where - -import Deriving.Aeson -import GeniusYield.Api.Dex.PartialOrder (PORefs (..)) - -deriving stock instance Generic PORefs - -deriving via CustomJSON '[FieldLabelModifier '[CamelToSnake]] PORefs instance (FromJSON PORefs) - -deriving via CustomJSON '[FieldLabelModifier '[CamelToSnake]] PORefs instance (ToJSON PORefs) diff --git a/geniusyield-market-maker/src/GeniusYield/MarketMaker/Prices.hs b/geniusyield-market-maker/src/GeniusYield/MarketMaker/Prices.hs index f662e8d..a226fb5 100644 --- a/geniusyield-market-maker/src/GeniusYield/MarketMaker/Prices.hs +++ b/geniusyield-market-maker/src/GeniusYield/MarketMaker/Prices.hs @@ -19,9 +19,9 @@ import qualified Data.Map.Strict as M import Data.Maybe (fromJust) import Data.Text (Text, pack) import Deriving.Aeson +import GeniusYield.Api.Dex.Constants (DEXInfo (..)) import GeniusYield.GYConfig import GeniusYield.Imports (Proxy) -import GeniusYield.MarketMaker.Orphans () import GeniusYield.MarketMaker.Spread (Spread (..)) import GeniusYield.MarketMaker.Utils import GeniusYield.OrderBot.DataSource.Providers (Connection) @@ -250,7 +250,7 @@ getMaestroPrice PP {maestroPP = MaestroPP {..}} mmtp = do let pair = TaggedText pairName - ohlInfo ← handleMaestroError (functionLocationIdent <> " - fetching price from pair") <=< try $ pricesFromDex mppEnv mppDex pair (Just mppResolution) (Just Descending) + ohlInfo ← handleMaestroError (functionLocationIdent <> " - fetching price from pair") <=< try $ pricesFromDex mppEnv mppDex pair (Just mppResolution) Nothing Nothing Nothing (Just Descending) let info = head ohlInfo curPrecision :: Int = fromIntegral $ mmtPrecision $ mmtpCurrency mmtp diff --git a/geniusyield-market-maker/src/GeniusYield/MarketMaker/Utils.hs b/geniusyield-market-maker/src/GeniusYield/MarketMaker/Utils.hs index 113bf59..9483e23 100644 --- a/geniusyield-market-maker/src/GeniusYield/MarketMaker/Utils.hs +++ b/geniusyield-market-maker/src/GeniusYield/MarketMaker/Utils.hs @@ -1,23 +1,14 @@ module GeniusYield.MarketMaker.Utils where -import qualified Cardano.Api as Api -import Data.Aeson (camelTo2) -import qualified Data.Text as Text -import GeniusYield.Api.Dex.PartialOrder (PORefs) -import GeniusYield.Imports (coerce, first, (&)) -import GeniusYield.MarketMaker.User (Secret (getSecret), - User (..)) -import GeniusYield.Providers.Common (SomeDeserializeError (DeserializeErrorAssetClass)) -import GeniusYield.Scripts (HasPartialOrderConfigAddr (..), - HasPartialOrderNftScript (..), - HasPartialOrderScript (..)) +import qualified Cardano.Api as Api +import Data.Aeson (camelTo2) +import qualified Data.Text as Text +import GeniusYield.Imports (coerce, first, (&)) +import GeniusYield.MarketMaker.User (Secret (getSecret), User (..)) +import GeniusYield.Providers.Common (SomeDeserializeError (DeserializeErrorAssetClass)) import GeniusYield.Types -import qualified Maestro.Types.V1 as Maestro -import PlutusLedgerApi.V1.Scripts (ScriptHash) -import PlutusLedgerApi.V1.Value (AssetClass) -import PlutusLedgerApi.V2 (Address) -import Ply (ScriptRole (..), TypedScript) -import Unsafe.Coerce (unsafeCoerce) +import qualified Maestro.Types.V1 as Maestro +import Unsafe.Coerce (unsafeCoerce) camelToSnake :: String -> String camelToSnake = camelTo2 '_' @@ -36,20 +27,3 @@ addrUser netId user = addressFromCredential netId assetClassFromMaestro :: (Maestro.TokenName, Maestro.PolicyId) → Either SomeDeserializeError GYAssetClass assetClassFromMaestro ("", "") = pure GYLovelace assetClassFromMaestro (tokenName, policyId) = first (DeserializeErrorAssetClass . Text.pack) $ parseAssetClassWithSep '#' (coerce policyId <> "#" <> coerce tokenName) - --- | Type that encapsulates the scripts needed for the dex api. -data DEXInfo = DEXInfo - { dexPartialOrderValidator :: !(TypedScript 'ValidatorRole '[Address, AssetClass]), - dexNftPolicy :: !(TypedScript 'MintingPolicyRole '[ScriptHash, Address, AssetClass]), - dexPartialOrderConfigAddr :: !GYAddress, - dexPORefs :: !PORefs - } - -instance HasPartialOrderScript DEXInfo where - getPartialOrderValidator = dexPartialOrderValidator - -instance HasPartialOrderNftScript DEXInfo where - getPartialOrderNftPolicy = dexNftPolicy - -instance HasPartialOrderConfigAddr DEXInfo where - getPartialOrderConfigAddr = dexPartialOrderConfigAddr diff --git a/sample-mainnet-maker-bot-config-gens.yaml b/sample-mainnet-maker-bot-config-gens.yaml index ada661a..f3bb992 100644 --- a/sample-mainnet-maker-bot-config-gens.yaml +++ b/sample-mainnet-maker-bot-config-gens.yaml @@ -87,11 +87,3 @@ mbc_token: ac: dda5fdb1002f7389b33e036b6afee82a8189becb6cba852e8b79b4fb.0014df1047454e53 # Registered decimal places for the token. As an examples, for `ADA` it is 6 and for `SNEK` it is 0. precision: 6 -# Boiler plate for Mainnet. -mbc_fp_nft_policy: compiled-scripts/minting-policy -mbc_fp_order_validator: compiled-scripts/partial-order -mbc_po_config_addr: addr1w9zr09hgj7z6vz3d7wnxw0u4x30arsp5k8avlcm84utptls8uqd0z -mbc_po_refs: - por_ref_nft: fae686ea8f21d567841d703dea4d4221c2af071a6f2b433ff07c0af2.4aff78908ef2dce98bfe435fb3fd2529747b1c4564dff5adebedf4e46d0fc63d - por_val_ref: 062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea#2 - por_mint_ref: 062f97b0e64130bc18b4a227299a62d6d59a4ea852a4c90db3de2204a2cd19ea#1 diff --git a/sample-preprod-maker-bot-config-gens.yaml b/sample-preprod-maker-bot-config-gens.yaml index 0a76502..ae6636c 100644 --- a/sample-preprod-maker-bot-config-gens.yaml +++ b/sample-preprod-maker-bot-config-gens.yaml @@ -91,11 +91,3 @@ mbc_token: ac: c6e65ba7878b2f8ea0ad39287d3e2fd256dc5c4160fc19bdf4c4d87e.7447454e53 # Registered decimal places for the token. As an examples, for `ADA` it is 6 and for `SNEK` it is 0. precision: 6 -# Boiler plate for Pre-production testnet. -mbc_fp_nft_policy: compiled-scripts/minting-policy -mbc_fp_order_validator: compiled-scripts/partial-order -mbc_po_config_addr: addr_test1wrgvy8fermjrruaf7fnndtmpuw4xx4cnvfqjp5zqu8kscfcvh32qk -mbc_po_refs: - por_ref_nft: fae686ea8f21d567841d703dea4d4221c2af071a6f2b433ff07c0af2.8309f9861928a55d37e84f6594b878941edce5e351f7904c2c63b559bde45c5c - por_val_ref: be6f8dc16d4e8d5aad566ff6b5ffefdda574817a60d503e2a0ea95f773175050#2 - por_mint_ref: be6f8dc16d4e8d5aad566ff6b5ffefdda574817a60d503e2a0ea95f773175050#1