mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 15:09:51 +00:00
* WIP * end of day WIP started migration of trade history * added kline support to hitbtc huobi lbank * added exchangehistory to all supported exchanges started work on coinbase 300 candles/request method * end of day WIP * removed unused ta and misc changes to flag ready for review * yobit cleanup * revert coinbase changES * general code clean up and added zb support * poloniex support added * renamed method to FormatExchangeKlineInterval other misc fixes * linter fixes * linter fixes * removed verbose * fixed poloniex test coverage * revert poloniex mock data * regenerated poloniex mock data * a very verbose clean up * binance mock clean up * removed unneeded t.Log() * setting verbose to true to debug CI issue * first pass changes addressed * common.ErrNotYetImplemented implemented :D * comments added * WIP-addressed exchange requests and reverted previous GetExchangeHistory changes * WIP-addressed exchange requests and reverted previous GetExchangeHistory changes * increased test coverage added kraken support * OKGroup support completed started work on address GetExchangeHistory feedback and migrating to own PR under https://github.com/xtda/gocryptotrader/tree/exchange_history * convert zb ratelimits * gofmt run on okcoin * increased delay on rate limit * gofmt package * fixed panic with coinbene and bithumb if conversion fails * very broken end of day WIP * added support for GetHistoricCandlesEx to coinbase and binance * gofmt package * coinbase, btcmarkets, zb ex wrapper function added * added all exchange support for ex regenerated mock data * update bithumb to return wrapper method * gofmt package * end of day started work on changes * models created for exchange/asset/currency/currencypair, new seed system created * reworked test coverage added okgroup support general fixes/change requests addressed * Added OneMonth * limit checks on supportedexchanges * reverted getexchangehistory * started work on currency seeding and insertion * reworked binance tesT * added workaround for kraken panic * :D extremely broken WIP * renamed command to extended removed interval check on non-implemented commands * added wrapperconfig back * increased test coverage for FormatExchangeKlineInterval * WIP * increased test coverage for FormatExchangeKlineInterval bitfinex/gateio/huobi * linter fixes * zb kraken lbank coinbene btcmarkets support added * removed verbose * OK group support for other asset types added * swapped margin to use spot endpoint * index support added test coverage added for asset types * added asset type to okcoin test * gofmt * add asset to extended method * removed verbose * Very broken WIP models need to be regenerated * add support for coinbene swap increase test coverage * removed verbose * small clean up of okgroup wrapper functions * verbose to troubleshoot CI issues * removed verbose * added error check reverted coinbasechanges * attempting to fix broken model generation * readme updated * :D i broke so much * model regeneration fixed & complete * candle model filled out * removed unused start/finish started work on decoupling api requests from kline package * restructured coinbene, bithumb methods, added bitstamp support * kraken time fix * BTCMarkets restructure * typo fix * removed test for futures due to contact changing * removed test for futures due to contact changing * added start/end date to extended method over range * WIP * added sync option to candles * converted to assettranslator * removed verbose * removed verbose * removed invalid char * reverted incorrectly removed return * added import * further template updates * macos hates my keyboard :D * misc canges * started work on creating kline from databases eed * x -> i * removed verbose * updated fixCasing to allocate var before checks * sqlite3 supported work started * removed time conversion * further work on tets * sort all outgoing kline candles * fixCasing fix * after/before checks added * added parallel to test * logic check on BTCmarkets * removed unused param, used correct iterator * converted HitBTC to use time.Time * test update * add iszero false check to candle times * Seed exchange & OHCLV data for test usage * updated resultlimit to 5000 * new line added * added comment to exported const * move date forward * use configured ratelimit * fixed pair for test * panic fixed WIP on fixCasing * fixCasing rework, started work on readme docs * enable rate limiter for wrapper issues tool * docs updated * removed unused vars from tests * removed err from return and formatted currency * updated Yobit supported status * Updated HitBTC to use onehour candles due to test exeuction times * added further details to gctcli output * added link to docs * added link to tempalte * disable FTX websocket in config_example * fix poloneix * regenerated poloniex mock data * removed recording flag * format on package * moved exchange var outside of method scope * reworked seeding into package * verbose output improved * removed verbose from candles * Added comments to exported functions * removed verbose output * Reworking of tests * end of day commit * added SQLite migration for asset, test updates for exchange, added support for withdrawal for new exchange_name_id relation * regenerated database models * WIP * test rework, sqlite migration updates for withdrawal * Reworked error returns to stop duplications, format all output to UTC, changed gctscript OHLCV output to be unix timestmap, started work on seeding tool * gofmt * dbseed command for seeding exchanges added, removed seed from dbmigrate, LoadCSV method added for exchange * go mod tidy * added import candle from csv command to dbseed * Removed reset & duplicate migrate command from helper, renamed struct to Item/Candle over Candle/Tick, added test coverage to dbseed, improved withdraw tests * remove broken tests due to ORM generation of Fk, removed go unneeded goroutine for inserting records * removed t.Cleanup usage because appveyor * added test coverage to StoreInDatabase() * removed unneeded data from config for test * added new line * Added down migration support to candle/asset removal, return original error and display rollback error * removed unneeded err assignment, break out of loop on error * add err check to method for test * first pass changes * WIP * Updated migrations for both sqlite3 & postgres to create exchanges if any withdrawal_history records are found, removed migrate command * removed argusage as usage information is provided by flags * added inserted records return count and test coverage * new line added * Database: comment config details out to disable local postgresl testing by default * added asset support * Database: added error return when no exchanges are found, title exchange name across queries * Fixed test data * Database: removed migration bool from ConnectToDatabase(), removed empty line, insert asset on test * Database: verbose linter :D * Database/OHLCV: removed go module from dbseed command and reverted back to main module, converted interval to int64 to match other parts of code base, provided migrations to update database, poloniex fix to skip first candle * dbseed: add completed message to output * Database: added migration to add asset to uniq index for candle table * Database: database -> exchange * Database: add asset to upsert conflict * Poloneix: fix for invalid interval * regenerated poloniex mock data * Database: added down migration for candle interval update * OHCLV/Database: WIP * OHLCV/Datastore: added new ValidateKline() method to check that asset, pair, interval are enabled/supported by exchange and updated tests * revert configtest changes * OHCLV/Kline: pointer assignment to ErrorKline & format pairs on check * goimports * migration updates * Database/Candle: updated tests * revert configtest changes * ZB: updaed defaults to use uppercase pairs * ZB: updaed defaults to use uppercase pairs * revert pair formatting * Switch over to .Cotains() method from pairManagement * Added comment & ftx back 😆 * OHLCV/Datastore: (Candles): added not null to asset, (WithdrawalHistory): added not null to exchange_name_id), reworked KlineError return * set verbose to false * updated btc markets test * Updated readme * removed ability to have blank exchange name as indexing requires it * remove old usedb and empty exchange check, return error on no data instead * Updated kline test to match date range * Renamed candles.exchange_id column to candles.xchange_name_id to match withdrawal table, return err on unwrap, zb fix revert * regenerated sqlite3 models * force UTC for sqlite.... because sqlite * OHLCV/Datastore: upper case pairs on insert for consistency, remove unneeded rollback call on commit failure as it has no effect, move rollback outside of insertsqlite/insertpsql methods * add error check for no candles * nil length/cap is 0 in golang :D * OHLCV/Datastore: updated wording on examples, removed duplicate testfile * OHLCV/Datastore: updated README with links to dbseed * dbtool -> dbseed
4037 lines
80 KiB
Go
4037 lines
80 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math"
|
|
"os"
|
|
"path/filepath"
|
|
"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 startTime, endTime, order string
|
|
var limit int
|
|
|
|
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, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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 getAccountInfoStreamCommand = cli.Command{
|
|
Name: "getaccountinfostream",
|
|
Usage: "gets the account info stream for a specific exchange",
|
|
ArgsUsage: "<exchange>",
|
|
Action: getAccountInfoStream,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "the exchange to get the account info stream from",
|
|
},
|
|
},
|
|
}
|
|
|
|
func getAccountInfoStream(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
cli.ShowCommandHelp(c, "getaccountinfostream")
|
|
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.GetAccountInfoStream(context.Background(),
|
|
&gctrpc.GetAccountInfoRequest{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("Account balance stream for %s:\n\n", exchangeName)
|
|
|
|
fmt.Printf("%+v", resp)
|
|
}
|
|
}
|
|
|
|
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> <cold_storage> <supported_exchanges> ",
|
|
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",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "cold_storage",
|
|
Usage: "true/false if address is cold storage",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "supported_exchanges",
|
|
Usage: "common separated list of exchanges supported by this address for withdrawals",
|
|
},
|
|
},
|
|
}
|
|
|
|
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
|
|
var supportedExchanges string
|
|
var coldstorage bool
|
|
|
|
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("description")
|
|
} else {
|
|
description = c.Args().Get(2)
|
|
}
|
|
|
|
if c.IsSet("balance") {
|
|
balance = c.Float64("balance")
|
|
} else if c.Args().Get(3) != "" {
|
|
balance, err = strconv.ParseFloat(c.Args().Get(3), 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if c.IsSet("cold_storage") {
|
|
coldstorage = c.Bool("cold_storage")
|
|
} else {
|
|
tv, errBool := strconv.ParseBool(c.Args().Get(4))
|
|
if errBool == nil {
|
|
coldstorage = tv
|
|
}
|
|
}
|
|
|
|
if c.IsSet("supported_exchanges") {
|
|
supportedExchanges = c.String("supported_exchanges")
|
|
} else {
|
|
supportedExchanges = c.Args().Get(5)
|
|
}
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
result, err := client.AddPortfolioAddress(context.Background(),
|
|
&gctrpc.AddPortfolioAddressRequest{
|
|
Address: address,
|
|
CoinType: coinType,
|
|
Description: description,
|
|
Balance: balance,
|
|
SupportedExchanges: supportedExchanges,
|
|
ColdStorage: coldstorage,
|
|
},
|
|
)
|
|
|
|
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("description")
|
|
} 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> <pair>",
|
|
Action: getOrders,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "the exchange to get orders for",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "asset",
|
|
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") {
|
|
assetType = c.String("asset")
|
|
} 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, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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> <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: "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 orderSide == "" {
|
|
return errors.New("order side must be set")
|
|
}
|
|
|
|
if c.IsSet("type") {
|
|
orderType = c.String("type")
|
|
} else {
|
|
orderType = c.Args().Get(3)
|
|
}
|
|
|
|
if orderType == "" {
|
|
return errors.New("order type must be set")
|
|
}
|
|
|
|
if c.IsSet("amount") {
|
|
amount = c.Float64("amount")
|
|
} else if c.Args().Get(4) != "" {
|
|
var err error
|
|
amount, err = strconv.ParseFloat(c.Args().Get(4), 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if amount == 0 {
|
|
return errors.New("amount must be set")
|
|
}
|
|
|
|
// price is optional for market orders
|
|
if c.IsSet("price") {
|
|
price = c.Float64("price")
|
|
} else if c.Args().Get(5) != "" {
|
|
var err error
|
|
price, err = strconv.ParseFloat(c.Args().Get(5), 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
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, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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 orderSide == "" {
|
|
return errors.New("side must be set")
|
|
}
|
|
|
|
if c.IsSet("amount") {
|
|
amount = c.Float64("amount")
|
|
} else if c.Args().Get(3) != "" {
|
|
var err error
|
|
amount, err = strconv.ParseFloat(c.Args().Get(3), 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if amount == 0 {
|
|
return errors.New("amount must be set")
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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 orderSide == "" {
|
|
return errors.New("order side must be set")
|
|
}
|
|
|
|
if c.IsSet("price") {
|
|
price = c.Float64("price")
|
|
} else if c.Args().Get(3) != "" {
|
|
var err error
|
|
price, err = strconv.ParseFloat(c.Args().Get(3), 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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> <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",
|
|
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("account_id") {
|
|
accountID = c.String("account_id")
|
|
} else {
|
|
accountID = c.Args().Get(1)
|
|
}
|
|
|
|
if c.IsSet("order_id") {
|
|
orderID = c.String("order_id")
|
|
} else {
|
|
orderID = c.Args().Get(2)
|
|
}
|
|
|
|
if orderID == "" {
|
|
return errors.New("an order ID must be set")
|
|
}
|
|
|
|
if c.IsSet("pair") {
|
|
currencyPair = c.String("pair")
|
|
} else {
|
|
currencyPair = c.Args().Get(3)
|
|
}
|
|
|
|
if c.IsSet("asset") {
|
|
assetType = c.String("asset")
|
|
} else {
|
|
assetType = c.Args().Get(4)
|
|
}
|
|
|
|
assetType = strings.ToLower(assetType)
|
|
if !validAsset(assetType) {
|
|
return errInvalidAsset
|
|
}
|
|
|
|
if c.IsSet("wallet_address") {
|
|
walletAddress = c.String("wallet_address")
|
|
} else {
|
|
walletAddress = c.Args().Get(5)
|
|
}
|
|
|
|
if c.IsSet("side") {
|
|
orderSide = c.String("side")
|
|
} else {
|
|
orderSide = c.Args().Get(6)
|
|
}
|
|
|
|
// pair is optional, but if it's set, do a validity check
|
|
var p currency.Pair
|
|
if len(currencyPair) > 0 {
|
|
if !validPair(currencyPair) {
|
|
return errInvalidPair
|
|
}
|
|
var err error
|
|
p, err = currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
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> <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",
|
|
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 !validExchange(exchangeName) {
|
|
return errInvalidExchange
|
|
}
|
|
|
|
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 !validPair(currencyPair) {
|
|
return errInvalidPair
|
|
}
|
|
|
|
if c.IsSet("asset") {
|
|
assetType = c.String("asset")
|
|
}
|
|
|
|
assetType = strings.ToLower(assetType)
|
|
if !validAsset(assetType) {
|
|
return errInvalidAsset
|
|
}
|
|
|
|
if c.IsSet("action") {
|
|
action = c.String("action")
|
|
} else {
|
|
return fmt.Errorf("action is required")
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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 if c.Args().Get(0) != "" {
|
|
var err error
|
|
eventID, err = strconv.ParseInt(c.Args().Get(0), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if eventID == 0 {
|
|
return errors.New("event id must be specified")
|
|
}
|
|
|
|
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 if c.Args().Get(1) != "" {
|
|
cryptocurrency = c.Args().Get(1)
|
|
}
|
|
|
|
if cryptocurrency == "" {
|
|
return errors.New("cryptocurrency must be set")
|
|
}
|
|
|
|
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: "withdrawcryptofunds",
|
|
Usage: "withdraws cryptocurrency funds from the desired exchange",
|
|
ArgsUsage: "<exchange> <currency> <amount> <address> <addresstag> <fee> <description>",
|
|
Action: withdrawCryptocurrencyFunds,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "the exchange to withdraw from",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "currency",
|
|
Usage: "the cryptocurrency to withdraw funds from",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "address",
|
|
Usage: "address to withdraw to",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "addresstag",
|
|
Usage: "address tag/memo",
|
|
},
|
|
cli.Float64Flag{
|
|
Name: "amount",
|
|
Usage: "amount of funds to withdraw",
|
|
},
|
|
cli.Float64Flag{
|
|
Name: "fee",
|
|
Usage: "fee to submit with request",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "description",
|
|
Usage: "description to submit with request",
|
|
},
|
|
},
|
|
}
|
|
|
|
func withdrawCryptocurrencyFunds(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
cli.ShowCommandHelp(c, "withdrawcryptofunds")
|
|
return nil
|
|
}
|
|
|
|
var exchange, cur, address, addressTag, description string
|
|
var amount, fee float64
|
|
|
|
if c.IsSet("exchange") {
|
|
exchange = c.String("exchange")
|
|
} else if c.Args().Get(0) != "" {
|
|
exchange = c.Args().Get(0)
|
|
}
|
|
|
|
if !validExchange(exchange) {
|
|
return errInvalidExchange
|
|
}
|
|
|
|
if c.IsSet("currency") {
|
|
cur = c.String("currency")
|
|
} else if c.Args().Get(1) != "" {
|
|
cur = c.Args().Get(1)
|
|
}
|
|
|
|
if c.IsSet("amount") {
|
|
amount = c.Float64("amount")
|
|
} else if c.Args().Get(2) != "" {
|
|
amountStr, err := strconv.ParseFloat(c.Args().Get(2), 64)
|
|
if err == nil {
|
|
amount = amountStr
|
|
}
|
|
}
|
|
|
|
if c.IsSet("address") {
|
|
address = c.String("address")
|
|
} else if c.Args().Get(3) != "" {
|
|
address = c.Args().Get(3)
|
|
}
|
|
|
|
if c.IsSet("addresstag") {
|
|
addressTag = c.String("addresstag")
|
|
} else if c.Args().Get(4) != "" {
|
|
addressTag = c.Args().Get(4)
|
|
}
|
|
|
|
if c.IsSet("fee") {
|
|
fee = c.Float64("fee")
|
|
} else if c.Args().Get(5) != "" {
|
|
feeStr, err := strconv.ParseFloat(c.Args().Get(5), 64)
|
|
if err == nil {
|
|
fee = feeStr
|
|
}
|
|
}
|
|
|
|
if c.IsSet("description") {
|
|
description = c.String("description")
|
|
} else if c.Args().Get(6) != "" {
|
|
description = c.Args().Get(6)
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
|
|
result, err := client.WithdrawCryptocurrencyFunds(context.Background(),
|
|
&gctrpc.WithdrawCryptoRequest{
|
|
Exchange: exchange,
|
|
Currency: cur,
|
|
Address: address,
|
|
AddressTag: addressTag,
|
|
Amount: amount,
|
|
Fee: fee,
|
|
Description: description,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|
|
|
|
var withdrawFiatFundsCommand = cli.Command{
|
|
Name: "withdrawfiatfunds",
|
|
Usage: "withdraws fiat funds from the desired exchange",
|
|
ArgsUsage: "<exchange> <currency> <amount> <bankaccount id> <description>",
|
|
Action: withdrawFiatFunds,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "the exchange to withdraw from",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "currency",
|
|
Usage: "the fiat currency to withdraw funds from",
|
|
},
|
|
cli.Float64Flag{
|
|
Name: "amount",
|
|
Usage: "amount of funds to withdraw",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "bankaccountid",
|
|
Usage: "ID of bank account to use",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "description",
|
|
Usage: "description to submit with request",
|
|
},
|
|
},
|
|
}
|
|
|
|
func withdrawFiatFunds(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
cli.ShowCommandHelp(c, "withdrawfiatfunds")
|
|
return nil
|
|
}
|
|
|
|
var exchange, cur, description, bankAccountID string
|
|
var amount float64
|
|
|
|
if c.IsSet("exchange") {
|
|
exchange = c.String("exchange")
|
|
} else if c.Args().Get(0) != "" {
|
|
exchange = c.Args().Get(0)
|
|
}
|
|
|
|
if !validExchange(exchange) {
|
|
return errInvalidExchange
|
|
}
|
|
|
|
if c.IsSet("currency") {
|
|
cur = c.String("currency")
|
|
} else if c.Args().Get(1) != "" {
|
|
cur = c.Args().Get(1)
|
|
}
|
|
|
|
if c.IsSet("amount") {
|
|
amount = c.Float64("amount")
|
|
} else if c.Args().Get(2) != "" {
|
|
amountStr, err := strconv.ParseFloat(c.Args().Get(2), 64)
|
|
if err == nil {
|
|
amount = amountStr
|
|
}
|
|
}
|
|
|
|
if c.IsSet("bankaccountid") {
|
|
bankAccountID = c.String("bankaccountid")
|
|
} else if c.Args().Get(3) != "" {
|
|
bankAccountID = c.Args().Get(3)
|
|
}
|
|
|
|
if c.IsSet("description") {
|
|
description = c.String("description")
|
|
} else if c.Args().Get(4) != "" {
|
|
description = c.Args().Get(4)
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
result, err := client.WithdrawFiatFunds(context.Background(),
|
|
&gctrpc.WithdrawFiatRequest{
|
|
Exchange: exchange,
|
|
Currency: cur,
|
|
Amount: amount,
|
|
Description: description,
|
|
BankAccountId: bankAccountID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|
|
|
|
var withdrawalRequestCommand = cli.Command{
|
|
Name: "withdrawalrequesthistory",
|
|
Usage: "retrieve previous withdrawal request details",
|
|
ArgsUsage: "<type> <args>",
|
|
Subcommands: []cli.Command{
|
|
{
|
|
Name: "byid",
|
|
Usage: "id",
|
|
ArgsUsage: "<id>",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Usage: "<id>",
|
|
},
|
|
},
|
|
Action: withdrawlRequestByID,
|
|
},
|
|
{
|
|
Name: "byexchangeid",
|
|
Usage: "exchange id",
|
|
ArgsUsage: "<id>",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "<exchange>",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "id",
|
|
Usage: "<id>",
|
|
},
|
|
},
|
|
Action: withdrawlRequestByExchangeID,
|
|
},
|
|
{
|
|
Name: "byexchange",
|
|
Usage: "exchange limit",
|
|
ArgsUsage: "<id>",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "<exchange>",
|
|
},
|
|
cli.Int64Flag{
|
|
Name: "limit",
|
|
Usage: "<limit>",
|
|
},
|
|
},
|
|
Action: withdrawlRequestByExchangeID,
|
|
},
|
|
{
|
|
Name: "bydate",
|
|
Usage: "exchange start end limit",
|
|
ArgsUsage: "<exchange> <start> <end> <limit>",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange",
|
|
Usage: "<exchange>",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "start",
|
|
Usage: "<start>",
|
|
Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat),
|
|
Destination: &startTime,
|
|
},
|
|
cli.StringFlag{
|
|
Name: "end",
|
|
Usage: "<end>",
|
|
Value: time.Now().Format(common.SimpleTimeFormat),
|
|
Destination: &endTime,
|
|
},
|
|
cli.Int64Flag{
|
|
Name: "limit",
|
|
Usage: "<limit>",
|
|
},
|
|
},
|
|
Action: withdrawlRequestByDate,
|
|
},
|
|
},
|
|
}
|
|
|
|
func withdrawlRequestByID(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
cli.ShowSubcommandHelp(c)
|
|
return nil
|
|
}
|
|
|
|
var ID string
|
|
if c.IsSet("id") {
|
|
ID = c.String("id")
|
|
} else {
|
|
ID = c.Args().First()
|
|
}
|
|
|
|
if ID == "" {
|
|
return errors.New("an ID must be specified")
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
|
|
result, err := client.WithdrawalEventByID(context.Background(),
|
|
&gctrpc.WithdrawalEventByIDRequest{
|
|
Id: ID,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|
|
|
|
func withdrawlRequestByExchangeID(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
cli.ShowSubcommandHelp(c)
|
|
return nil
|
|
}
|
|
|
|
var exchange string
|
|
if c.IsSet("exchange") {
|
|
exchange = c.String("exchange")
|
|
} else {
|
|
exchange = c.Args().First()
|
|
}
|
|
|
|
var limit, limitStr int64
|
|
var ID string
|
|
var err error
|
|
if c.Command.Name == "byexchangeid" {
|
|
if c.IsSet("id") {
|
|
ID = c.String("id")
|
|
} else {
|
|
ID = c.Args().Get(1)
|
|
}
|
|
if ID == "" {
|
|
return errors.New("an ID must be specified")
|
|
}
|
|
limit = 1
|
|
} else {
|
|
if c.IsSet("limit") {
|
|
limit = c.Int64("limit")
|
|
} else if c.Args().Get(1) != "" {
|
|
limitStr, err = strconv.ParseInt(c.Args().Get(1), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if limitStr > math.MaxInt32 {
|
|
return fmt.Errorf("limit greater than max size: %v", math.MaxInt32)
|
|
}
|
|
limit = limitStr
|
|
}
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
|
|
result, err := client.WithdrawalEventsByExchange(context.Background(),
|
|
&gctrpc.WithdrawalEventsByExchangeRequest{
|
|
Exchange: exchange,
|
|
Id: ID,
|
|
Limit: int32(limit),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|
|
|
|
func withdrawlRequestByDate(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
cli.ShowSubcommandHelp(c)
|
|
return nil
|
|
}
|
|
|
|
var exchange string
|
|
var limit, limitStr int64
|
|
var err error
|
|
if c.IsSet("exchange") {
|
|
exchange = c.String("exchange")
|
|
} else {
|
|
exchange = c.Args().First()
|
|
}
|
|
|
|
if !c.IsSet("start") {
|
|
if c.Args().Get(1) != "" {
|
|
startTime = c.Args().Get(1)
|
|
}
|
|
}
|
|
|
|
if !c.IsSet("end") {
|
|
if c.Args().Get(2) != "" {
|
|
endTime = c.Args().Get(2)
|
|
}
|
|
}
|
|
|
|
if c.IsSet("limit") {
|
|
limit = c.Int64("limit")
|
|
} else if c.Args().Get(3) != "" {
|
|
limitStr, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if limitStr > math.MaxInt32 {
|
|
return fmt.Errorf("limit greater than max size: %v", math.MaxInt32)
|
|
}
|
|
limit = limitStr
|
|
}
|
|
|
|
s, err := time.Parse(common.SimpleTimeFormat, startTime)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid time format for start: %v", err)
|
|
}
|
|
|
|
e, err := time.Parse(common.SimpleTimeFormat, 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")
|
|
}
|
|
|
|
_, offset := time.Now().Zone()
|
|
loc := time.FixedZone("", -offset)
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
result, err := client.WithdrawalEventsByDate(context.Background(),
|
|
&gctrpc.WithdrawalEventsByDateRequest{
|
|
Exchange: exchange,
|
|
Start: s.In(loc).Format(common.SimpleTimeFormat),
|
|
End: e.In(loc).Format(common.SimpleTimeFormat),
|
|
Limit: int32(limit),
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
if logger == "" {
|
|
return errors.New("a logger must be specified")
|
|
}
|
|
|
|
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 logger == "" {
|
|
return errors.New("a logger must be specified")
|
|
}
|
|
|
|
if c.IsSet("level") {
|
|
level = c.String("level")
|
|
} else {
|
|
level = c.Args().Get(1)
|
|
}
|
|
|
|
if level == "" {
|
|
return errors.New("level must be specified")
|
|
}
|
|
|
|
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 getOrderbookStreamCommand = cli.Command{
|
|
Name: "getorderbookstream",
|
|
Usage: "gets the orderbook stream for a specific currency pair and exchange",
|
|
ArgsUsage: "<exchange> <pair> <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, err := currency.NewPairDelimiter(pair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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> <pair> <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, err := currency.NewPairDelimiter(pair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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(common.SimpleTimeFormat),
|
|
Destination: &startTime,
|
|
},
|
|
cli.StringFlag{
|
|
Name: "end, e",
|
|
Usage: "end time to search",
|
|
Value: time.Now().Format(common.SimpleTimeFormat),
|
|
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, 64)
|
|
if err == nil {
|
|
limit = int(limitStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
s, err := time.Parse(common.SimpleTimeFormat, startTime)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid time format for start: %v", err)
|
|
}
|
|
|
|
e, err := time.Parse(common.SimpleTimeFormat, 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(common.SimpleTimeFormat),
|
|
EndDate: e.In(loc).Format(common.SimpleTimeFormat),
|
|
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: "script",
|
|
Usage: "execute scripting management 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
|
|
}
|
|
|
|
const klineMessage = "%v in seconds supported values are: 15, 60(1min), 180(3min), 300(5min), 600(10min), 900(15min), " +
|
|
"1800(30min), 3600(1h), 7200(2h), 14400(4h), 21600(6h), 28800(8h), 43200(12h), 86400(1d), 259200(3d) " +
|
|
"60480(1w), 1209600(2w), 1296000(15d), 2592000(1M), 31536000(1Y)"
|
|
|
|
var candleRangeSize, candleGranularity int64
|
|
var getHistoricCandlesCommand = cli.Command{
|
|
Name: "gethistoriccandles",
|
|
Usage: "gets historical candles for the specified granularity up to range size time from now.",
|
|
ArgsUsage: "<exchange> <pair> <asset> <rangesize> <granularity>",
|
|
Action: getHistoricCandles,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange, e",
|
|
Usage: "the exchange to get the candles from",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pair",
|
|
Usage: "the currency pair to get the candles for",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "asset",
|
|
Usage: "the asset type of the currency pair",
|
|
},
|
|
cli.Int64Flag{
|
|
Name: "rangesize, r",
|
|
Usage: "the amount of time to go back from now to fetch candles in the given granularity",
|
|
Value: 10,
|
|
Destination: &candleRangeSize,
|
|
},
|
|
cli.Int64Flag{
|
|
Name: "granularity, g",
|
|
Usage: fmt.Sprintf(klineMessage, "granularity"),
|
|
Value: 86400,
|
|
Destination: &candleGranularity,
|
|
},
|
|
},
|
|
}
|
|
|
|
func getHistoricCandles(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
return cli.ShowCommandHelp(c, "gethistoriccandles")
|
|
}
|
|
|
|
var exchangeName string
|
|
if c.IsSet("exchange") {
|
|
exchangeName = c.String("exchange")
|
|
} else {
|
|
exchangeName = c.Args().First()
|
|
}
|
|
if !validExchange(exchangeName) {
|
|
return errInvalidExchange
|
|
}
|
|
|
|
var currencyPair string
|
|
if c.IsSet("pair") {
|
|
currencyPair = c.String("pair")
|
|
} else {
|
|
currencyPair = c.Args().Get(1)
|
|
}
|
|
if !validPair(currencyPair) {
|
|
return errInvalidPair
|
|
}
|
|
p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var assetType string
|
|
if c.IsSet("asset") {
|
|
assetType = c.String("asset")
|
|
} else {
|
|
assetType = c.Args().Get(2)
|
|
}
|
|
|
|
if !validAsset(assetType) {
|
|
return errInvalidAsset
|
|
}
|
|
|
|
if c.IsSet("rangesize") {
|
|
candleRangeSize = c.Int64("rangesize")
|
|
} else if c.Args().Get(3) != "" {
|
|
candleRangeSize, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if c.IsSet("granularity") {
|
|
candleGranularity = c.Int64("granularity")
|
|
} else if c.Args().Get(4) != "" {
|
|
candleGranularity, err = strconv.ParseInt(c.Args().Get(4), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
candleInterval := time.Duration(candleGranularity) * time.Second
|
|
|
|
end := time.Now().UTC().Truncate(candleInterval)
|
|
start := end.Add(-candleInterval * time.Duration(candleRangeSize))
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
result, err := client.GetHistoricCandles(context.Background(),
|
|
&gctrpc.GetHistoricCandlesRequest{
|
|
Exchange: exchangeName,
|
|
Pair: &gctrpc.CurrencyPair{
|
|
Delimiter: p.Delimiter,
|
|
Base: p.Base.String(),
|
|
Quote: p.Quote.String(),
|
|
},
|
|
AssetType: assetType,
|
|
Start: start.Unix(),
|
|
End: end.Unix(),
|
|
TimeInterval: int64(candleInterval),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|
|
|
|
var getHistoricCandlesExtendedCommand = cli.Command{
|
|
Name: "gethistoriccandlesextended",
|
|
Usage: "gets historical candles for the specified pair, asset, interval & date range",
|
|
ArgsUsage: "<exchange> <pair> <asset> <interval> <start> <end>",
|
|
Action: getHistoricCandlesExtended,
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "exchange, e",
|
|
Usage: "the exchange to get the candles from",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "pair",
|
|
Usage: "the currency pair to get the candles for",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "asset",
|
|
Usage: "the asset type of the currency pair",
|
|
},
|
|
cli.Int64Flag{
|
|
Name: "interval, i",
|
|
Usage: fmt.Sprintf(klineMessage, "interval"),
|
|
Value: 86400,
|
|
Destination: &candleGranularity,
|
|
},
|
|
cli.StringFlag{
|
|
Name: "start",
|
|
Usage: "<start>",
|
|
Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat),
|
|
Destination: &startTime,
|
|
},
|
|
cli.StringFlag{
|
|
Name: "end",
|
|
Usage: "<end>",
|
|
Value: time.Now().Format(common.SimpleTimeFormat),
|
|
Destination: &endTime,
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "sync",
|
|
Usage: "<true/false>",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "db",
|
|
Usage: "source data from database <true/false>",
|
|
},
|
|
},
|
|
}
|
|
|
|
func getHistoricCandlesExtended(c *cli.Context) error {
|
|
if c.NArg() == 0 && c.NumFlags() == 0 {
|
|
return cli.ShowCommandHelp(c, "gethistoriccandlesextended")
|
|
}
|
|
|
|
var exchangeName string
|
|
if c.IsSet("exchange") {
|
|
exchangeName = c.String("exchange")
|
|
} else {
|
|
exchangeName = c.Args().First()
|
|
}
|
|
if !validExchange(exchangeName) {
|
|
return errInvalidExchange
|
|
}
|
|
|
|
var currencyPair string
|
|
if c.IsSet("pair") {
|
|
currencyPair = c.String("pair")
|
|
} else {
|
|
currencyPair = c.Args().Get(1)
|
|
}
|
|
if !validPair(currencyPair) {
|
|
return errInvalidPair
|
|
}
|
|
|
|
p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var assetType string
|
|
if c.IsSet("asset") {
|
|
assetType = c.String("asset")
|
|
} else {
|
|
assetType = c.Args().Get(2)
|
|
}
|
|
|
|
if !validAsset(assetType) {
|
|
return errInvalidAsset
|
|
}
|
|
|
|
if c.IsSet("interval") {
|
|
candleGranularity = c.Int64("interval")
|
|
} else if c.Args().Get(3) != "" {
|
|
candleGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if !c.IsSet("start") {
|
|
if c.Args().Get(4) != "" {
|
|
startTime = c.Args().Get(4)
|
|
}
|
|
}
|
|
|
|
if !c.IsSet("end") {
|
|
if c.Args().Get(5) != "" {
|
|
endTime = c.Args().Get(5)
|
|
}
|
|
}
|
|
|
|
var sync bool
|
|
if c.IsSet("sync") {
|
|
sync = c.Bool("sync")
|
|
}
|
|
|
|
var db bool
|
|
if c.IsSet("db") {
|
|
db = c.Bool("db")
|
|
}
|
|
|
|
conn, err := setupClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
candleInterval := time.Duration(candleGranularity) * time.Second
|
|
|
|
s, err := time.Parse(common.SimpleTimeFormat, startTime)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid time format for start: %v", err)
|
|
}
|
|
|
|
e, err := time.Parse(common.SimpleTimeFormat, 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")
|
|
}
|
|
|
|
client := gctrpc.NewGoCryptoTraderClient(conn)
|
|
result, err := client.GetHistoricCandles(context.Background(),
|
|
&gctrpc.GetHistoricCandlesRequest{
|
|
Exchange: exchangeName,
|
|
Pair: &gctrpc.CurrencyPair{
|
|
Delimiter: p.Delimiter,
|
|
Base: p.Base.String(),
|
|
Quote: p.Quote.String(),
|
|
},
|
|
AssetType: assetType,
|
|
Start: s.Unix(),
|
|
End: e.Unix(),
|
|
TimeInterval: int64(candleInterval),
|
|
ExRequest: true,
|
|
Sync: sync,
|
|
UseDb: db,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
jsonOutput(result)
|
|
return nil
|
|
}
|