Skip to content

Commit

Permalink
Merge pull request #2 from onomyprotocol/pool-logic
Browse files Browse the repository at this point in the history
Pool logic
  • Loading branch information
cgdusek authored Apr 18, 2024
2 parents 3ab4ee5 + 964eaba commit b32919f
Show file tree
Hide file tree
Showing 14 changed files with 5,313 additions and 3 deletions.
982 changes: 982 additions & 0 deletions api/onex/market/member.pulsar.go

Large diffs are not rendered by default.

2,278 changes: 2,278 additions & 0 deletions api/onex/market/pool.pulsar.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
cosmossdk.io/depinject v1.0.0-alpha.4
cosmossdk.io/errors v1.0.1
cosmossdk.io/log v1.3.1
cosmossdk.io/math v1.3.0
cosmossdk.io/store v1.0.2
cosmossdk.io/tools/confix v0.1.1
cosmossdk.io/x/circuit v0.1.0
Expand Down Expand Up @@ -57,7 +58,6 @@ require (
connectrpc.com/connect v1.15.0 // indirect
connectrpc.com/otelconnect v0.7.0 // indirect
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/math v1.3.0 // indirect
cosmossdk.io/x/tx v0.13.1 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
Expand Down
22 changes: 22 additions & 0 deletions proto/onex/market/member.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
syntax = "proto3";
package onex.market;
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";

option go_package = "onex/x/market/types";

// Member defines the parameters for a member of a pair for pool.
message Member {
string pair = 1;
string denom_a = 2;
string denom_b = 3;
// Member Balance of denom b
string balance = 4 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
string previous = 5;
uint64 limit = 6;
uint64 stop = 7;
}
44 changes: 44 additions & 0 deletions proto/onex/market/pool.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
syntax = "proto3";
package onex.market;
import "gogoproto/gogo.proto";
import "cosmos_proto/cosmos.proto";

option go_package = "onex/x/market/types";

// Pool defines the parameters for
message Pool {
string pair = 1;
string denom1 = 2;
string denom2 = 3;
Volume volume1 = 4;
Volume volume2 = 5;
repeated Leader leaders = 6;
// Pool liquidity
string drops = 7 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
uint64 history = 8;
}

// Leader defines the parameters for
message Leader {
string address = 1;
// Pool liquidity
string drops = 7 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}

// Volume defines the parameters for
message Volume {
string denom = 1;
string amount = 2 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}
27 changes: 27 additions & 0 deletions x/market/keeper/member.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package keeper

import (
"github.com/cosmos/cosmos-sdk/runtime"

"context"
"onex/x/market/types"
)

// GetParams get all parameters as types.Params
func (k Keeper) GetMember(
ctx context.Context,
denomA string,
denomB string,
) (member types.Member, found bool) {
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
bz := store.Get(types.MemberKey(
denomA,
denomB,
))
if bz == nil {
return member, false
}

k.cdc.MustUnmarshal(bz, &member)
return member, true
}
104 changes: 102 additions & 2 deletions x/market/keeper/msg_server_create_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,115 @@ import (
"context"

"onex/x/market/types"
"strings"

"cosmossdk.io/math"

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

func (k msgServer) CreatePool(goCtx context.Context, msg *types.MsgCreatePool) (*types.MsgCreatePoolResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// TODO: Handling the message
_ = ctx
// CoinAmsg and CoinBmsg pre-sort from raw msg
coinA, err := sdk.ParseCoinNormalized(msg.CoinA)
if err != nil {
panic(err)
}

coinB, err := sdk.ParseCoinNormalized(msg.CoinB)
if err != nil {
panic(err)
}

coinPair := sdk.NewCoins(coinA, coinB)

// NewCoins sorts denoms.
// The sorted pair joined by "," is used as the key for the pool.
denom1 := coinPair.GetDenomByIndex(0)
denom2 := coinPair.GetDenomByIndex(1)
pair := strings.Join([]string{denom1, denom2}, ",")

// Test if pool either exists and active or exists and inactive
// Inactive pool will be dry or have no drops
member1, _ := k.GetMember(ctx, denom2, denom1)

member2, _ := k.GetMember(ctx, denom1, denom2)

pool, found := k.GetPool(ctx, denom1, denom2)

if found {
if !member1.Balance.Equal(math.ZeroInt()) {
return nil, types.ErrPoolAlreadyExists
}

if !member2.Balance.Equal(math.ZeroInt()) {
return nil, types.ErrPoolAlreadyExists
}

if !pool.Drops.Equal(math.ZeroInt()) {
return nil, types.ErrPoolAlreadyExists
}
}

// Get the borrower address
creator, _ := sdk.AccAddressFromBech32(msg.Creator)

// All coins added to pools are deposited into the module account until redemption
sdkError := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creator, types.ModuleName, coinPair)
if sdkError != nil {
return nil, sdkError
}

// Drops define proportional ownership to the liquidity in the pool
drops := coinPair.AmountOf(denom1).Mul(coinPair.AmountOf(denom2))

leader := types.Leader{
Address: msg.Creator,
Drops: drops,
}

if found {
pool.Drops = drops
pool.Leaders = []*types.Leader{&leader}
member1.Balance = coinPair.AmountOf(denom1)
member2.Balance = coinPair.AmountOf(denom2)
} else {
pool = types.Pool{
Pair: pair,
Leaders: []*types.Leader{&leader},
Denom1: coinPair.GetDenomByIndex(0),
Denom2: coinPair.GetDenomByIndex(1),
Volume1: &types.Volume{
Denom: coinPair.GetDenomByIndex(0),
Amount: math.ZeroInt(),
},
Volume2: &types.Volume{
Denom: coinPair.GetDenomByIndex(1),
Amount: math.ZeroInt(),
},
Drops: drops,
History: uint64(0),
}

member1 = types.Member{
Pair: pair,
DenomA: denom2,
DenomB: denom1,
Balance: coinPair.AmountOf(denom1),
Limit: 0,
Stop: 0,
}

member2 = types.Member{
Pair: pair,
DenomA: denom1,
DenomB: denom2,
Balance: coinPair.AmountOf(denom2),
Limit: 0,
Stop: 0,
}
}

return &types.MsgCreatePoolResponse{}, nil
}
27 changes: 27 additions & 0 deletions x/market/keeper/pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package keeper

import (
"github.com/cosmos/cosmos-sdk/runtime"

"context"
"onex/x/market/types"
)

// GetParams get all parameters as types.Params
func (k Keeper) GetPool(
ctx context.Context,
denomA string,
denomB string,
) (pool types.Pool, found bool) {
store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx))
bz := store.Get(types.PoolKey(
denomA,
denomB,
))
if bz == nil {
return pool, false
}

