Skip to content
Open
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5a230e6
start adding fields to proto and investigating gctcli
samuael Jun 22, 2025
58d4ab3
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jun 25, 2025
621d8f3
update and generate order submit request proto and related files, and…
samuael Jun 26, 2025
f3ae934
update order submit, modify, and cancel proto and command handling
samuael Jun 29, 2025
1be30be
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 3, 2025
8d2f788
update submit order and update order parameters and testing
samuael Jul 3, 2025
afd5ddf
restore config example
samuael Jul 3, 2025
a1c292a
rm unncessary comment
samuael Jul 3, 2025
67c5525
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 8, 2025
c948b75
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 10, 2025
d72aa91
update on order submit, modify, and cancel params processing
samuael Jul 10, 2025
840cda8
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 12, 2025
f9926b6
format .proto file
samuael Jul 12, 2025
69a65f0
cli params unmarshaler and unit tests, types update, and commands han…
samuael Jul 12, 2025
04f9ae7
update on unmarshal and FlagFromStruct method call and commands handling
samuael Jul 13, 2025
6b51735
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 14, 2025
2e6a6c4
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 17, 2025
bc5fc0e
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jul 22, 2025
54037a9
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Aug 1, 2025
fb0e913
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Aug 8, 2025
44ec1bb
minor linter issues fix
samuael Aug 8, 2025
8afc223
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Aug 12, 2025
a922d91
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Aug 16, 2025
62732f1
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 5, 2025
25cb665
updated UpdateCLIFields and FlagsFromStruct methods, and updating str…
samuael Sep 5, 2025
399a26c
replace command flags with struct and FlagsFromStruct method
samuael Sep 6, 2025
fc0eb3f
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 8, 2025
fdc9a78
update command line parameters and handling
samuael Sep 8, 2025
9f60b09
update the unit test and handler types
samuael Sep 8, 2025
58f0274
linter issues fix and code cleanups
samuael Sep 9, 2025
392596d
conver futures flags handling to struct based and added unit tests
samuael Sep 9, 2025
26249e0
update futures commands, types, type to flag converstion, and unit tests
samuael Sep 10, 2025
d53a9de
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 10, 2025
52e5e7d
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 13, 2025
431eb1d
replce trade endpoints and update unit tests
samuael Sep 14, 2025
186fe56
update pair management commands handlers and add test coverage
samuael Sep 14, 2025
29d5944
update on pair management command
samuael Sep 14, 2025
7cd9055
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 16, 2025
cf9d67d
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 16, 2025
031b633
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 17, 2025
7b34e70
update on risk management fieds of bybit value assignment
samuael Sep 17, 2025
2a349e9
fix based on codex feedbacks
samuael Sep 17, 2025
aecd12f
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 18, 2025
8d8e3ff
rename types based on feedbacks
samuael Sep 18, 2025
163780d
currency state fields handling update and unmarshaler function rename
samuael Sep 18, 2025
4b59adf
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Oct 3, 2025
87e2b54
comment, types, and minor handler functions
samuael Oct 3, 2025
eb607e2
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Oct 24, 2025
e3e9ff9
mod file tidy
samuael Oct 24, 2025
8783e2e
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 8, 2025
5d334cf
regenerate pb.go files from .proto file
samuael Nov 9, 2025
399249f
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 16, 2025
9c83586
action functions code structure update
samuael Nov 16, 2025
c879552
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 19, 2025
82131b0
minor fix to client cli handlers
samuael Nov 19, 2025
e4f10fe
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 27, 2025
1de0f6b
added test coverage for POST with a slice
samuael Nov 27, 2025
6e02eb0
Revert "added test coverage for POST with a slice"
samuael Nov 27, 2025
c67951e
Merge branch 'gctcli_update' of https://github.com/samuael/gocryptotr…
samuael Dec 4, 2025
d9b1ac3
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Dec 22, 2025
805943f
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 3, 2026
1f98dfa
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 8, 2026
4bf7e11
minor update
samuael Jan 8, 2026
a4b66bc
miscellaneous checks fix
samuael Jan 18, 2026
d67c5a2
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 18, 2026
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
2,398 changes: 597 additions & 1,801 deletions cmd/gctcli/commands.go

