Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BE-632 | Include limit order balances in passthrough/portfolio-assets #552

Closed
wants to merge 13 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
BE-586 | Claimbot (#524)
* BE-586 | Claimbot prototype

Init

* BE-586 | WIP

* BE-586 | WIP

* BE-595 | Clean up

* BE-586 | Add docs

* BE-586 | Clean up

* BE-586 | Add docs

* BE-596 | Tests init

* BE-586 | Add tests for slices, orderbook packages

* BE-586 | claimbot/tx tests

* BE-586 | claimbot/order.go tests

* BE-586 | Requested changes

* BE-586 | Process block orderbooks, tests

* BE-586 | Requested changes

* BE-586 | Config update

* BE-586 | OrderBookClient use slices.Split for pagination

Cleans up OrderBookClient by reusing slices.Split instead of duplicating
splitting slices into chunks logic in some of the methods.

* BE-586 | Clean up

* BE-586 | Fix fillbot docker-compose

Fixes errors running fillbot via docker-compose

* BE-586 | Docs, docker compose fixes

* BE-586 | Run fillbot via docker-compose

* BE-586 | Run claimbot via docker-compose, clean up

* BE-586 | Cleanup

* BE-586 | Named logger

* BE-586 | Requested changes

* BE-586 | Logging failing tx

* BE-586 | Increase gas adjustment

* BE-586 | Error logging fix

* BE-586 | Trace name update

* BE-586 | Requested changes #1

* BE-586 | Requested changes #2

* BE-586 | Sequence number update

* BE-586 | added tests

* BE-586 | Suggested improvements
  • Loading branch information
deividaspetraitis authored Nov 3, 2024
commit 2a46eeb4a5cd4dd418fb9d23e68875b53d233720
18 changes: 16 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -243,11 +243,25 @@ orderbook-fillbot-start:
./ingest/usecase/plugins/orderbook/fillbot/create_copy_config.sh
cd ./ingest/usecase/plugins/orderbook/fillbot && docker compose up -d
cd ../../../../
echo "Order Book Filler Bot Started"
echo "Orderbook Fill Bot Started"
sleep 10 && osmosisd status
sleep 10 && docker logs -f osmosis-sqs

orderbook-fillbot-stop:
cd ./ingest/usecase/plugins/orderbook/fillbot && docker compose down
cd ../../../../
echo "Order Book Filler Bot Stopped"
echo "Orderbook Fill Bot Stopped"


orderbook-claimbot-start:
./ingest/usecase/plugins/orderbook/fillbot/create_copy_config.sh
cd ./ingest/usecase/plugins/orderbook/claimbot && docker compose up -d
cd ../../../../
echo "Orderbook Claim Bot Started"
sleep 10 && osmosisd status
sleep 10 && docker logs -f osmosis-sqs

orderbook-claimbot-stop:
cd ./ingest/usecase/plugins/orderbook/claimbot && docker compose down
cd ../../../../
echo "Orderbook Claim Bot Stopped"
24 changes: 23 additions & 1 deletion app/sidecar_query_server.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ import (

ingestrpcdelivry "github.com/osmosis-labs/sqs/ingest/delivery/grpc"
ingestusecase "github.com/osmosis-labs/sqs/ingest/usecase"
orderbookclaimbot "github.com/osmosis-labs/sqs/ingest/usecase/plugins/orderbook/claimbot"
orderbookfillbot "github.com/osmosis-labs/sqs/ingest/usecase/plugins/orderbook/fillbot"
orderbookrepository "github.com/osmosis-labs/sqs/orderbook/repository"
orderbookusecase "github.com/osmosis-labs/sqs/orderbook/usecase"
@@ -271,7 +272,7 @@ func NewSideCarQueryServer(appCodec codec.Codec, config domain.Config, logger lo
if plugin.IsEnabled() {
var currentPlugin domain.EndBlockProcessPlugin

if plugin.GetName() == orderbookplugindomain.OrderBookPluginName {
if plugin.GetName() == orderbookplugindomain.OrderbookFillbotPlugin {
// Create keyring
keyring, err := keyring.New()
if err != nil {
@@ -282,6 +283,27 @@ func NewSideCarQueryServer(appCodec codec.Codec, config domain.Config, logger lo
currentPlugin = orderbookfillbot.New(poolsUseCase, routerUsecase, tokensUseCase, passthroughGRPCClient, orderBookAPIClient, keyring, defaultQuoteDenom, logger)
}

if plugin.GetName() == orderbookplugindomain.OrderbookClaimbotPlugin {
// Create keyring
keyring, err := keyring.New()
if err != nil {
return nil, err
}

logger.Info("Using keyring with address", zap.Stringer("address", keyring.GetAddress()))
currentPlugin, err = orderbookclaimbot.New(
keyring,
orderBookUseCase,
poolsUseCase,
logger,
config.ChainGRPCGatewayEndpoint,
config.ChainID,
)
if err != nil {
return nil, err
}
}

// Register the plugin with the ingest use case
ingestUseCase.RegisterEndBlockProcessPlugin(currentPlugin)
}
32 changes: 19 additions & 13 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
{
"flight-record": {
"enabled": false
},
"otel": {
"enabled": false,
"environment": "sqs-dev"
},
"plugins": [
{
"name": "orderbook",
"enabled": false
}
]
"flight-record": {
"enabled": false
},
"otel": {
"enabled": false,
"environment": "sqs-dev"
},
"grpc-ingester": {
"plugins": [
{
"name": "orderbook-fillbot-plugin",
"enabled": false
},
{
"name": "orderbook-claimbot-plugin",
"enabled": false
}
]
}
}
10 changes: 8 additions & 2 deletions domain/config.go
Original file line number Diff line number Diff line change
@@ -157,7 +157,11 @@ var (
Plugins: []Plugin{
&OrderBookPluginConfig{
Enabled: false,
Name: orderbookplugindomain.OrderBookPluginName,
Name: orderbookplugindomain.OrderbookFillbotPlugin,
},
&OrderBookPluginConfig{
Enabled: false,
Name: orderbookplugindomain.OrderbookClaimbotPlugin,
},
},
},
@@ -377,7 +381,9 @@ func validateDynamicMinLiquidityCapDesc(values []DynamicMinLiquidityCapFilterEnt
// PluginFactory creates a Plugin instance based on the provided name.
func PluginFactory(name string) Plugin {
switch name {
case orderbookplugindomain.OrderBookPluginName:
case orderbookplugindomain.OrderbookFillbotPlugin:
return &OrderBookPluginConfig{}
case orderbookplugindomain.OrderbookClaimbotPlugin:
return &OrderBookPluginConfig{}
// Add cases for other plugins as needed
default:
2 changes: 1 addition & 1 deletion domain/cosmos/tx/tx.go
Original file line number Diff line number Diff line change
@@ -119,7 +119,7 @@ func SimulateMsgs(
txFactory = txFactory.WithAccountNumber(account.AccountNumber)
txFactory = txFactory.WithSequence(account.Sequence)
txFactory = txFactory.WithChainID(chainID)
txFactory = txFactory.WithGasAdjustment(1.05)
txFactory = txFactory.WithGasAdjustment(1.15)

// Estimate transaction
gasResult, adjustedGasUsed, err := gasCalculator.CalculateGas(
26 changes: 21 additions & 5 deletions domain/mocks/orderbook_usecase_mock.go
Original file line number Diff line number Diff line change
@@ -7,17 +7,20 @@ import (
"github.com/osmosis-labs/sqs/domain/mvc"
orderbookdomain "github.com/osmosis-labs/sqs/domain/orderbook"
"github.com/osmosis-labs/sqs/sqsdomain"

"github.com/osmosis-labs/osmosis/osmomath"
)

var _ mvc.OrderBookUsecase = &OrderbookUsecaseMock{}

// OrderbookUsecaseMock is a mock implementation of the RouterUsecase interface
type OrderbookUsecaseMock struct {
ProcessPoolFunc func(ctx context.Context, pool sqsdomain.PoolI) error
GetAllTicksFunc func(poolID uint64) (map[int64]orderbookdomain.OrderbookTick, bool)
GetActiveOrdersFunc func(ctx context.Context, address string) ([]orderbookdomain.LimitOrder, bool, error)
GetActiveOrdersStreamFunc func(ctx context.Context, address string) <-chan orderbookdomain.OrderbookResult
CreateFormattedLimitOrderFunc func(orderbook domain.CanonicalOrderBooksResult, order orderbookdomain.Order) (orderbookdomain.LimitOrder, error)
ProcessPoolFunc func(ctx context.Context, pool sqsdomain.PoolI) error
GetAllTicksFunc func(poolID uint64) (map[int64]orderbookdomain.OrderbookTick, bool)
GetActiveOrdersFunc func(ctx context.Context, address string) ([]orderbookdomain.LimitOrder, bool, error)
GetActiveOrdersStreamFunc func(ctx context.Context, address string) <-chan orderbookdomain.OrderbookResult
CreateFormattedLimitOrderFunc func(orderbook domain.CanonicalOrderBooksResult, order orderbookdomain.Order) (orderbookdomain.LimitOrder, error)
GetClaimableOrdersForOrderbookFunc func(ctx context.Context, fillThreshold osmomath.Dec, orderbook domain.CanonicalOrderBooksResult) ([]orderbookdomain.ClaimableOrderbook, error)
}

func (m *OrderbookUsecaseMock) ProcessPool(ctx context.Context, pool sqsdomain.PoolI) error {
@@ -59,3 +62,16 @@ func (m *OrderbookUsecaseMock) CreateFormattedLimitOrder(orderbook domain.Canoni
}
panic("unimplemented")
}

func (m *OrderbookUsecaseMock) GetClaimableOrdersForOrderbook(ctx context.Context, fillThreshold osmomath.Dec, orderbook domain.CanonicalOrderBooksResult) ([]orderbookdomain.ClaimableOrderbook, error) {
if m.GetClaimableOrdersForOrderbookFunc != nil {
return m.GetClaimableOrdersForOrderbookFunc(ctx, fillThreshold, orderbook)
}
panic("unimplemented")
}

func (m *OrderbookUsecaseMock) WithGetClaimableOrdersForOrderbook(orders []orderbookdomain.ClaimableOrderbook, err error) {
m.GetClaimableOrdersForOrderbookFunc = func(ctx context.Context, fillThreshold osmomath.Dec, orderbook domain.CanonicalOrderBooksResult) ([]orderbookdomain.ClaimableOrderbook, error) {
return orders, err
}
}
6 changes: 6 additions & 0 deletions domain/mvc/orderbook.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package mvc
import (
"context"

"github.com/osmosis-labs/osmosis/osmomath"
"github.com/osmosis-labs/sqs/domain"
orderbookdomain "github.com/osmosis-labs/sqs/domain/orderbook"
"github.com/osmosis-labs/sqs/sqsdomain"
@@ -25,4 +26,9 @@ type OrderBookUsecase interface {

// CreateFormattedLimitOrder creates a formatted limit order from the given orderbook and order.
CreateFormattedLimitOrder(orderbook domain.CanonicalOrderBooksResult, order orderbookdomain.Order) (orderbookdomain.LimitOrder, error)

// GetClaimableOrdersForOrderbook retrieves all claimable orders for a given orderbook.
// It fetches all ticks for the orderbook, processes each tick to find claimable orders,
// and returns a combined list of all claimable orders across all ticks.
GetClaimableOrdersForOrderbook(ctx context.Context, fillThreshold osmomath.Dec, orderbook domain.CanonicalOrderBooksResult) ([]orderbookdomain.ClaimableOrderbook, error)
}
16 changes: 16 additions & 0 deletions domain/orderbook/order.go
Original file line number Diff line number Diff line change
@@ -119,3 +119,19 @@ type OrderbookResult struct {
IsBestEffort bool
Error error
}

// ClaimableOrderbook represents a list of claimable orders for an orderbook.
// If an error occurs processing the orders, it is stored in the error field.
type ClaimableOrderbook struct {
Tick OrderbookTick
Orders []ClaimableOrder
Error error
}

// ClaimableOrder represents an order that is claimable.
// If an error occurs processing the order, it is stored in the error field
// and the order is nil.
type ClaimableOrder struct {
Order Order
Error error
}
16 changes: 16 additions & 0 deletions domain/orderbook/orderbook_tick.go
Original file line number Diff line number Diff line change
@@ -53,3 +53,19 @@ type TickValues struct {
// sync.
LastTickSyncEtas string `json:"last_tick_sync_etas"`
}

// isTickFullyFilled checks if a tick is fully filled by comparing its cumulative total value
// to its effective total amount swapped.
func (tv *TickValues) IsTickFullyFilled() (bool, error) {
cumulativeTotalValue, err := osmomath.NewDecFromStr(tv.CumulativeTotalValue)
if err != nil {
return false, err
}

effectiveTotalAmountSwapped, err := osmomath.NewDecFromStr(tv.EffectiveTotalAmountSwapped)
if err != nil {
return false, err
}

return cumulativeTotalValue.Equal(effectiveTotalAmountSwapped), nil
}
5 changes: 3 additions & 2 deletions domain/orderbook/plugin/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package orderbookplugindomain

// Orderbook plugin names
const (
// OrderBookPluginName is the name of the orderbook plugin.
OrderBookPluginName = "orderbook"
OrderbookFillbotPlugin = "orderbook-fillbot-plugin"
OrderbookClaimbotPlugin = "orderbook-claimbot-plugin"
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DD_API_KEY=YOUR_API_KEY
OSMOSIS_KEYRING_PATH=/root/.osmosisd/keyring-test
OSMOSIS_KEYRING_PASSWORD=test
OSMOSIS_KEYRING_KEY_NAME=local.info
OSMOSIS_KEYRING_KEY_NAME=local.info
69 changes: 69 additions & 0 deletions ingest/usecase/plugins/orderbook/claimbot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Orderbook Claimbot Plugin

The Orderbook Claimbot plugin is a plugin that claims filled order book orders.

It scans all active orders for each order book determining which orders have been filled and need to be claimed. At the moment order is said to be claimable if it is filled 98 percent or more. In order for an order book to be processed to claim its active orders it must be canonical as per SQS definition.


Such order book scanning and claiming is achieved by listening for new blocks and core logic is triggered at the end of each new block by calling Claimbot `ProcessEndBlock` method.

## Configuration

### Node

1. Initialize a fresh node with the `osmosisd` binary.
```bash
osmosisd init claim-bot --chain-id osmosis-1
```

2. Get latest snapshot from [here](https://snapshots.osmosis.zone/index.html)

3. Go to `$HOME/.osmosisd/config/app.toml` and set `osmosis-sqs.is-enabled` to true

4. Optionally, turn off any services from `app.toml` and `config.toml` that you don't need

### SQS

In `config.json`, set the plugin to enabled:

```json
"grpc-ingester":{
...
"plugins": [
{
"name": "orderbook-claimbot-plugin",
"enabled": true
}
]
},
```

Configure the key on a test keyring, and set the following environment variables:
```bash
OSMOSIS_KEYRING_PATH=/root/.osmosisd/keyring-test
OSMOSIS_KEYRING_PASSWORD=test
OSMOSIS_KEYRING_KEY_NAME=local.info
```
- Here, the key is named `local` and the keyring path is in the default `osmosisd` home directory.

To create your key:
```bash
osmosisd keys add local --keyring-backend test --recover

# Enter your mnemonic

# Confirm the key is created
osmosisd keys list --keyring-backend test
```

Note that the test keyring is not a secure approach but we opted-in for simplicity and speed
of PoC implementation. In the future, this can be improved to support multiple backends.

## Starting (via docker compose)

1. Ensure that the "Configuration" section is complete.
2. From project root, `cd` into `ingest/usecase/plugins/orderbook/claimbot`
3. Update `.env` with your environment variables.
4. Run `make orderbook-claimbot-start`
5. Run `osmosisd status` to check that the node is running and caught up to tip.
6. Curl `/healthcheck` to check that SQS is running `curl http://localhost:9092/healthcheck`
54 changes: 54 additions & 0 deletions ingest/usecase/plugins/orderbook/claimbot/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package claimbot

import (
"github.com/osmosis-labs/sqs/delivery/grpc"
authtypes "github.com/osmosis-labs/sqs/domain/cosmos/auth/types"
sqstx "github.com/osmosis-labs/sqs/domain/cosmos/tx"
"github.com/osmosis-labs/sqs/domain/keyring"
"github.com/osmosis-labs/sqs/domain/mvc"
"github.com/osmosis-labs/sqs/log"

txfeestypes "github.com/osmosis-labs/osmosis/v26/x/txfees/types"

txtypes "github.com/cosmos/cosmos-sdk/types/tx"
)

// Config is the configuration for the claimbot plugin
type Config struct {
Keyring keyring.Keyring
PoolsUseCase mvc.PoolsUsecase
OrderbookUsecase mvc.OrderBookUsecase
AccountQueryClient authtypes.QueryClient
TxfeesClient txfeestypes.QueryClient
GasCalculator sqstx.GasCalculator
TxServiceClient txtypes.ServiceClient
ChainID string
Logger log.Logger
}

// NewConfig creates a new Config instance.
func NewConfig(
keyring keyring.Keyring,
orderbookusecase mvc.OrderBookUsecase,
poolsUseCase mvc.PoolsUsecase,
logger log.Logger,
chainGRPCGatewayEndpoint string,
chainID string,
) (*Config, error) {
grpcClient, err := grpc.NewClient(chainGRPCGatewayEndpoint)
if err != nil {
return nil, err
}

return &Config{
Keyring: keyring,
PoolsUseCase: poolsUseCase,
OrderbookUsecase: orderbookusecase,
AccountQueryClient: authtypes.NewQueryClient(grpcClient),
TxfeesClient: txfeestypes.NewQueryClient(grpcClient),
GasCalculator: sqstx.NewGasCalculator(grpcClient),
TxServiceClient: txtypes.NewServiceClient(grpcClient),
Logger: logger.Named("claimbot"),
ChainID: chainID,
}, nil
}
Loading
Loading