k.cdc.MustUnmarshal(bz, &pool)
return pool, true
}
42 changes: 42 additions & 0 deletions x/market/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,46 @@ import (
var (
ErrInvalidSigner = sdkerrors.Register(ModuleName, 1100, "expected gov account as only signer for proposal message")
ErrSample = sdkerrors.Register(ModuleName, 1101, "sample error")
// ErrInvalidCoins - coin/coins are invalid.
ErrInvalidCoins = sdkerrors.Register(ModuleName, 1, "coins are invalid")
// ErrInsufficientBalance - the user balance is insufficient for the operation.
ErrInsufficientBalance = sdkerrors.Register(ModuleName, 2, "insufficient balance") // nolint: gomnd
// ErrPoolAlreadyExists - the pool is already exist.
ErrPoolAlreadyExists = sdkerrors.Register(ModuleName, 3, "the pool already exists") // nolint: gomnd
// ErrPoolNotFound - the pool not found.
ErrPoolNotFound = sdkerrors.Register(ModuleName, 4, "the pool not found") // nolint: gomnd
// ErrPoolNotFound - the drop not found.
ErrDropNotFound = sdkerrors.Register(ModuleName, 5, "the pool not found") // nolint: gomnd
// ErrPoolNotFound - the drop not found.
ErrNotDrops = sdkerrors.Register(ModuleName, 6, "not order owner") // nolint: gomnd
// ErrMemberNotFound - the pool member not found.
ErrMemberNotFound = sdkerrors.Register(ModuleName, 7, "the pool member not found") // nolint: gomnd
// ErrInvalidDropAmount - the drop amount is invalid.
ErrInvalidDropAmount = sdkerrors.Register(ModuleName, 8, "invalid drop amount") // nolint: gomnd
// ErrInvalidDenomsPair - invalid demos pair.
ErrInvalidDenomsPair = sdkerrors.Register(ModuleName, 9, "invalid demos pair") // nolint: gomnd
// ErrInvalidOrder - invalid demos pair.
ErrInvalidOrder = sdkerrors.Register(ModuleName, 10, "invalid order") // nolint: gomnd
// ErrPoolNotFound - the drop not found.
ErrOrderNotFound = sdkerrors.Register(ModuleName, 11, "order not found") // nolint: gomnd
// ErrPoolNotFound - the drop not found.
ErrNotOrderOwner = sdkerrors.Register(ModuleName, 12, "not order owner") // nolint: gomnd
// ErrInvalidOrderAmount - invalid bid amount
ErrInvalidOrderAmount = sdkerrors.Register(ModuleName, 13, "invalid order amount") // nolint: gomnd
// ErrSlippageTooGreat - slippage over limit
ErrSlippageTooGreat = sdkerrors.Register(ModuleName, 14, "slippage too great") // nolint: gomnd
// ErrPoolInactive - the pool is not active and has 0 drops.
ErrPoolInactive = sdkerrors.Register(ModuleName, 15, "the pool is inactive") // nolint: gomnd
// ErrDropSumNotFound - the drop sum of owner with drop not found
ErrDropSumNotFound = sdkerrors.Register(ModuleName, 16, "drop sum not found") // nolint: gomnd
// ErrAmtZero - Not greater than zero
ErrAmtZero = sdkerrors.Register(ModuleName, 17, "payment amount equal to zero") // nolint: gomnd
// ErrMemberBalanceZero - the drop sum of owner with drop not found
ErrMemberBalanceZero = sdkerrors.Register(ModuleName, 18, "member balance zero - pool empty") // nolint: gomnd
// ErrDenomMismatch - mismatch of denoms entered
ErrDenomMismatch = sdkerrors.Register(ModuleName, 19, "denoms are not matching") // nolint: gomnd
// ErrLiquidityLow - liquidity is too low
ErrLiquidityLow = sdkerrors.Register(ModuleName, 20, "liquidity too low") // nolint: gomnd
// ErrProductInvalid - liquidity is too low
ErrProductInvalid = sdkerrors.Register(ModuleName, 21, "product less than beg") // nolint: gomnd
)
1 change: 1 addition & 0 deletions x/market/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type AccountKeeper interface {
// BankKeeper defines the expected interface for the Bank module.
type BankKeeper interface {
SpendableCoins(context.Context, sdk.AccAddress) sdk.Coins
SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
// Methods imported from bank should be defined here
}

Expand Down
24 changes: 24 additions & 0 deletions x/market/types/key_member.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package types

const (
// MemberKeyPrefix is the prefix to retrieve all Member
MemberKeyPrefix = "Member/value/"
)

// MemberKey returns the store key to retrieve a Member from the index fields
func MemberKey(
denomA string,
denomB string,
) []byte {
var key []byte

denomABytes := []byte(denomA)
key = append(key, denomABytes...)
key = append(key, []byte("/")...)

denomBBytes := []byte(denomB)
key = append(key, denomBBytes...)
key = append(key, []byte("/")...)

return key
}
31 changes: 31 additions & 0 deletions x/market/types/key_pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package types

import (
"slices"
"strings"
)

const (
// PoolKeyPrefix is the prefix to retrieve all Pool
PoolKeyPrefix = "Pool/value/"
)

// PoolKey returns the store key to retrieve a Pool
func PoolKey(
denomA string,
denomB string,
) []byte {

denoms := []string{denomA, denomB}
// CoinAmsg and CoinBmsg pre-sort from raw msg

slices.Sort(denoms)

var key []byte

pairBytes := []byte(strings.Join(denoms, ", "))
key = append(key, pairBytes...)
key = append(key, []byte("/")...)

return key
}
Loading

0 comments on commit b32919f

Please sign in to comment.