Files
gocryptotrader/cmd/gctcli/commands.go
Andrew f6fd94ea69 Engine: Scripting support (#383)
* WIP

* updated appveyor and increased deadline 5 seconds due to increased linters being added

* revert files to upstream/engine

* WIP

* WIP

* mod file changes

* added script manager

* Added manager/and cli interfaces to scripting

* Added script task handler

* WIP - Added timer/repeat support and fleshed out wrapper further

* autoload support added + WIP

* WIP commit

* added account balance info

* btc markets temp work around

* WIP - merged with upstream for new order package BTC Markets responses broken

* Cancel order wrapper WIP

*  order wrapper update

* Added test coverage for VM

* moved to map for VM List shutdown of all VM now handled added gctcli commands for list and stop of running scripts

* added override to load/execute for path

* fixed incorrect channel shutdown added further test coverage and restructured gctcli commands into sub commands

* increased test coverage for packages

* Added docs cleaned up tests and example scripts

* Test coverage increased for module/gct/exchange package

* windows fixes

* merged upstream/engine

* WIP

* logger fixes - removed pointer to bool check removed duplicate test check for logger

* remove unused mutex

* added inital upload support

* fix linter issues for go-fmt

* added zip support for uploading and added base for fund withdrawing

* changed error return types and also log errors, fix zip path issue

* improved error outputs and code flow

* pairs response fix added protobuf defs for stop all and list all

* added stop all running scripts general clean up and moved across to OrderManager

* linter fixes (gofmt)

* added list all command

* rewrote zip handler to be cleaner also fixed file overwrite on upload

* added query command reworked tests

* added further error checking to compileandrun corrected use of pointers for accountinfo

* bumped tengo version

* Removed named returns reworded log messages removed unused falseptr

* WIP

* Added virutal machine limit improved config options

* added model for script event added upload validation

* script_event table has been completed, tests for wrapper functions implemented

* README updates

* reverted changes opened new PR to move withdraw struct outs

* intial work on adding withdraw support after merger of withdraw package

* started work on examples

* Added crypto withdraw support

* fix switch case assignment and gofmt project

* Reworking Fiat withdraw request pending #402

* removed double pointer call

* added withdraw support for fiat  currencies

* added tests for withdraw methods increased readme

* removed local tengo require and also fix linter issues

* Added default log size const added basic test for invalid script execution

* First pass at moving wrapper to validator package to allow proper validation of uploaded scripts

* Added script details to README added config test added test for no file extension

* moved tests to const and fixed incorrect pathing

* added test coverage to withdraw package

* corrected file close handling

* point to included configtest.json

* extended validator support when a script is uploaded

* Bug fix on bool logic

* Added mutex

* Don't create autit events on test execution

* reverted common to master

* moved file rename to unix timestamp format

* converted logger enabled back to pointer as i need nilness check also moved scriptid to text over blob

* started work on autoload add/remove support

* First round of PR fixes (mostly commented exports)

* Moved GCTScript load to last, removed unneeded error from cleanup()

* Comment clairty for AuitEventID

* added autoload add/remove command to cli

* added tests for autoload

* Test updates for Exchanges

* linter fixes (gofmt)

* Removed double check of engine pointer

* remove possible nil pointer on GetSpecificTicker

* Fixed not closing file handler on write that causes archive removal to fail

* file handler Close clean ups

* corrected spelling on error return and return invalid name n autoload

* moved strings to cosnt moved bool pointer creation to convert package

* new zip extractor added

* Validation has been added to archive uploads

* removed shadow var on err

* added ok check to conversion

* converted condition check

* basic test for zip extract added

* new zip handler

* reverted back to old atomic loading system

* removed shadow err

* lets add a new line

* added space to error return

* command line toggle for script now works properly

* readme updated

* set configLoaded to true

* check for configLoaded condition

* added mutex to allow for multiple access on virtual machine increased test coverage disable script manager if scripting is disabled

* linked up to enable/disablesubsystem commands

* added start/stop example to readme

* reworked logic on test as check should be done on Load()

* updated to tengo v2

* linters

* lower time on ntp client to stop slippage

* remove all fails if any fail validtion from an archive

* remove vm from list if timer is invalid

* removed shadow on err

* remove config creation from NTPCheck test

* WIP testing DB changes

* add unique constraint

* WIP: created has many model

* linters run

* basic sqlite3 support added for new database format

* linters run

* Added test coverage for script repo

* removed unused print

* updated env vars for CI instances

* updated env vars for CI instances

* Updated test packages

* Test updates for postgresql

* removed invalid tests from postgres

* remove duplication of struct and improved code flow

* general cleanup

* wording changes on log output

* use databasemgr logger and add support for autoload without file extension

* corrected test naming

* return correct error

* return correct error again version 82

* store scriptdata on creation

* Hello

* Errorln -> Errorf

* Removed unused vars

* Read me updates

* testing without parallel

* comment on exported type

* added nil check against VM for test

* add debugging information

* gofmt

* remove verbose and data sent to channel

* Added debug information

* linter fixes (gofmt)

* remove unused CompileAndRun() call

* test sleep to see if issue is timing related

* semi-concurrent map fixes

* one day i will run gofmt or setup precommit hooks

* new line :D

* increased test coverage

* added correct sleep time

* Moved over to sync map

* linter fixes (gofmt)

* goimports

* moved VM related methods to vm.go

* new line at end of file

* trying increased timeout on golangci-lint for appveyor

* add debugging information

* removed timeout

* reworked timeout logic

* linter fixes (gofmt)

* increased test coverage

* increased test coverage

* one day i will run gofmt or setup precommit hooks

* removed unused exchange test

* increased golangci-lint timeout

* Added nil check on shutdown and test coverage for it lowered timeout back to 1:30

* reworked ID system

* removed script hash as it was unused

* added comments on exported methods and read me update

* reorder code

* removed to atomic.value for test execution flag

* increased test coverage

* move add further up execution

* point to correct script file
2020-01-23 13:54:04 +11:00

3353 lines
65 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/gctrpc"
"github.com/urfave/cli"
)
var getInfoCommand = cli.Command{
Name: "getinfo",
Usage: "gets GoCryptoTrader info",
Action: getInfo,
}
func getInfo(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetInfo(context.Background(),
&gctrpc.GetInfoRequest{},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getSubsystemsCommand = cli.Command{
Name: "getsubsystems",
Usage: "gets GoCryptoTrader subsystems and their status",
Action: getSubsystems,
}
func getSubsystems(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetSubsystems(context.Background(),
&gctrpc.GetSubsystemsRequest{},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var enableSubsystemCommand = cli.Command{
Name: "enablesubsystem",
Usage: "enables an engine subsystem",
ArgsUsage: "<subsystem>",
Action: enableSubsystem,
Flags: []cli.Flag{
cli.StringFlag{
Name: "subsystem",
Usage: "the subsystem to enable",
},
},
}
func enableSubsystem(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "enablesubsystem")
return nil
}
var subsystemName string
if c.IsSet("subsystem") {
subsystemName = c.String("subsystem")
} else {
subsystemName = c.Args().First()
}
if subsystemName == "" {
return errors.New("invalid subsystem supplied")
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.EnableSubsystem(context.Background(),
&gctrpc.GenericSubsystemRequest{
Subsystem: subsystemName,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var disableSubsystemCommand = cli.Command{
Name: "disablesubsystem",
Usage: "disables an engine subsystem",
ArgsUsage: "<subsystem>",
Action: disableSubsystem,
Flags: []cli.Flag{
cli.StringFlag{
Name: "subsystem",
Usage: "the subsystem to disable",
},
},
}
func disableSubsystem(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "disablesubsystem")
return nil
}
var subsystemName string
if c.IsSet("subsystem") {
subsystemName = c.String("subsystem")
} else {
subsystemName = c.Args().First()
}
if subsystemName == "" {
return errors.New("invalid subsystem supplied")
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.DisableSubsystem(context.Background(),
&gctrpc.GenericSubsystemRequest{
Subsystem: subsystemName,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getRPCEndpointsCommand = cli.Command{
Name: "getrpcendpoints",
Usage: "gets GoCryptoTrader endpoints info",
Action: getRPCEndpoints,
}
func getRPCEndpoints(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetRPCEndpoints(context.Background(),
&gctrpc.GetRPCEndpointsRequest{},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getCommunicationRelayersCommand = cli.Command{
Name: "getcommsrelayers",
Usage: "gets GoCryptoTrader communication relayers",
Action: getCommunicationRelayers,
}
func getCommunicationRelayers(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetCommunicationRelayers(context.Background(),
&gctrpc.GetCommunicationRelayersRequest{},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getExchangesCommand = cli.Command{
Name: "getexchanges",
Usage: "gets a list of enabled or available exchanges",
ArgsUsage: "<enabled>",
Action: getExchanges,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "enabled",
Usage: "whether to list enabled exchanges or not",
},
},
}
func getExchanges(c *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
var enabledOnly bool
if c.IsSet("enabled") {
enabledOnly = c.Bool("enabled")
}
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchanges(context.Background(),
&gctrpc.GetExchangesRequest{
Enabled: enabledOnly,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var enableExchangeCommand = cli.Command{
Name: "enableexchange",
Usage: "enables an exchange",
ArgsUsage: "<exchange>",
Action: enableExchange,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to enable",
},
},
}
func enableExchange(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "enableexchange")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.EnableExchange(context.Background(),
&gctrpc.GenericExchangeNameRequest{
Exchange: exchangeName,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var disableExchangeCommand = cli.Command{
Name: "disableexchange",
Usage: "disables an exchange",
ArgsUsage: "<exchange>",
Action: disableExchange,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to disable",
},
},
}
func disableExchange(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "disableexchange")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.DisableExchange(context.Background(),
&gctrpc.GenericExchangeNameRequest{
Exchange: exchangeName,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getExchangeOTPCommand = cli.Command{
Name: "getexchangeotp",
Usage: "gets a specific exchange OTP code",
ArgsUsage: "<exchange>",
Action: getExchangeOTPCode,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the OTP code for",
},
},
}
func getExchangeOTPCode(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getexchangeotp")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchangeOTPCode(context.Background(),
&gctrpc.GenericExchangeNameRequest{
Exchange: exchangeName,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getExchangeOTPsCommand = cli.Command{
Name: "getexchangeotps",
Usage: "gets all exchange OTP codes",
Action: getExchangeOTPCodes,
}
func getExchangeOTPCodes(c *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchangeOTPCodes(context.Background(),
&gctrpc.GetExchangeOTPsRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getExchangeInfoCommand = cli.Command{
Name: "getexchangeinfo",
Usage: "gets a specific exchanges info",
ArgsUsage: "<exchange>",
Action: getExchangeInfo,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the info for",
},
},
}
func getExchangeInfo(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getexchangeinfo")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchangeInfo(context.Background(),
&gctrpc.GenericExchangeNameRequest{
Exchange: exchangeName,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getTickerCommand = cli.Command{
Name: "getticker",
Usage: "gets the ticker for a specific currency pair and exchange",
ArgsUsage: "<exchange> <pair> <asset>",
Action: getTicker,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the ticker for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair to get the ticker for",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type of the currency pair to get the ticker for",
},
},
}
func getTicker(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getticker")
return nil
}
var exchangeName string
var currencyPair string
var assetType string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(1)
}
if !validPair(currencyPair) {
return errInvalidPair
}
if c.IsSet("asset") {
assetType = c.String("asset")
} else {
assetType = c.Args().Get(2)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetTicker(context.Background(),
&gctrpc.GetTickerRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
AssetType: assetType,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getTickersCommand = cli.Command{
Name: "gettickers",
Usage: "gets all tickers for all enabled exchanges and currency pairs",
Action: getTickers,
}
func getTickers(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetTickers(context.Background(), &gctrpc.GetTickersRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getOrderbookCommand = cli.Command{
Name: "getorderbook",
Usage: "gets the orderbook for a specific currency pair and exchange",
ArgsUsage: "<exchange> <pair> <asset>",
Action: getOrderbook,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the orderbook for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair to get the orderbook for",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type of the currency pair to get the orderbook for",
},
},
}
func getOrderbook(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getorderbook")
return nil
}
var exchangeName string
var currencyPair string
var assetType string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(1)
}
if !validPair(currencyPair) {
return errInvalidPair
}
if c.IsSet("asset") {
assetType = c.String("asset")
} else {
assetType = c.Args().Get(2)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrderbook(context.Background(),
&gctrpc.GetOrderbookRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
AssetType: assetType,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getOrderbooksCommand = cli.Command{
Name: "getorderbooks",
Usage: "gets all orderbooks for all enabled exchanges and currency pairs",
Action: getOrderbooks,
}
func getOrderbooks(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrderbooks(context.Background(), &gctrpc.GetOrderbooksRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getAccountInfoCommand = cli.Command{
Name: "getaccountinfo",
Usage: "gets the exchange account balance info",
ArgsUsage: "<exchange>",
Action: getAccountInfo,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the account info for",
},
},
}
func getAccountInfo(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getaccountinfo")
return nil
}
var exchange string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
if !validExchange(exchange) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetAccountInfo(context.Background(),
&gctrpc.GetAccountInfoRequest{
Exchange: exchange,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getConfigCommand = cli.Command{
Name: "getconfig",
Usage: "gets the config",
Action: getConfig,
}
func getConfig(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetConfig(context.Background(), &gctrpc.GetConfigRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getPortfolioCommand = cli.Command{
Name: "getportfolio",
Usage: "gets the portfolio",
Action: getPortfolio,
}
func getPortfolio(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetPortfolio(context.Background(), &gctrpc.GetPortfolioRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getPortfolioSummaryCommand = cli.Command{
Name: "getportfoliosummary",
Usage: "gets the portfolio summary",
Action: getPortfolioSummary,
}
func getPortfolioSummary(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetPortfolioSummary(context.Background(), &gctrpc.GetPortfolioSummaryRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var addPortfolioAddressCommand = cli.Command{
Name: "addportfolioaddress",
Usage: "adds an address to the portfolio",
ArgsUsage: "<address> <coin_type> <description> <balance>",
Action: addPortfolioAddress,
Flags: []cli.Flag{
cli.StringFlag{
Name: "address",
Usage: "the address to add to the portfolio",
},
cli.StringFlag{
Name: "coin_type",
Usage: "the coin type e.g ('BTC')",
},
cli.StringFlag{
Name: "description",
Usage: "description of the address",
},
cli.Float64Flag{
Name: "balance",
Usage: "balance of the address",
},
},
}
func addPortfolioAddress(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "addportfolioaddress")
return nil
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
var address string
var coinType string
var description string
var balance float64
if c.IsSet("address") {
address = c.String("address")
} else {
address = c.Args().First()
}
if c.IsSet("coin_type") {
coinType = c.String("coin_type")
} else {
coinType = c.Args().Get(1)
}
if c.IsSet("description") {
description = c.String("asset")
} else {
description = c.Args().Get(2)
}
if c.IsSet("balance") {
balance = c.Float64("balance")
} else {
balance, _ = strconv.ParseFloat(c.Args().Get(3), 64)
}
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.AddPortfolioAddress(context.Background(),
&gctrpc.AddPortfolioAddressRequest{
Address: address,
CoinType: coinType,
Description: description,
Balance: balance,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var removePortfolioAddressCommand = cli.Command{
Name: "removeportfolioaddress",
Usage: "removes an address from the portfolio",
ArgsUsage: "<address> <coin_type> <description>",
Action: removePortfolioAddress,
Flags: []cli.Flag{
cli.StringFlag{
Name: "address",
Usage: "the address to add to the portfolio",
},
cli.StringFlag{
Name: "coin_type",
Usage: "the coin type e.g ('BTC')",
},
cli.StringFlag{
Name: "description",
Usage: "description of the address",
},
},
}
func removePortfolioAddress(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "removeportfolioaddress")
return nil
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
var address string
var coinType string
var description string
if c.IsSet("address") {
address = c.String("address")
} else {
address = c.Args().First()
}
if c.IsSet("coin_type") {
coinType = c.String("coin_type")
} else {
coinType = c.Args().Get(1)
}
if c.IsSet("description") {
description = c.String("asset")
} else {
description = c.Args().Get(2)
}
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.RemovePortfolioAddress(context.Background(),
&gctrpc.RemovePortfolioAddressRequest{
Address: address,
CoinType: coinType,
Description: description,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getForexProvidersCommand = cli.Command{
Name: "getforexproviders",
Usage: "gets the available forex providers",
Action: getForexProviders,
}
func getForexProviders(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetForexProviders(context.Background(), &gctrpc.GetForexProvidersRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getForexRatesCommand = cli.Command{
Name: "getforexrates",
Usage: "gets forex rates",
Action: getForexRates,
}
func getForexRates(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetForexRates(context.Background(), &gctrpc.GetForexRatesRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getOrdersCommand = cli.Command{
Name: "getorders",
Usage: "gets the open orders",
ArgsUsage: "<exchange> <asset_type> <pair>",
Action: getOrders,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get orders for",
},
cli.StringFlag{
Name: "asset_type",
Usage: "the asset type to get orders for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair to get orders for",
},
},
}
func getOrders(c *cli.Context) error {
var exchangeName string
var assetType string
var currencyPair string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("asset_type") {
assetType = c.String("asset_type")
} else {
assetType = c.Args().Get(1)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(2)
}
if !validPair(currencyPair) {
return errInvalidPair
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchangeName,
AssetType: assetType,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getOrderCommand = cli.Command{
Name: "getorder",
Usage: "gets the specified order info",
ArgsUsage: "<exchange> <order_id>",
Action: getOrder,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the order for",
},
cli.StringFlag{
Name: "order_id",
Usage: "the order id to retrieve",
},
},
}
func getOrder(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getorder")
return nil
}
var exchangeName string
var orderID string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("order_id") {
orderID = c.String("order_id")
} else {
orderID = c.Args().Get(1)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrder(context.Background(), &gctrpc.GetOrderRequest{
Exchange: exchangeName,
OrderId: orderID,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var submitOrderCommand = cli.Command{
Name: "submitorder",
Usage: "submit order submits an exchange order",
ArgsUsage: "<exchange> <pair> <side> <order_type> <amount> <price> <client_id>",
Action: submitOrder,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to submit the order for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair",
},
cli.StringFlag{
Name: "side",
Usage: "the order side to use (BUY OR SELL)",
},
cli.StringFlag{
Name: "order_type",
Usage: "the order type (MARKET OR LIMIT)",
},
cli.Float64Flag{
Name: "amount",
Usage: "the amount for the order",
},
cli.Float64Flag{
Name: "price",
Usage: "the price for the order",
},
cli.StringFlag{
Name: "client_id",
Usage: "the optional client order ID",
},
},
}
func submitOrder(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "submitorder")
return nil
}
var exchangeName string
var currencyPair string
var orderSide string
var orderType string
var amount float64
var price float64
var clientID string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(1)
}
if !validPair(currencyPair) {
return errInvalidPair
}
if c.IsSet("side") {
orderSide = c.String("side")
} else {
orderSide = c.Args().Get(2)
}
if c.IsSet("order_type") {
orderType = c.String("order_type")
} else {
orderType = c.Args().Get(3)
}
if c.IsSet("amount") {
amount = c.Float64("amount")
} else {
amount, _ = strconv.ParseFloat(c.Args().Get(4), 64)
}
if c.IsSet("price") {
price = c.Float64("price")
} else {
price, _ = strconv.ParseFloat(c.Args().Get(5), 64)
}
if c.IsSet("client_id") {
clientID = c.String("client_id")
} else {
clientID = c.Args().Get(6)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.SubmitOrder(context.Background(), &gctrpc.SubmitOrderRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
Side: orderSide,
OrderType: orderType,
Amount: amount,
Price: price,
ClientId: clientID,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var simulateOrderCommand = cli.Command{
Name: "simulateorder",
Usage: "simulate order simulates an exchange order",
ArgsUsage: "<exchange> <pair> <side> <amount>",
Action: simulateOrder,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to simulate the order for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair",
},
cli.StringFlag{
Name: "side",
Usage: "the order side to use (BUY OR SELL)",
},
cli.Float64Flag{
Name: "amount",
Usage: "the amount for the order",
},
},
}
func simulateOrder(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "simulateorder")
return nil
}
var exchangeName string
var currencyPair string
var orderSide string
var amount float64
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(1)
}
if !validPair(currencyPair) {
return errInvalidPair
}
if c.IsSet("side") {
orderSide = c.String("side")
} else {
orderSide = c.Args().Get(2)
}
if c.IsSet("amount") {
amount = c.Float64("amount")
} else {
amount, _ = strconv.ParseFloat(c.Args().Get(3), 64)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.SimulateOrder(context.Background(), &gctrpc.SimulateOrderRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
Side: orderSide,
Amount: amount,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var whaleBombCommand = cli.Command{
Name: "whalebomb",
Usage: "whale bomb finds the amount required to reach a price target",
ArgsUsage: "<exchange> <pair> <side> <price>",
Action: whaleBomb,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to whale bomb",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair",
},
cli.StringFlag{
Name: "side",
Usage: "the order side to use (BUY OR SELL)",
},
cli.Float64Flag{
Name: "price",
Usage: "the price target",
},
},
}
func whaleBomb(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "whalebomb")
return nil
}
var exchangeName string
var currencyPair string
var orderSide string
var price float64
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(1)
}
if !validPair(currencyPair) {
return errInvalidPair
}
if c.IsSet("side") {
orderSide = c.String("side")
} else {
orderSide = c.Args().Get(2)
}
if c.IsSet("price") {
price = c.Float64("price")
} else {
price, _ = strconv.ParseFloat(c.Args().Get(3), 64)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.WhaleBomb(context.Background(), &gctrpc.WhaleBombRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
Side: orderSide,
PriceTarget: price,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var cancelOrderCommand = cli.Command{
Name: "cancelorder",
Usage: "cancel order cancels an exchange order",
ArgsUsage: "<exchange> <account_id> <order_id> <pair> <asset_type> <wallet_address> <side>",
Action: cancelOrder,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to cancel the order for",
},
cli.StringFlag{
Name: "account_id",
Usage: "the account id",
},
cli.StringFlag{
Name: "order_id",
Usage: "the order id",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair to cancel the order for",
},
cli.StringFlag{
Name: "asset_type",
Usage: "the asset type",
},
cli.Float64Flag{
Name: "wallet_address",
Usage: "the wallet address",
},
cli.StringFlag{
Name: "side",
Usage: "the order side",
},
},
}
func cancelOrder(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "cancelorder")
return nil
}
var exchangeName string
var accountID string
var orderID string
var currencyPair string
var assetType string
var walletAddress string
var orderSide string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("order_id") {
orderID = c.String("order_id")
} else {
orderID = c.Args().Get(2)
}
if c.IsSet("account_id") {
accountID = c.String("account_id")
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
}
if c.IsSet("asset_type") {
assetType = c.String("asset_type")
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
if c.IsSet("wallet_address") {
walletAddress = c.String("wallet_address")
}
if c.IsSet("order_side") {
orderSide = c.String("order_side")
}
var p currency.Pair
if len(currencyPair) > 0 {
if !validPair(currencyPair) {
return errInvalidPair
}
p = currency.NewPairDelimiter(currencyPair, pairDelimiter)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.CancelOrder(context.Background(), &gctrpc.CancelOrderRequest{
Exchange: exchangeName,
AccountId: accountID,
OrderId: orderID,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
AssetType: assetType,
WalletAddress: walletAddress,
Side: orderSide,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var cancelAllOrdersCommand = cli.Command{
Name: "cancelallorders",
Usage: "cancels all orders (all or by exchange name)",
ArgsUsage: "<exchange>",
Action: cancelAllOrders,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to cancel all orders on",
},
},
}
func cancelAllOrders(c *cli.Context) error {
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
// exchange name is an optional param
if exchangeName != "" {
if !validExchange(exchangeName) {
return errInvalidExchange
}
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.CancelAllOrders(context.Background(), &gctrpc.CancelAllOrdersRequest{
Exchange: exchangeName,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getEventsCommand = cli.Command{
Name: "getevents",
Usage: "gets all events",
Action: getEvents,
}
func getEvents(_ *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetEvents(context.Background(), &gctrpc.GetEventsRequest{})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var addEventCommand = cli.Command{
Name: "addevent",
Usage: "adds an event",
ArgsUsage: "<exchange> <item> <condition> <price> <check_bids> <check_bids_and_asks> <orderbook_amount> <pair> <asset_type> <action>",
Action: addEvent,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to add an event for",
},
cli.StringFlag{
Name: "item",
Usage: "the item to trigger the event",
},
cli.StringFlag{
Name: "condition",
Usage: "the condition for the event",
},
cli.Float64Flag{
Name: "price",
Usage: "the price to trigger the event",
},
cli.BoolFlag{
Name: "check_bids",
Usage: "whether to check the bids (if false, asks will be used)",
},
cli.BoolFlag{
Name: "check_bids_and_asks",
Usage: "the wallet address",
},
cli.Float64Flag{
Name: "orderbook_amount",
Usage: "the orderbook amount to trigger the event",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair",
},
cli.StringFlag{
Name: "asset_type",
Usage: "the asset type",
},
cli.StringFlag{
Name: "action",
Usage: "the action for the event to perform upon trigger",
},
},
}
func addEvent(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "addevent")
return nil
}
var exchangeName string
var item string
var condition string
var price float64
var checkBids bool
var checkBidsAndAsks bool
var orderbookAmount float64
var currencyPair string
var assetType string
var action string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
return fmt.Errorf("exchange name is required")
}
if c.IsSet("item") {
item = c.String("item")
} else {
return fmt.Errorf("item is required")
}
if c.IsSet("condition") {
condition = c.String("condition")
} else {
return fmt.Errorf("condition is required")
}
if c.IsSet("price") {
price = c.Float64("price")
}
if c.IsSet("check_bids") {
checkBids = c.Bool("check_bids")
}
if c.IsSet("check_bids_and_asks") {
checkBids = c.Bool("check_bids_and_asks")
}
if c.IsSet("orderbook_amount") {
orderbookAmount = c.Float64("orderbook_amount")
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
return fmt.Errorf("currency pair is required")
}
if c.IsSet("asset_type") {
assetType = c.String("asset_type")
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
if c.IsSet("action") {
action = c.String("action")
} else {
return fmt.Errorf("action is required")
}
if !validPair(currencyPair) {
return errInvalidPair
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.AddEvent(context.Background(), &gctrpc.AddEventRequest{
Exchange: exchangeName,
Item: item,
ConditionParams: &gctrpc.ConditionParams{
Condition: condition,
Price: price,
CheckBids: checkBids,
CheckBidsAndAsks: checkBidsAndAsks,
OrderbookAmount: orderbookAmount,
},
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
AssetType: assetType,
Action: action,
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var removeEventCommand = cli.Command{
Name: "removeevent",
Usage: "removes an event",
ArgsUsage: "<event_id>",
Action: removeEvent,
Flags: []cli.Flag{
cli.StringFlag{
Name: "event_id",
Usage: "the event id to remove",
},
},
}
func removeEvent(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "removeevent")
return nil
}
var eventID int64
if c.IsSet("event_id") {
eventID = c.Int64("event_id")
} else {
evtID, err := strconv.Atoi(c.Args().Get(0))
if err != nil {
return fmt.Errorf("unable to strconv input to int. Err: %s", err)
}
eventID = int64(evtID)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.RemoveEvent(context.Background(),
&gctrpc.RemoveEventRequest{Id: eventID})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getCryptocurrencyDepositAddressesCommand = cli.Command{
Name: "getcryptocurrencydepositaddresses",
Usage: "gets the cryptocurrency deposit addresses for an exchange",
ArgsUsage: "<exchange>",
Action: getCryptocurrencyDepositAddresses,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the cryptocurrency deposit addresses for",
},
},
}
func getCryptocurrencyDepositAddresses(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getcryptocurrencydepositaddresses")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetCryptocurrencyDepositAddresses(context.Background(),
&gctrpc.GetCryptocurrencyDepositAddressesRequest{Exchange: exchangeName})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getCryptocurrencyDepositAddressCommand = cli.Command{
Name: "getcryptocurrencydepositaddress",
Usage: "gets the cryptocurrency deposit address for an exchange and cryptocurrency",
ArgsUsage: "<exchange> <cryptocurrency>",
Action: getCryptocurrencyDepositAddress,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the cryptocurrency deposit address for",
},
cli.StringFlag{
Name: "cryptocurrency",
Usage: "the cryptocurrency to get the deposit address for",
},
},
}
func getCryptocurrencyDepositAddress(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getcryptocurrencydepositaddresses")
return nil
}
var exchangeName string
var cryptocurrency string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("cryptocurrency") {
cryptocurrency = c.String("cryptocurrency")
} else {
cryptocurrency = c.Args().Get(1)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetCryptocurrencyDepositAddress(context.Background(),
&gctrpc.GetCryptocurrencyDepositAddressRequest{
Exchange: exchangeName,
Cryptocurrency: cryptocurrency,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var withdrawCryptocurrencyFundsCommand = cli.Command{
Name: "withdrawcryptocurrencyfunds",
Usage: "withdraws cryptocurrency funds from the desired exchange",
ArgsUsage: "<exchange> <cryptocurrency>",
Action: withdrawCryptocurrencyFunds,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to withdraw from",
},
cli.StringFlag{
Name: "cryptocurrency",
Usage: "the cryptocurrency to withdraw funds from",
},
},
}
func withdrawCryptocurrencyFunds(_ *cli.Context) error {
return common.ErrNotYetImplemented
}
var withdrawFiatFundsCommand = cli.Command{
Name: "withdrawfiatfunds",
Usage: "withdraws fiat funds from the desired exchange",
ArgsUsage: "<exchange> <fiat_currency>",
Action: withdrawFiatFunds,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to withdraw from",
},
cli.StringFlag{
Name: "fiat_currency",
Usage: "the fiat currency to withdraw funds from",
},
},
}
func withdrawFiatFunds(_ *cli.Context) error {
return common.ErrNotYetImplemented
}
var getLoggerDetailsCommand = cli.Command{
Name: "getloggerdetails",
Usage: "gets an individual loggers details",
ArgsUsage: "<logger>",
Action: getLoggerDetails,
Flags: []cli.Flag{
cli.StringFlag{
Name: "logger",
Usage: "logger to get level details of",
},
},
}
func getLoggerDetails(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getloggerdetails")
return nil
}
var logger string
if c.IsSet("logger") {
logger = c.String("logger")
} else {
logger = c.Args().First()
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetLoggerDetails(context.Background(),
&gctrpc.GetLoggerDetailsRequest{
Logger: logger,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var setLoggerDetailsCommand = cli.Command{
Name: "setloggerdetails",
Usage: "sets an individual loggers details",
ArgsUsage: "<logger> <flags>",
Action: setLoggerDetails,
Flags: []cli.Flag{
cli.StringFlag{
Name: "logger",
Usage: "logger to get level details of",
},
cli.StringFlag{
Name: "flags",
Usage: "pipe separated value of loggers e.g INFO|WARN",
},
},
}
func setLoggerDetails(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "setloggerdetails")
return nil
}
var logger string
var level string
if c.IsSet("logger") {
logger = c.String("logger")
} else {
logger = c.Args().First()
}
if c.IsSet("level") {
level = c.String("level")
} else {
level = c.Args().Get(1)
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.SetLoggerDetails(context.Background(),
&gctrpc.SetLoggerDetailsRequest{
Logger: logger,
Level: level,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getExchangePairsCommand = cli.Command{
Name: "getexchangepairs",
Usage: "gets an exchanges supported currency pairs (available and enabled) plus asset types",
ArgsUsage: "<exchange> <asset>",
Action: getExchangePairs,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to list of the currency pairs of",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type to filter by",
},
},
}
func getExchangePairs(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getexchangepairs")
return nil
}
var exchange string
var asset string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
if !validExchange(exchange) {
return errInvalidExchange
}
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(1)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchangePairs(context.Background(),
&gctrpc.GetExchangePairsRequest{
Exchange: exchange,
Asset: asset,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var enableExchangePairCommand = cli.Command{
Name: "enableexchangepair",
Usage: "enables an exchange currency pair",
ArgsUsage: "<exchange> <pair> <asset>",
Action: enableExchangePair,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to enable the currency pair for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair to enable",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type to enable the currency pair for",
},
},
}
func enableExchangePair(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "enableexchangepair")
return nil
}
var exchange string
var pair string
var asset string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
if !validExchange(exchange) {
return errInvalidExchange
}
if c.IsSet("pair") {
pair = c.String("pair")
} else {
pair = c.Args().Get(1)
}
if !validPair(pair) {
return errInvalidPair
}
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(2)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(pair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.EnableExchangePair(context.Background(),
&gctrpc.ExchangePairRequest{
Exchange: exchange,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
AssetType: asset,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var disableExchangePairCommand = cli.Command{
Name: "disableexchangepair",
Usage: "disables a previously enabled exchange currency pair",
ArgsUsage: "<exchange> <pair> <asset>",
Action: disableExchangePair,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to disable the currency pair for",
},
cli.StringFlag{
Name: "pair",
Usage: "the currency pair to disable",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type to disable the currency pair for",
},
},
}
func disableExchangePair(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "disableexchangepair")
return nil
}
var exchange string
var pair string
var asset string
if c.IsSet("exchange") {
exchange = c.String("exchange")
} else {
exchange = c.Args().First()
}
if !validExchange(exchange) {
return errInvalidExchange
}
if c.IsSet("pair") {
pair = c.String("pair")
} else {
pair = c.Args().Get(1)
}
if !validPair(pair) {
return errInvalidPair
}
if c.IsSet("asset") {
asset = c.String("asset")
} else {
asset = c.Args().Get(2)
}
asset = strings.ToLower(asset)
if !validAsset(asset) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(pair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.DisableExchangePair(context.Background(),
&gctrpc.ExchangePairRequest{
Exchange: exchange,
Pair: &gctrpc.CurrencyPair{
Delimiter: p.Delimiter,
Base: p.Base.String(),
Quote: p.Quote.String(),
},
AssetType: asset,
},
)
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var getOrderbookStreamCommand = cli.Command{
Name: "getorderbookstream",
Usage: "gets the orderbook stream for a specific currency pair and exchange",
ArgsUsage: "<exchange> <currencyPair> <asset>",
Action: getOrderbookStream,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the orderbook from",
},
cli.StringFlag{
Name: "pair",
Usage: "currency pair",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type of the currency pair",
},
},
}
func getOrderbookStream(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getorderbookstream")
return nil
}
var exchangeName string
var pair string
var assetType string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
pair = c.String("pair")
} else {
pair = c.Args().Get(1)
}
if !validPair(pair) {
return errInvalidPair
}
if c.IsSet("asset") {
assetType = c.String("asset")
} else {
assetType = c.Args().Get(2)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(pair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrderbookStream(context.Background(),
&gctrpc.GetOrderbookStreamRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Base: p.Base.String(),
Quote: p.Quote.String(),
Delimiter: p.Delimiter,
},
AssetType: assetType,
},
)
if err != nil {
return err
}
for {
resp, err := result.Recv()
if err != nil {
return err
}
err = clearScreen()
if err != nil {
return err
}
fmt.Printf("Orderbook stream for %s %s:\n\n", exchangeName,
resp.Pair.String())
fmt.Println("\t\tBids\t\t\t\tAsks")
fmt.Println()
bidLen := len(resp.Bids) - 1
askLen := len(resp.Asks) - 1
var maxLen int
if bidLen >= askLen {
maxLen = bidLen
} else {
maxLen = askLen
}
for i := 0; i < maxLen; i++ {
var bidAmount, bidPrice float64
if i <= bidLen {
bidAmount = resp.Bids[i].Amount
bidPrice = resp.Bids[i].Price
}
var askAmount, askPrice float64
if i <= askLen {
askAmount = resp.Asks[i].Amount
askPrice = resp.Asks[i].Price
}
fmt.Printf("%f %s @ %f %s\t\t%f %s @ %f %s\n",
bidAmount,
resp.Pair.Base,
bidPrice,
resp.Pair.Quote,
askAmount,
resp.Pair.Base,
askPrice,
resp.Pair.Quote)
if i >= 49 {
// limits orderbook display output
break
}
}
}
}
var getExchangeOrderbookStreamCommand = cli.Command{
Name: "getexchangeorderbookstream",
Usage: "gets a stream for all orderbooks associated with an exchange",
ArgsUsage: "<exchange>",
Action: getExchangeOrderbookStream,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the orderbook from",
},
},
}
func getExchangeOrderbookStream(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getexchangeorderbookstream")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchangeOrderbookStream(context.Background(),
&gctrpc.GetExchangeOrderbookStreamRequest{
Exchange: exchangeName,
})
if err != nil {
return err
}
for {
resp, err := result.Recv()
if err != nil {
return err
}
err = clearScreen()
if err != nil {
return err
}
fmt.Printf("Orderbook streamed for %s %s",
exchangeName,
resp.Pair.String())
}
}
var getTickerStreamCommand = cli.Command{
Name: "gettickerstream",
Usage: "gets the ticker stream for a specific currency pair and exchange",
ArgsUsage: "<exchange> <currencyPair> <asset>",
Action: getTickerStream,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the ticker from",
},
cli.StringFlag{
Name: "pair",
Usage: "currency pair",
},
cli.StringFlag{
Name: "asset",
Usage: "the asset type of the currency pair",
},
},
}
func getTickerStream(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "gettickerstream")
return nil
}
var exchangeName string
var pair string
var assetType string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("pair") {
pair = c.String("pair")
} else {
pair = c.Args().Get(1)
}
if !validPair(pair) {
return errInvalidPair
}
if c.IsSet("asset") {
assetType = c.String("asset")
} else {
assetType = c.Args().Get(2)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
p := currency.NewPairDelimiter(pair, pairDelimiter)
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetTickerStream(context.Background(),
&gctrpc.GetTickerStreamRequest{
Exchange: exchangeName,
Pair: &gctrpc.CurrencyPair{
Base: p.Base.String(),
Quote: p.Quote.String(),
Delimiter: p.Delimiter,
},
AssetType: assetType,
},
)
if err != nil {
return err
}
for {
resp, err := result.Recv()
if err != nil {
return err
}
err = clearScreen()
if err != nil {
return err
}
fmt.Printf("Ticker stream for %s %s:\n", exchangeName,
resp.Pair.String())
fmt.Println()
fmt.Printf("LAST: %f\n HIGH: %f\n LOW: %f\n BID: %f\n ASK: %f\n VOLUME: %f\n PRICEATH: %f\n LASTUPDATED: %d\n",
resp.Last,
resp.High,
resp.Low,
resp.Bid,
resp.Ask,
resp.Volume,
resp.PriceAth,
resp.LastUpdated)
}
}
var getExchangeTickerStreamCommand = cli.Command{
Name: "getexchangetickerstream",
Usage: "gets a stream for all tickers associated with an exchange",
ArgsUsage: "<exchange>",
Action: getExchangeTickerStream,
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "the exchange to get the ticker from",
},
},
}
func getExchangeTickerStream(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
cli.ShowCommandHelp(c, "getexchangetickerstream")
return nil
}
var exchangeName string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetExchangeTickerStream(context.Background(),
&gctrpc.GetExchangeTickerStreamRequest{
Exchange: exchangeName,
})
if err != nil {
return err
}
for {
resp, err := result.Recv()
if err != nil {
return err
}
fmt.Printf("Ticker stream for %s %s:\n",
exchangeName,
resp.Pair.String())
fmt.Printf("LAST: %f HIGH: %f LOW: %f BID: %f ASK: %f VOLUME: %f PRICEATH: %f LASTUPDATED: %d\n",
resp.Last,
resp.High,
resp.Low,
resp.Bid,
resp.Ask,
resp.Volume,
resp.PriceAth,
resp.LastUpdated)
}
}
func clearScreen() error {
switch runtime.GOOS {
case "windows":
cmd := exec.Command("cmd", "/c", "cls")
cmd.Stdout = os.Stdout
return cmd.Run()
default:
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
return cmd.Run()
}
}
const timeFormat = "2006-01-02 15:04:05"
var startTime, endTime, order string
var limit int
var getAuditEventCommand = cli.Command{
Name: "getauditevent",
Usage: "gets audit events matching query parameters",
ArgsUsage: "<starttime> <endtime> <orderby> <limit>",
Action: getAuditEvent,
Flags: []cli.Flag{
cli.StringFlag{
Name: "start, s",
Usage: "start date to search",
Value: time.Now().Add(-time.Hour).Format(timeFormat),
Destination: &startTime,
},
cli.StringFlag{
Name: "end, e",
Usage: "end time to search",
Value: time.Now().Format(timeFormat),
Destination: &endTime,
},
cli.StringFlag{
Name: "order, o",
Usage: "order results by ascending/descending",
Value: "asc",
Destination: &order,
},
cli.IntFlag{
Name: "limit, l",
Usage: "how many results to retrieve",
Value: 100,
Destination: &limit,
},
},
}
func getAuditEvent(c *cli.Context) error {
if !c.IsSet("start") {
if c.Args().Get(0) != "" {
startTime = c.Args().Get(0)
}
}
if !c.IsSet("end") {
if c.Args().Get(1) != "" {
endTime = c.Args().Get(1)
}
}
if !c.IsSet("order") {
if c.Args().Get(2) != "" {
order = c.Args().Get(2)
}
}
if !c.IsSet("limit") {
if c.Args().Get(3) != "" {
limitStr, err := strconv.ParseInt(c.Args().Get(3), 10, 32)
if err == nil {
limit = int(limitStr)
}
}
}
s, err := time.Parse(timeFormat, startTime)
if err != nil {
return fmt.Errorf("invalid time format for start: %v", err)
}
e, err := time.Parse(timeFormat, endTime)
if err != nil {
return fmt.Errorf("invalid time format for end: %v", err)
}
if e.Before(s) {
return errors.New("start cannot be after before")
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
_, offset := time.Now().Zone()
loc := time.FixedZone("", -offset)
result, err := client.GetAuditEvent(context.Background(),
&gctrpc.GetAuditEventRequest{
StartDate: s.In(loc).Format(timeFormat),
EndDate: e.In(loc).Format(timeFormat),
Limit: int32(limit),
OrderBy: order,
Offset: int32(offset),
})
if err != nil {
return err
}
jsonOutput(result)
return nil
}
var uuid, filename, path string
var gctScriptCommand = cli.Command{
Name: "gctscript",
Usage: "execute gctscript command",
ArgsUsage: "<command> <args>",
Subcommands: []cli.Command{
{
Name: "execute",
Usage: "execute script filename",
ArgsUsage: "<filename> <path>",
Flags: []cli.Flag{
cli.StringFlag{
Name: "filename",
Usage: "<filename>",
Destination: &filename,
},
cli.StringFlag{
Name: "path",
Usage: "<script path>",
Destination: &path,
},
},
Action: gctScriptExecute,
},
{
Name: "query",
Usage: "query running virtual machine",
Flags: []cli.Flag{
cli.StringFlag{
Name: "uuid",
Usage: "<uuid>",
Destination: &uuid,
},
},
Action: gctScriptQuery,
},
{
Name: "read",
Usage: "read script",
Flags: []cli.Flag{
cli.StringFlag{
Name: "name",
Usage: "<name>",
Destination: &uuid,
},
},
Action: gctScriptRead,
},
{
Name: "status",
Usage: "get status of running scripts",
Action: gctScriptStatus,
},
{
Name: "list",
Usage: "lists all scripts in default scriptpath",
Action: gctScriptList,
},
{
Name: "stop",
Usage: "terminate running script",
Flags: []cli.Flag{
cli.StringFlag{
Name: "uuid",
Usage: "<uuid>",
Destination: &uuid,
},
},
Action: gctScriptStop,
},
{
Name: "stopall",
Usage: "terminate running script",
Action: gctScriptStopAll,
},
{
Name: "upload",
Usage: "upload a new script/archive",
Flags: []cli.Flag{
cli.StringFlag{
Name: "path",
Usage: "<path> to single script or zip collection",
Destination: &filename,
},
cli.BoolFlag{
Name: "overwrite",
Usage: "<true/false>",
},
cli.BoolFlag{
Name: "archived",
Usage: "<true/false>",
},
},
Action: gctScriptUpload,
},
{
Name: "autoload",
Usage: "add or remove script from autoload list",
Flags: []cli.Flag{
cli.StringFlag{
Name: "command",
Usage: "<add/remove>",
},
cli.StringFlag{
Name: "script",
Usage: "<script name>",
},
},
Action: gctScriptAutoload,
},
},
}
func gctScriptAutoload(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
}
var command, script string
var status bool
if !c.IsSet("command") {
if c.Args().Get(0) != "" {
command = c.Args().Get(0)
}
}
if !c.IsSet("script") {
if c.Args().Get(1) != "" {
script = c.Args().Get(1)
}
}
switch command {
case "add":
status = false
case "remove":
status = true
default:
_ = cli.ShowSubcommandHelp(c)
return nil
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptAutoLoadToggle(context.Background(),
&gctrpc.GCTScriptAutoLoadRequest{
Script: script,
Status: status,
})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptExecute(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
}
if !c.IsSet("filename") {
if c.Args().Get(0) != "" {
filename = c.Args().Get(0)
}
}
if !c.IsSet("path") {
if c.Args().Get(1) != "" {
path = c.Args().Get(1)
}
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptExecute(context.Background(),
&gctrpc.GCTScriptExecuteRequest{
Script: &gctrpc.GCTScript{
Name: filename,
Path: path,
},
})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptStatus(c *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptStatus(context.Background(),
&gctrpc.GCTScriptStatusRequest{})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptList(c *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptListAll(context.Background(),
&gctrpc.GCTScriptListAllRequest{})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptStop(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
}
if !c.IsSet("uuid") {
if c.Args().Get(0) != "" {
uuid = c.Args().Get(0)
}
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptStop(context.Background(),
&gctrpc.GCTScriptStopRequest{
Script: &gctrpc.GCTScript{UUID: uuid},
})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptStopAll(c *cli.Context) error {
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptStopAll(context.Background(),
&gctrpc.GCTScriptStopAllRequest{})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptRead(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
}
if !c.IsSet("name") {
if c.Args().Get(0) != "" {
uuid = c.Args().Get(0)
}
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptReadScript(context.Background(),
&gctrpc.GCTScriptReadScriptRequest{
Script: &gctrpc.GCTScript{
Name: uuid,
},
})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptQuery(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
}
if !c.IsSet("uuid") {
if c.Args().Get(0) != "" {
uuid = c.Args().Get(0)
}
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
executeCommand, err := client.GCTScriptQuery(context.Background(),
&gctrpc.GCTScriptQueryRequest{
Script: &gctrpc.GCTScript{
UUID: uuid,
},
})
if err != nil {
return err
}
jsonOutput(executeCommand)
return nil
}
func gctScriptUpload(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
_ = cli.ShowSubcommandHelp(c)
return nil
}
var overwrite bool
var archived bool
if !c.IsSet("path") {
if c.Args().Get(0) != "" {
filename = c.Args().Get(0)
}
}
if c.IsSet("overwrite") {
overwrite = c.Bool("overwrite")
} else {
ow, err := strconv.ParseBool(c.Args().Get(1))
if err == nil {
overwrite = ow
}
}
if c.IsSet("archived") {
archived = c.Bool("archived")
} else {
ow, err := strconv.ParseBool(c.Args().Get(1))
if err == nil {
archived = ow
}
}
if filepath.Ext(filename) != ".gct" && filepath.Ext(filename) != ".zip" {
return errors.New("file type must be gct or zip")
}
file, err := os.Open(filename)
if err != nil {
return err
}
conn, err := setupClient()
if err != nil {
return err
}
defer conn.Close()
client := gctrpc.NewGoCryptoTraderClient(conn)
data, err := ioutil.ReadAll(file)
if err != nil {
return err
}
uploadCommand, err := client.GCTScriptUpload(context.Background(),
&gctrpc.GCTScriptUploadRequest{
ScriptName: filepath.Base(file.Name()),
Data: data,
Archived: archived,
Overwrite: overwrite,
})
if err != nil {
return err
}
jsonOutput(uploadCommand)
return nil
}