Skip to content

Commit

Permalink
Merge pull request #64 from geniusyield/62-order-details-get-patch
Browse files Browse the repository at this point in the history
fix: remove unnecessary nesting of get order details response
  • Loading branch information
ajuggler authored May 21, 2024
2 parents d7ccfc7 + ce8ef79 commit f879637
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 39 deletions.
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ using the [Trading Strategy Executor Framework](https://github.com/geniusyield/s
Thanks to the programming language agnostic RESTful API, any modern programming
language could be used to implement trading strategies and/or SOR, MMBs.

Intergration with the Genius Yield DEX has never been easier.
Integration with the Genius Yield DEX has never been easier.

> [!TIP]
> Have a look at sample configuration in [Building locally from source using the Haskell Toolchain](#building-locally-from-source-using-the-haskell-toolchain) section for thorough explanation of options made available to configure the server.
### Building locally from source using Docker

Expand Down Expand Up @@ -106,20 +109,16 @@ For details please see the following section:

```yaml
# Blockchain provider used by Atlas, our off-chain transaction building tool.
# Supported values of `coreProvider` represented as JSON for brevity:
# Local node in combination of Kupo, `{ socketPath: string, kupoUrl: string }`
# Maestro, `{ maestroToken: string, turboSubmit: boolean }`
# Blockfrost, `{ blockfrostKey: string }`
# Note that Blockfrost is not recommended as some of the operations performed aren't optimal with it.
# Head over to https://atlas-app.io/getting-started/endpoints#providing-data-provider section to know how to configure `coreProvider` and what all options are available for it.
coreProvider:
maestroToken: YOUR_MAESTRO_TOKEN
turboSubmit: false
# Network id, only `mainnet` and `preprod` are supported for at the moment.
networkId: mainnet
# Logging configuration. It's an array to cater for potentially multiple scribes.
# See it's description mentioned at https://atlas-app.io/getting-started/endpoints#providing-data-provider for more information.
logging:
- type:
# TODO: Possible values of `tag` are to be documented.
tag: stderr
# Possible values of `severity` are `Debug`, `Info`, `Warning` and `Error`.
severity: Debug
Expand Down
5 changes: 5 additions & 0 deletions geniusyield-server-lib/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Revision history for geniusyield-server-lib

## 0.4.0 -- 2024-05-20

* Fix response of GET `/v0/orders/details/{nft-token}` endpoint to not return response under a `data` field nesting.
* Added `/v0/orders/fill` endpoint.

## 0.3.0 -- 2024-05-07

* Adds TapTools OHLCV endpoint.
Expand Down
5 changes: 1 addition & 4 deletions geniusyield-server-lib/geniusyield-server-lib.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 3.6
name: geniusyield-server-lib
version: 0.3.0
version: 0.4.0
synopsis: GeniusYield server library
description: Library for GeniusYield server.
license: Apache-2.0
Expand Down Expand Up @@ -98,11 +98,8 @@ library
, insert-ordered-containers
, lens
, optparse-applicative
, plutus-ledger-api
, ply-core
, rio
, servant
, servant-checked-exceptions
, servant-client
, servant-client-core
, servant-foreign
Expand Down
56 changes: 44 additions & 12 deletions geniusyield-server-lib/src/GeniusYield/Server/Dex/PartialOrder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module GeniusYield.Server.Dex.PartialOrder (
poiToOrderInfo,
PodServerException (..),
PodOrderNotFound (..),
ErrDescription (..),
) where

import Data.Aeson (ToJSON (..))
Expand Down Expand Up @@ -33,7 +32,6 @@ import RIO.Map qualified as Map
import RIO.NonEmpty qualified as NonEmpty
import RIO.Text qualified as T
import Servant
import Servant.Checked.Exceptions

-- | Number of orders that we at most allow to be filled in a single transaction.
maxFillOrders GYNatural
Expand All @@ -52,8 +50,10 @@ data PodOrderNotFound = PodOrderNotFound
deriving (Eq, Show, Generic)
deriving anyclass (Exception, ToJSON)

instance ErrStatus PodOrderNotFound where
toErrStatus _ = status404
instance Swagger.ToSchema PodOrderNotFound where
declareNamedSchema =
Swagger.genericDeclareNamedSchema Swagger.defaultSchemaOptions
& addSwaggerDescription (toErrDescription PodOrderNotFound)

class ErrDescription e where
toErrDescription e Text
Expand Down Expand Up @@ -320,6 +320,23 @@ instance Swagger.ToSchema FillOrderParameters where
& addSwaggerDescription "Fill order(s) request parameters."
& addSwaggerExample (toJSON $ FillOrderParameters {fopAddresses = pure "addr_test1qrsuhwqdhz0zjgnf46unas27h93amfghddnff8lpc2n28rgmjv8f77ka0zshfgssqr5cnl64zdnde5f8q2xt923e7ctqu49mg5", fopChangeAddress = Just (ChangeAddress "addr_test1qrsuhwqdhz0zjgnf46unas27h93amfghddnff8lpc2n28rgmjv8f77ka0zshfgssqr5cnl64zdnde5f8q2xt923e7ctqu49mg5"), fopCollateral = Just "4293386fef391299c9886dc0ef3e8676cbdbc2c9f2773507f1f838e00043a189#1", fopOrderReferencesWithAmount = ("0018dbaa1611531b9f11a31765e8abe875f9c43750b82b5f321350f31e1ea747#0", 100) :| [("0018dbaa1611531b9f11a31765e8abe875f9c43750b82b5f321350f31e144444#0", 100)]})

newtype BotFillOrderParameters = BotFillOrderParameters
{ bfopOrderReferencesWithAmount NonEmpty (GYTxOutRef, GYNatural)
}
deriving stock (Show, Generic)
deriving
(FromJSON, ToJSON)
via CustomJSON '[FieldLabelModifier '[StripPrefix BotFillOrderReqPrefix, CamelToSnake]] BotFillOrderParameters

type BotFillOrderReqPrefix Symbol
type BotFillOrderReqPrefix = "bfop"

instance Swagger.ToSchema BotFillOrderParameters where
declareNamedSchema =
Swagger.genericDeclareNamedSchema Swagger.defaultSchemaOptions {Swagger.fieldLabelModifier = dropSymbolAndCamelToSnake @BotFillOrderReqPrefix}
& addSwaggerDescription "Fill order(s) request parameters specialized towards configured bot."
& addSwaggerExample (toJSON $ BotFillOrderParameters {bfopOrderReferencesWithAmount = ("0018dbaa1611531b9f11a31765e8abe875f9c43750b82b5f321350f31e1ea747#0", 100) :| [("0018dbaa1611531b9f11a31765e8abe875f9c43750b82b5f321350f31e144444#0", 100)]})

type FillOrderResPrefix Symbol
type FillOrderResPrefix = "fotd"

Expand All @@ -344,7 +361,7 @@ type CommonCollateralText ∷ Symbol
type CommonCollateralText = "Note that if \"collateral\" field is not provided, then framework would try to pick collateral UTxO on it's own and in that case would also be free to spend it (i.e., would be made available to coin balancer)."

type CommonSignText Symbol
type CommonSignText = "It uses the signing key from configuration to compute for wallet address. If collateral is specified in the configuration, then it would be used for."
type CommonSignText = "This endpoint would also sign & submit the built transaction. It uses the signing key from configuration to compute for wallet address. If collateral is specified in the configuration, then it would be used for."

type OrdersAPI =
Summary "Build transaction to create order"
Expand All @@ -354,7 +371,7 @@ type OrdersAPI =
:> ReqBody '[JSON] PlaceOrderParameters
:> Post '[JSON] PlaceOrderTransactionDetails
:<|> Summary "Create an order"
:> Description ("Create an order. This endpoint would also sign & submit the built transaction. " `AppendSymbol` CommonSignText `AppendSymbol` " \"stakeAddress\" field from configuration, if provided, is used to place order at a mangled address.")
:> Description ("Create an order. " `AppendSymbol` CommonSignText `AppendSymbol` " \"stakeAddress\" field from configuration, if provided, is used to place order at a mangled address.")
:> ReqBody '[JSON] BotPlaceOrderParameters
:> Post '[JSON] PlaceOrderTransactionDetails
:<|> Summary "Build transaction to cancel order(s)"
Expand All @@ -364,7 +381,7 @@ type OrdersAPI =
:> ReqBody '[JSON] CancelOrderParameters
:> Post '[JSON] CancelOrderTransactionDetails
:<|> Summary "Cancel order(s)"
:> Description ("Cancel order(s). This endpoint would also sign & submit the built transaction. " `AppendSymbol` CommonSignText)
:> Description ("Cancel order(s). " `AppendSymbol` CommonSignText)
:> ReqBody '[JSON] BotCancelOrderParameters
:> Delete '[JSON] CancelOrderTransactionDetails
:<|> Summary "Get order(s) details"
Expand All @@ -376,14 +393,18 @@ type OrdersAPI =
:> Description "Get details of an order using it's unique NFT token. Note that each order is identified uniquely by an associated NFT token which can then later be used to retrieve it's details across partial fills."
:> "details"
:> Capture "nft-token" GYAssetClass
:> Throws PodOrderNotFound
:> Get '[JSON] OrderInfoDetailed
:> UVerb 'GET '[JSON] '[WithStatus 200 OrderInfoDetailed, WithStatus 404 PodOrderNotFound]
:<|> Summary "Build transaction to fill order(s)"
:> Description ("Build a transaction to fill order(s). " `AppendSymbol` CommonCollateralText)
:> "tx"
:> "build-fill"
:> ReqBody '[JSON] FillOrderParameters
:> Post '[JSON] FillOrderTransactionDetails
:<|> Summary "Build transaction to fill order(s)"
:> Description ("Build a transaction to fill order(s). " `AppendSymbol` CommonSignText)
:> "fill"
:> ReqBody '[JSON] BotFillOrderParameters
:> Post '[JSON] FillOrderTransactionDetails

handleOrdersApi Ctx ServerT OrdersAPI IO
handleOrdersApi ctx =
Expand All @@ -394,6 +415,7 @@ handleOrdersApi ctx =
:<|> handleOrdersDetails ctx
:<|> handleOrderDetails ctx
:<|> handleFillOrders ctx
:<|> handleFillOrdersAndSignSubmit ctx

handlePlaceOrder Ctx PlaceOrderParameters IO PlaceOrderTransactionDetails
handlePlaceOrder ctx@Ctx {..} pops@PlaceOrderParameters {..} = do
Expand Down Expand Up @@ -477,14 +499,14 @@ handleCancelOrdersAndSignSubmit ctx BotCancelOrderParameters {..} = do
-- Though transaction id would be same, but we are returning it again, just in case...
pure $ details {cotdTransactionId = txId, cotdTransaction = signedTx}

handleOrderDetails Ctx GYAssetClass IO (Envelope '[PodOrderNotFound] OrderInfoDetailed)
handleOrderDetails Ctx GYAssetClass IO (Union '[WithStatus 200 OrderInfoDetailed, WithStatus 404 PodOrderNotFound])
handleOrderDetails ctx@Ctx {..} ac = do
logInfo ctx $ "Getting order details for NFT token: " +|| ac ||+ ""
let porefs = dexPORefs ctxDexInfo
os runQuery ctx $ fmap poiToOrderInfoDetailed <$> orderByNft porefs ac
case os of
Nothing throwIO PodOrderNotFound
Just o pureSuccEnvelope o
Nothing throwIO PodOrderNotFound -- We could use `respond` here as well but then as it would not have @application/json@ header, it would not be caught by our @errorJsonWrapMiddleware@.
Just o respond (WithStatus @200 o)

handleOrdersDetails Ctx [GYAssetClass] IO [OrderInfoDetailed]
handleOrdersDetails ctx@Ctx {..} acs = do
Expand Down Expand Up @@ -539,3 +561,13 @@ handleFillOrders ctx@Ctx {..} fops@FillOrderParameters {..} = do
takerFee =
Map.foldlWithKey' (\acc ac amt acc <> valueSingleton ac (roundFunctionForPOCVersion overallPocVersion $ toRational amt * rationalToGHC takerFeeRatio)) mempty takerACWithAmt
in takerFee

handleFillOrdersAndSignSubmit Ctx BotFillOrderParameters IO FillOrderTransactionDetails
handleFillOrdersAndSignSubmit ctx BotFillOrderParameters {..} = do
logInfo ctx "Filling order(s) and signing & submitting the transaction."
ctxAddr addressToBech32 <$> resolveCtxAddr ctx
details handleFillOrders ctx $ FillOrderParameters {fopAddresses = pure ctxAddr, fopChangeAddress = Just (ChangeAddress ctxAddr), fopCollateral = ctxCollateral ctx, fopOrderReferencesWithAmount = bfopOrderReferencesWithAmount}
signedTx handleTxSign ctx $ fotdTransaction details
txId handleTxSubmit ctx signedTx
-- Though transaction id would be same, but we are returning it again, just in case...
pure $ details {fotdTransactionId = txId, fotdTransaction = signedTx}
15 changes: 0 additions & 15 deletions geniusyield-server-lib/src/GeniusYield/Server/Orphans.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,11 @@ import Control.Lens (at, (?~))
import Data.HashMap.Strict.InsOrd qualified as IOHM
import Data.Swagger
import GeniusYield.Server.Auth (APIKeyAuthProtect, apiKeyHeaderText)
import GeniusYield.Server.Dex.PartialOrder (ErrDescription (..))
import RIO
import Servant
import Servant.Checked.Exceptions
import Servant.Foreign
import Servant.Swagger

type IsErr err = (ErrDescription err, ErrStatus err)

instance (IsErr err, HasSwagger sub) HasSwagger (Throws err :> sub) where
toSwagger _ =
toSwagger (Proxy Proxy sub)
& setResponseWith
(\old _ addDescription old)
(fromEnum $ toErrStatus (undefined err))
(return $ mempty & description .~ errDescription)
where
addDescription = description %~ ((errDescription <> " OR ") <>)
errDescription = toErrDescription (undefined err)

instance HasSwagger api HasSwagger (APIKeyAuthProtect :> api) where
toSwagger _ =
toSwagger (Proxy Proxy api)
Expand Down
66 changes: 65 additions & 1 deletion web/swagger/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ definitions:
required:
- order_references
type: object
BotFillOrderParameters:
description: Fill order(s) request parameters specialized towards configured bot.
example:
order_references_with_amount:
- - 0018dbaa1611531b9f11a31765e8abe875f9c43750b82b5f321350f31e1ea747#0
- '100'
- - 0018dbaa1611531b9f11a31765e8abe875f9c43750b82b5f321350f31e144444#0
- '100'
properties:
order_references_with_amount:
items:
items:
- $ref: '#/definitions/GYTxOutRef'
- $ref: '#/definitions/GYNatural'
maxItems: 2
minItems: 2
type: array
minItems: 1
type: array
required:
- order_references_with_amount
type: object
BotPlaceOrderParameters:
description: Place order request parameters specialized towards configured bot.
properties:
Expand Down Expand Up @@ -478,6 +500,11 @@ definitions:
- order_ref
- nft_token
type: object
PodOrderNotFound:
description: Order not found
enum:
- PodOrderNotFound
type: string
Settings:
description: Genius Yield Server settings.
properties:
Expand Down Expand Up @@ -957,14 +984,51 @@ paths:
description: Forbidden - The API key does not have permission to perform
the request
'404':
description: Order not found
description: ''
schema:
$ref: '#/definitions/PodOrderNotFound'
'500':
description: Internal server error
security:
- api-key: []
summary: Get order details
tags:
- Orders
/v0/orders/fill:
post:
consumes:
- application/json;charset=utf-8
description: Build a transaction to fill order(s). This endpoint would also
sign & submit the built transaction. It uses the signing key from configuration
to compute for wallet address. If collateral is specified in the configuration,
then it would be used for.
parameters:
- in: body
name: body
required: true
schema:
$ref: '#/definitions/BotFillOrderParameters'
produces:
- application/json;charset=utf-8
responses:
'200':
description: ''
schema:
$ref: '#/definitions/FillOrderTransactionDetails'
'400':
description: Invalid `body`
'401':
description: Unauthorized access - API key missing
'403':
description: Forbidden - The API key does not have permission to perform
the request
'500':
description: Internal server error
security:
- api-key: []
summary: Build transaction to fill order(s)
tags:
- Orders
/v0/orders/tx/build-cancel:
post:
consumes:
Expand Down

0 comments on commit f879637

Please sign in to comment.