Skip to content

Commit

Permalink
feat: draft SwapTx
Browse files Browse the repository at this point in the history
  • Loading branch information
jaeseung-bae committed Apr 19, 2024
1 parent 6afe633 commit fd4945a
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 24 deletions.
18 changes: 17 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,25 @@ require (
)

require (
cosmossdk.io/api v0.7.0 // indirect
cosmossdk.io/collections v0.4.0 // indirect
cosmossdk.io/core v0.10.0 // indirect
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/Workiva/go-datastructures v1.1.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/errors v1.10.0 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20230525220056-bb4fc9527b3b // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cosmos/cosmos-db v1.0.0 // indirect
github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/creachadair/taskgroup v0.6.1 // indirect
github.com/danieljoos/wincred v1.0.2 // indirect
Expand All @@ -74,6 +85,7 @@ require (
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/getsentry/sentry-go v0.23.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
Expand All @@ -91,8 +103,11 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/linxGnu/grocksdb v1.7.16 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
Expand All @@ -105,14 +120,15 @@ require (
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/cors v1.10.1 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sasha-s/go-deadlock v0.3.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/zondax/hid v0.9.2 // indirect
github.com/zondax/ledger-go v0.14.3 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
Expand Down
56 changes: 56 additions & 0 deletions go.sum

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions x/fswap/keeper/expected_keepers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package keeper

import sdk "github.com/Finschia/finschia-sdk/types"

type (
AccountKeeper interface {
GetModuleAddress(name string) sdk.AccAddress
}

BankKeeper interface {
HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
SendCoins(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
}
)
168 changes: 145 additions & 23 deletions x/fswap/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,161 @@
package keeper

import (
"fmt"

"github.com/tendermint/tendermint/libs/log"
"errors"

"github.com/Finschia/finschia-sdk/codec"
storetypes "github.com/Finschia/finschia-sdk/store/types"
sdk "github.com/Finschia/finschia-sdk/types"
sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
"github.com/Finschia/finschia-sdk/x/fswap/types"
)

type (
Keeper struct {
cdc codec.BinaryCodec
accountKeeper types.AccountKeeper
bankKeeper types.BankKeeper
storeKey storetypes.StoreKey
}
// TODO: move const to proper place
const (
OldDenom = "cony"
NewDenom = "TBD"
SwapMultiple = 123
)

func NewKeeper(
cdc codec.BinaryCodec,
ak types.AccountKeeper,
bk types.BankKeeper,
storeKey storetypes.StoreKey,
) Keeper {
return Keeper{
cdc: cdc,
accountKeeper: ak,
bankKeeper: bk,
storeKey: storeKey,
type Keeper struct {
cdc codec.BinaryCodec
storeKey storetypes.StoreKey

AccountKeeper
BankKeeper
}

func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey, ak AccountKeeper, bk BankKeeper) *Keeper {
return &Keeper{
cdc,
storeKey,
ak,
bk,
}
}

func (k Keeper) Swap(ctx sdk.Context, addr sdk.AccAddress, amount sdk.Coin) error {
// 1. Check Balance
// 2. Check swapCap
// 3. Send coin to module
// 4. Burn & Mint TBD coins(with multiple)
// 5. Send back coins to addr
// 6. Update swapped state
if ok := k.HasBalance(ctx, addr, amount); !ok {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "not enough amount: %s", amount)
}

multipleAmount := amount.Amount.Mul(sdk.NewInt(SwapMultiple))
newAmount := sdk.NewCoin(NewDenom, multipleAmount)
if err := k.checkSwapCap(ctx, newAmount); err != nil {
return err
}

moduleAddr := k.GetModuleAddress(types.ModuleName)
if err := k.SendCoins(ctx, addr, moduleAddr, sdk.NewCoins(amount)); err != nil {
return err
}

if err := k.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(amount)); err != nil {
return err
}

if err := k.MintCoins(ctx, types.ModuleName, sdk.NewCoins(newAmount)); err != nil {
return err
}

if err := k.SendCoins(ctx, moduleAddr, addr, sdk.NewCoins(newAmount)); err != nil {
return err
}

if err := k.updateSwapped(ctx, amount, newAmount); err != nil {
return err
}

if err := ctx.EventManager().EmitTypedEvent(&types.EventSwapCoins{
Address: addr.String(),
OldCoinAmount: amount,
NewCoinAmount: newAmount,
}); err != nil {
panic(err)
}
return nil
}

func (k Keeper) SwapAll(ctx sdk.Context, addr sdk.AccAddress) error {
balance := k.GetBalance(ctx, addr, OldDenom)
if balance.IsZero() {
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "zero balance for %s", OldDenom)
}

if err := k.Swap(ctx, addr, balance); err != nil {
return err
}
return nil
}

func (k Keeper) updateSwapped(ctx sdk.Context, oldAmount sdk.Coin, newAmount sdk.Coin) error {
prevSwapped, err := k.GetSwapped(ctx)
if err != nil {
return err
}
updatedSwapped := &types.Swapped{
OldCoinAmount: oldAmount.Add(prevSwapped.OldCoinAmount),
NewCoinAmount: newAmount.Add(prevSwapped.NewCoinAmount),
}

store := ctx.KVStore(k.storeKey)
key := swappedKey()
bz, err := k.cdc.Marshal(updatedSwapped)
if err != nil {
return err
}
store.Set(key, bz)
return nil
}

func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
func (k Keeper) GetSwapped(ctx sdk.Context) (types.Swapped, error) {
store := ctx.KVStore(k.storeKey)
key := swappedKey()
bz := store.Get(key)
swapped := types.Swapped{}
if err := k.cdc.Unmarshal(bz, &swapped); err != nil {
return types.Swapped{}, err
}
return swapped, nil
}

func (k Keeper) setSwapCap(ctx sdk.Context) error {
// TODO(bjs): how to set it only once
//store := ctx.KVStore(k.storeKey)
return nil
}

func (k Keeper) getSwapCap(ctx sdk.Context) (sdk.Coin, error) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(swapCapKey())
if bz == nil {
return sdk.Coin{}, errors.New("swap cap not found")
}

swapCap := sdk.Coin{}
if err := k.cdc.Unmarshal(bz, &swapCap); err != nil {
return sdk.Coin{}, err
}
return swapCap, nil
}

func (k Keeper) checkSwapCap(ctx sdk.Context, amountNewCoin sdk.Coin) error {
swapCap, err := k.getSwapCap(ctx)
if err != nil {
return err
}
swapped, err := k.GetSwapped(ctx)
if err != nil {
return err
}
if swapCap.IsLT(swapped.GetNewCoinAmount().Add(amountNewCoin)) {
return errors.New("not enough swap coin amount")
}
return nil
}
8 changes: 8 additions & 0 deletions x/fswap/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package keeper

import (
"testing"
)

func TestNewKeeper(t *testing.T) {
}
17 changes: 17 additions & 0 deletions x/fswap/keeper/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package keeper

import "cosmossdk.io/collections"

var (
paramsKeyValue = collections.NewPrefix(0)
swappedKeyValue = collections.NewPrefix(1)
swapCapKeyValue = collections.NewPrefix(2)
)

func swappedKey() []byte {
return swappedKeyValue.Bytes()
}

func swapCapKey() []byte {
return swapCapKeyValue.Bytes()
}
Loading

0 comments on commit fd4945a

Please sign in to comment.