Large diffs are not rendered by default.

176 changes: 176 additions & 0 deletions cmd/gctcli/commands_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package main

import (
"errors"
"fmt"
"os"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/collateral"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/urfave/cli/v2"
)

func TestFlagsFromStruct(t *testing.T) {
t.Parallel()
targets := []cli.Flag{
&cli.StringFlag{Name: "exchange", Required: true, Usage: "the required 'exchange' for the request", Value: "okx"},
&cli.Int64Flag{Name: "leverage", Required: true, Usage: "the required 'leverage' for the request", Value: 1},
&cli.Float64Flag{Name: "price", Usage: "the price for the order", Value: 3.141529},
&cli.StringFlag{Name: "cryptocurrency", Aliases: []string{"c"}, Required: true, Usage: "the cryptocurrency to get the deposit address for"},
&cli.StringFlag{Name: "asset", Aliases: []string{"a"}, Usage: "the optional 'asset' for the request"},
&cli.Int64Flag{Name: "limit", Usage: "the optional 'limit' for the request"},
&cli.BoolFlag{Name: "sync", Usage: "<true/false>", Value: true},
&cli.Float64Flag{Name: "amount", Usage: "the optional 'amount' for the request"},
}
flags := FlagsFromStruct(&struct {
Exchange string `name:"exchange" required:"true"`
Leverage int64 `name:"leverage" required:"t"`
Price float64 `name:"price" usage:"the price for the order"`
Currency string `name:"cryptocurrency,c" required:"t" usage:"the cryptocurrency to get the deposit address for"`
AssetType string `name:"asset,a"`
Limit int64 `name:"limit"`
Sync bool `name:"sync" usage:"<true/false>"`
Amount float64 `name:"amount"`
hiddenValue int64 `name:"hidden"`
NoTag bool
}{
Exchange: "okx",
Leverage: 1,
Price: 3.141529,
Sync: true,
})
require.Len(t, flags, len(targets))
for i := range targets {
require.Equal(t, reflect.TypeOf(targets[i]), reflect.TypeOf(flags[i]))
require.Equal(t, targets[i].Names(), flags[i].Names())
switch target := targets[i].(type) {
case *cli.StringFlag:
flag, ok := flags[i].(*cli.StringFlag)
require.True(t, ok)
require.Equal(t, target.Required, flag.Required)
require.Equal(t, target.Aliases, flag.Aliases)
require.Equal(t, target.Usage, flag.Usage)
require.Equal(t, target.Usage, flag.Usage)
case *cli.Float64Flag:
flag, ok := flags[i].(*cli.Float64Flag)
require.True(t, ok)

require.Equal(t, target.Required, flag.Required)
require.Equal(t, target.Aliases, flag.Aliases)
require.Equal(t, target.Usage, flag.Usage)
require.Equal(t, target.Usage, flag.Usage)
case *cli.Int64Flag:
flag, ok := flags[i].(*cli.Int64Flag)
require.True(t, ok)

require.Equal(t, target.Required, flag.Required)
require.Equal(t, target.Aliases, flag.Aliases)
require.Equal(t, target.Usage, flag.Usage)
require.Equal(t, target.Usage, flag.Usage)
case *cli.BoolFlag:
flag, ok := flags[i].(*cli.BoolFlag)
require.True(t, ok)

require.Equal(t, target.Required, flag.Required)
require.Equal(t, target.Aliases, flag.Aliases)
require.Equal(t, target.Usage, flag.Usage)
require.Equal(t, target.DefaultText, flag.DefaultText)
}
}
}

func TestUnmarshalCLIFields(t *testing.T) {
t.Parallel()
type SampleTest struct {
Exchange string `name:"exchange" required:"t"`
OrderID int64 `name:"order_id" required:"true"`
ClientOrderID string `name:"client_order_id"`
PostOnly bool `name:"post_only"`
ReduceOnly bool `name:"reduce_only"`
}

flags := FlagsFromStruct(&SampleTest{Exchange: "Okx", OrderID: 1234, ClientOrderID: "5678", PostOnly: true})

var target SampleTest
app := &cli.App{
Flags: flags,
Action: func(ctx *cli.Context) error {
return unmarshalCLIFields(ctx, &target)
},
}
err := app.Run([]string{"test", "-exchange", "", "-order_id", "1234", "-client_order_id", "5678"})
require.ErrorIs(t, err, ErrRequiredValueMissing)

err = app.Run([]string{"test", "-exchange", "Okx", "-order_id", "4321", "-client_order_id", "9012", "-post_only", "true"})
require.NoError(t, err)
assert.Equal(t, SampleTest{Exchange: "Okx", OrderID: 4321, ClientOrderID: "9012", PostOnly: true}, target)
}

func TestFunctionsAndStructHandling(t *testing.T) {
t.Parallel()

funcAndValue := []struct {
function func(c *cli.Context) error
val any
args []string
err error
missingRequiredFlag string
}{
// Futures commands handled
{function: getManagedPosition, val: &GetManagedPositionsParams{}, args: []string{"test", "-e", "Okx", "-a", "spot", "-p", "btc-usdt"}, err: futures.ErrNotFuturesAsset},
{function: getManagedPosition, val: &GetManagedPositionsParams{}, args: []string{"test", "-e", "Okx", "-a", "spot"}, missingRequiredFlag: "pair"},
{function: getManagedPosition, val: &GetManagedPositionsParams{}, args: []string{"test", "-e", "Okx", "-a", "futures", "-p", "btc-usdt"}},
{function: getAllManagedPositions, val: &GetAllManagedPositions{}},
{function: getCollateral, val: &GetCollateralParams{}, args: []string{"test", "-e", "okx", "-a", "futures"}},
{function: getLatestFundingRate, val: &GetLatestFundingRateParams{}, args: []string{"test", "-e", "Binance", "-a", "futures", "-p", "btc-usdt"}},
{function: getLatestFundingRate, val: &GetLatestFundingRateParams{}, args: []string{"test", "-e", "Binance", "-a", "", "-p", "btc-usdt"}, err: ErrRequiredValueMissing},
{function: getLatestFundingRate, val: &GetLatestFundingRateParams{}, args: []string{"test", "-e", "Binance", "-a", "futures", "-p", ""}, err: ErrRequiredValueMissing},
{function: getCollateralMode, val: &GetCollateralMode{}, args: []string{"test", "-e", "Binance", "-a", "spot"}, err: futures.ErrNotFuturesAsset},
{function: getCollateralMode, val: &GetCollateralMode{}, args: []string{"test", "-e", "Binance", "-a", "futures"}},
{function: setCollateralMode, val: &SetCollateralMode{}, args: []string{"test", "-e", "kucoin", "--asset", "perpetual_swap", "-c", "multi"}, err: asset.ErrNotSupported},
{function: setCollateralMode, val: &SetCollateralMode{}, args: []string{"test", "-e", "kucoin", "--asset", "delivery", "-c", "abcd"}, err: collateral.ErrInvalidCollateralMode},
{function: setCollateralMode, val: &SetCollateralMode{}, args: []string{"test", "-e", "kucoin", "--asset", "delivery", "-c", "multi"}, err: asset.ErrNotSupported},
{function: setLeverage, val: &SetLeverage{}, args: []string{"test", "--exchange", "binance", "-a", "spot", "-p", "btc_usdt", "-margintype", "multi", "-l", "2312"}, err: futures.ErrNotFuturesAsset},
{function: setLeverage, val: &SetLeverage{}, args: []string{"test", "--exchange", "binance", "-a", "futures", "-p", "btc_usdt", "-margintype", "multi", "-l", "2312"}},
{function: getLeverage, val: &LeverageInfo{}, args: []string{"test", "--exchange", "okx", "-a", "something", "-p", "btc_usdt", "-margintype", "multi"}, err: asset.ErrNotSupported},
{function: getLeverage, val: &LeverageInfo{}, args: []string{"test", "--exchange", "okx", "-a", "spot", "-p", "btc_usdt", "-margintype", "multi"}, err: futures.ErrNotFuturesAsset},
{function: getLeverage, val: &LeverageInfo{}, args: []string{"test", "--exchange", "okx", "-a", "futures", "-p", "btc_usdt", "-margintype", "multi"}},
{function: changePositionMargin, val: &ChangePositionMargin{}, args: []string{"test", "--exchange", "okx", "--asset", "spot", "--pair", "btc-usd", "--margintype", "cross", "--originalallocatedmargin", "123.", "--newallocatedmargin", "456"}, err: futures.ErrNotFuturesAsset},
{function: changePositionMargin, val: &ChangePositionMargin{}, args: []string{"test", "--exchange", "okx", "--asset", "futures", "--pair", "btc-usd", "--margintype", "cross", "--originalallocatedmargin", "123.", "--newallocatedmargin", "456"}},
{function: getFuturesPositionSummary, val: &GetFuturesPositionSummary{}, args: []string{"test", "-e", "deribit", "-a", "spot", "-p", "btc-eth"}, err: futures.ErrNotFuturesAsset},
{function: getFuturesPositionSummary, val: &GetFuturesPositionSummary{}, args: []string{"test", "-e", "deribit", "-a", "coinmarginedfutures", "-p", "btc-eth"}},
{function: getFuturePositionOrders, val: &GetFuturePositionOrders{}, args: []string{"test", "-e", "deribit", "-a", "coinmarginedfutures", "-p", "btc-eth"}},
{function: setMarginType, val: &SetMarginType{}, args: []string{"test", "-e", "deribit", "-a", "coinmarginedfutures", "-margintype", "multi", "-p", "btc-eth"}},
{function: getOpenInterest, val: &GetOpenInterest{}, args: []string{"test", "-e", "kucoin"}},

// Trade commands handler
{function: setExchangeTradeProcessing, val: &SetExchangeTradeProcessingParams{}, args: []string{"test", "-e", "binance", "-status"}},

// Orderbook commands handler
{function: whaleBomb, val: &WhaleBombParams{}, args: []string{"test", "--exchange", "okx", "-asset", "something", "-p", "btc_usdt"}, missingRequiredFlag: "side"},
{function: whaleBomb, val: &WhaleBombParams{}, args: []string{"test", "--exchange", "okx", "-asset", "something", "-p", "btc_usdt", "-s", ""}, err: ErrRequiredValueMissing},
{function: whaleBomb, val: &WhaleBombParams{}, args: []string{"test", "--exchange", "okx", "-asset", "something", "-p", "btc_usdt", "-s", "sell"}},

// Pair management commands handler
{function: enableDisableExchangePair, val: &EnableDisableExchangePairParams{}, args: []string{"test", "-e", "okx", "-p", "btc-usdt", "-asset", "spot"}},
}

for a := range funcAndValue {
app := &cli.App{
Flags: FlagsFromStruct(funcAndValue[a].val),
Action: funcAndValue[a].function,
}

err := app.Run(funcAndValue[a].args)
if funcAndValue[a].missingRequiredFlag != "" {
require.ErrorContains(t, err, fmt.Sprintf("Required flag %q not set", funcAndValue[a].missingRequiredFlag))
} else if !errors.Is(err, os.ErrNotExist) {
require.ErrorIs(t, err, funcAndValue[a].err)
}
}
}
Loading
Loading