mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-23 07:26:47 +00:00
script: implementation of error insertion on return (#986)
* exchanges/account: shift credentials to account package and segregate funds to keys * merge: fixes * linter: fix * Update exchanges/account/account.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits + protection for string panic * glorious_suggestion: add method for matching keys * linter: fix tests * account: add protected method for credentials minimizing access, display full account details to rpc. * linter: spelling kweeeeeeen * accounts/portfolio: clean/check portfolio code and quickly check balances from change. Add protected method for future matching. * accounts: theres no point in pointerising everything * linter: ok pointerise this then... * exchanges: fix regression add in little notes. * glorious: nits * Update exchanges/account/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/account/credentials_test.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/account/credentials_test.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * gloriously: fix glorious glorious test gloriously * script: initial implementation of error insertion on return * script: make script context aware(ish) and update error handle in examples * script: add tests * script: add syntax highlighting to readme * Update gctscript/vm/vm.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/vm/vm.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/examples/exchange/account_info.gct Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/examples/exchange/cancel_order.gct Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/examples/verbose.gct Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct_test.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * rm: bros * scripts: handle errors in examples when they are going to use the data after fetching * linter: fix rides again * SCOTT_SPELL_CHECK_LINTER: fix * gctscript: fix tests * glorious: niiiiiiiiiiiiits * scriptmodules/gct: standardize runtime errors * Update gctscript/modules/gct/exchange.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/exchange.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/exchange.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/exchange.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update gctscript/modules/gct/gct.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits/reverts * go mod: tidy Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
This commit is contained in:
@@ -59,6 +59,26 @@ func WriteAsCSV(args ...objects.Object) (objects.Object, error) {
|
||||
case indicators.OHLCV:
|
||||
temp, err = convertOHLCV(args[i])
|
||||
front = true
|
||||
case "scriptContext":
|
||||
if target != "" {
|
||||
return nil, fmt.Errorf("filename already set, extra string %v cannot be processed", args[i])
|
||||
}
|
||||
scriptCtx, ok := objects.ToInterface(args[i]).(*Context)
|
||||
if !ok {
|
||||
return nil, common.GetAssertError("*gct.Context", args[i])
|
||||
}
|
||||
|
||||
scriptDetails, ok := scriptCtx.Value["script"]
|
||||
if !ok {
|
||||
return nil, errors.New("no script details")
|
||||
}
|
||||
|
||||
target, ok = objects.ToString(scriptDetails)
|
||||
if !ok {
|
||||
return nil, errors.New("failed to convert incoming output to string")
|
||||
}
|
||||
|
||||
target = processTarget(target)
|
||||
case "string":
|
||||
if target != "" {
|
||||
return nil, fmt.Errorf("filename already set, extra string %v cannot be processed", args[i])
|
||||
@@ -73,26 +93,7 @@ func WriteAsCSV(args ...objects.Object) (objects.Object, error) {
|
||||
return nil, errors.New("script context details not specified")
|
||||
}
|
||||
|
||||
// Removes file transversal
|
||||
target = filepath.Base(target)
|
||||
|
||||
// checks to see if file is context defined, if not it will allow
|
||||
// a client defined filename and append a date, forces the use of
|
||||
// .csv file extension
|
||||
switch {
|
||||
case filepath.Ext(target) != ".csv" && strings.Contains(target, common.GctExt):
|
||||
target += ".csv"
|
||||
case filepath.Ext(target) == ".csv":
|
||||
s := strings.Split(target, ".")
|
||||
if len(s) == 2 {
|
||||
target = s[0] + "-" + strconv.FormatInt(time.Now().UnixNano(), 10) + ".csv"
|
||||
}
|
||||
default:
|
||||
target += "-" + strconv.FormatInt(time.Now().UnixNano(), 10) + ".csv"
|
||||
}
|
||||
|
||||
target = filepath.Join(OutputDir, target)
|
||||
|
||||
target = processTarget(target)
|
||||
default:
|
||||
err = fmt.Errorf("%s type is not handled", args[i].TypeName())
|
||||
}
|
||||
@@ -130,7 +131,7 @@ func WriteAsCSV(args ...objects.Object) (objects.Object, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Infof(log.GCTScriptMgr,
|
||||
log.Debugf(log.GCTScriptMgr,
|
||||
"CSV file successfully saved to: %s",
|
||||
target)
|
||||
return nil, nil
|
||||
@@ -484,3 +485,24 @@ func convertOHLCV(a objects.Object) ([][]string, error) {
|
||||
}
|
||||
return bucket, nil
|
||||
}
|
||||
|
||||
func processTarget(target string) string {
|
||||
// Removes file transversal
|
||||
target = filepath.Base(target)
|
||||
|
||||
// checks to see if file is context defined, if not it will allow
|
||||
// a client defined filename and append a date, forces the use of
|
||||
// .csv file extension
|
||||
switch {
|
||||
case filepath.Ext(target) != ".csv" && strings.Contains(target, common.GctExt):
|
||||
target += ".csv"
|
||||
case filepath.Ext(target) == ".csv":
|
||||
s := strings.Split(target, ".")
|
||||
if len(s) == 2 {
|
||||
target = s[0] + "-" + strconv.FormatInt(time.Now().UnixNano(), 10) + ".csv"
|
||||
}
|
||||
default:
|
||||
target += "-" + strconv.FormatInt(time.Now().UnixNano(), 10) + ".csv"
|
||||
}
|
||||
return filepath.Join(OutputDir, target)
|
||||
}
|
||||
|
||||
39
gctscript/modules/gct/errors.go
Normal file
39
gctscript/modules/gct/errors.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
objects "github.com/d5/tengo/v2"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
)
|
||||
|
||||
const standardFormatting = "%s"
|
||||
|
||||
var (
|
||||
errFormatStringIsEmpty = errors.New("format string is empty")
|
||||
errNoArguments = errors.New("no arguments for error response")
|
||||
)
|
||||
|
||||
// errorResponsef is a helper function to apply error details to a return object
|
||||
// for better script side error handling
|
||||
func errorResponsef(format string, a ...interface{}) (objects.Object, error) {
|
||||
if format == "" {
|
||||
return nil, fmt.Errorf("cannot generate tengo error object %w", errFormatStringIsEmpty)
|
||||
}
|
||||
|
||||
if len(a) == 0 {
|
||||
return nil, fmt.Errorf("cannot generate tengo error object %w", errNoArguments)
|
||||
}
|
||||
|
||||
return &objects.Error{
|
||||
Value: &objects.String{Value: fmt.Sprintf(format, a...)},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func constructRuntimeError(argPosition int, funcName, expectedType string, unexpectedData interface{}) error {
|
||||
return fmt.Errorf("function [%s] argument position [%d] - %w",
|
||||
funcName,
|
||||
argPosition,
|
||||
common.GetAssertError(expectedType, unexpectedData))
|
||||
}
|
||||
38
gctscript/modules/gct/errors_test.go
Normal file
38
gctscript/modules/gct/errors_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
)
|
||||
|
||||
func TestErrorResponse(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := errorResponsef("")
|
||||
if !errors.Is(err, errFormatStringIsEmpty) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, errFormatStringIsEmpty)
|
||||
}
|
||||
|
||||
_, err = errorResponsef("--")
|
||||
if !errors.Is(err, errNoArguments) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, errNoArguments)
|
||||
}
|
||||
|
||||
errResp, err := errorResponsef("error %s", "hello")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if errResp.String() != `error: "error hello"` {
|
||||
t.Fatalf("received: %v but expected: %v", errResp.String(), `error: "error hello"`)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstructRuntimeError(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := constructRuntimeError(0, "", "", nil)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("receieved: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -16,74 +15,93 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||
)
|
||||
|
||||
const (
|
||||
orderbookFunc = "orderbook"
|
||||
tickerFunc = "ticker"
|
||||
exchangesFunc = "exchanges"
|
||||
pairsFunc = "pairs"
|
||||
accountInfoFunc = "accountinfo"
|
||||
depositAddressFunc = "depositaddress"
|
||||
orderQueryFunc = "orderquery"
|
||||
orderCancelFunc = "ordercancel"
|
||||
orderSubmitFunc = "ordersubmit"
|
||||
withdrawCryptoFunc = "withdrawcrypto"
|
||||
withdrawFiatFunc = "withdrawfiat"
|
||||
ohlcvFunc = "ohlcv"
|
||||
)
|
||||
|
||||
var exchangeModule = map[string]objects.Object{
|
||||
"orderbook": &objects.UserFunction{Name: "orderbook", Value: ExchangeOrderbook},
|
||||
"ticker": &objects.UserFunction{Name: "ticker", Value: ExchangeTicker},
|
||||
"exchanges": &objects.UserFunction{Name: "exchanges", Value: ExchangeExchanges},
|
||||
"pairs": &objects.UserFunction{Name: "pairs", Value: ExchangePairs},
|
||||
"accountinfo": &objects.UserFunction{Name: "accountinfo", Value: ExchangeAccountInfo},
|
||||
"depositaddress": &objects.UserFunction{Name: "depositaddress", Value: ExchangeDepositAddress},
|
||||
"orderquery": &objects.UserFunction{Name: "orderquery", Value: ExchangeOrderQuery},
|
||||
"ordercancel": &objects.UserFunction{Name: "ordercancel", Value: ExchangeOrderCancel},
|
||||
"ordersubmit": &objects.UserFunction{Name: "ordersubmit", Value: ExchangeOrderSubmit},
|
||||
"withdrawcrypto": &objects.UserFunction{Name: "withdrawcrypto", Value: ExchangeWithdrawCrypto},
|
||||
"withdrawfiat": &objects.UserFunction{Name: "withdrawfiat", Value: ExchangeWithdrawFiat},
|
||||
"ohlcv": &objects.UserFunction{Name: "ohlcv", Value: exchangeOHLCV},
|
||||
orderbookFunc: &objects.UserFunction{Name: orderbookFunc, Value: ExchangeOrderbook},
|
||||
tickerFunc: &objects.UserFunction{Name: tickerFunc, Value: ExchangeTicker},
|
||||
exchangesFunc: &objects.UserFunction{Name: exchangesFunc, Value: ExchangeExchanges},
|
||||
pairsFunc: &objects.UserFunction{Name: pairsFunc, Value: ExchangePairs},
|
||||
accountInfoFunc: &objects.UserFunction{Name: accountInfoFunc, Value: ExchangeAccountInfo},
|
||||
depositAddressFunc: &objects.UserFunction{Name: depositAddressFunc, Value: ExchangeDepositAddress},
|
||||
orderQueryFunc: &objects.UserFunction{Name: orderQueryFunc, Value: ExchangeOrderQuery},
|
||||
orderCancelFunc: &objects.UserFunction{Name: orderCancelFunc, Value: ExchangeOrderCancel},
|
||||
orderSubmitFunc: &objects.UserFunction{Name: orderSubmitFunc, Value: ExchangeOrderSubmit},
|
||||
withdrawCryptoFunc: &objects.UserFunction{Name: withdrawCryptoFunc, Value: ExchangeWithdrawCrypto},
|
||||
withdrawFiatFunc: &objects.UserFunction{Name: withdrawFiatFunc, Value: ExchangeWithdrawFiat},
|
||||
ohlcvFunc: &objects.UserFunction{Name: ohlcvFunc, Value: exchangeOHLCV},
|
||||
}
|
||||
|
||||
// ExchangeOrderbook returns orderbook for requested exchange & currencypair
|
||||
func ExchangeOrderbook(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 4 {
|
||||
if len(args) != 5 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, orderbookFunc, "*gct.Context", args[0])
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
return nil, constructRuntimeError(2, orderbookFunc, "string", args[1])
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
currencyPair, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
return nil, constructRuntimeError(3, orderbookFunc, "string", args[2])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[3])
|
||||
delimiter, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
return nil, constructRuntimeError(4, orderbookFunc, "string", args[3])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(5, orderbookFunc, "string", args[4])
|
||||
}
|
||||
|
||||
pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
assetType, err := asset.New(assetTypeParam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
ob, err := wrappers.GetWrapper().
|
||||
Orderbook(context.TODO(), exchangeName, pair, assetType)
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
ob, err := wrappers.GetWrapper().Orderbook(ctx, exchangeName, pair, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
var asks, bids objects.Array
|
||||
|
||||
asks := objects.Array{Value: make([]objects.Object, len(ob.Asks))}
|
||||
for x := range ob.Asks {
|
||||
temp := make(map[string]objects.Object, 2)
|
||||
temp["amount"] = &objects.Float{Value: ob.Asks[x].Amount}
|
||||
temp["price"] = &objects.Float{Value: ob.Asks[x].Price}
|
||||
asks.Value = append(asks.Value, &objects.Map{Value: temp})
|
||||
asks.Value[x] = &objects.Map{Value: temp}
|
||||
}
|
||||
|
||||
bids := objects.Array{Value: make([]objects.Object, len(ob.Bids))}
|
||||
for x := range ob.Bids {
|
||||
temp := make(map[string]objects.Object, 2)
|
||||
temp["amount"] = &objects.Float{Value: ob.Bids[x].Amount}
|
||||
temp["price"] = &objects.Float{Value: ob.Bids[x].Price}
|
||||
bids.Value = append(bids.Value, &objects.Map{Value: temp})
|
||||
bids.Value[x] = &objects.Map{Value: temp}
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 5)
|
||||
@@ -93,32 +111,35 @@ func ExchangeOrderbook(args ...objects.Object) (objects.Object, error) {
|
||||
data["bids"] = &bids
|
||||
data["asset"] = &objects.String{Value: ob.Asset.String()}
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
return &objects.Map{Value: data}, nil
|
||||
}
|
||||
|
||||
// ExchangeTicker returns ticker data for requested exchange and currency pair
|
||||
func ExchangeTicker(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 4 {
|
||||
if len(args) != 5 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, tickerFunc, "*gct.Context", args[0])
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
return nil, constructRuntimeError(2, tickerFunc, "string", args[1])
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
currencyPair, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
return nil, constructRuntimeError(3, tickerFunc, "string", args[2])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[3])
|
||||
delimiter, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
return nil, constructRuntimeError(4, tickerFunc, "string", args[3])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(5, tickerFunc, "string", args[4])
|
||||
}
|
||||
|
||||
pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
@@ -128,13 +149,13 @@ func ExchangeTicker(args ...objects.Object) (objects.Object, error) {
|
||||
|
||||
assetType, err := asset.New(assetTypeParam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
tx, err := wrappers.GetWrapper().
|
||||
Ticker(context.TODO(), exchangeName, pair, assetType)
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
tx, err := wrappers.GetWrapper().Ticker(ctx, exchangeName, pair, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 14)
|
||||
@@ -166,13 +187,15 @@ func ExchangeExchanges(args ...objects.Object) (objects.Object, error) {
|
||||
|
||||
enabledOnly, ok := objects.ToBool(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, enabledOnly)
|
||||
return nil, constructRuntimeError(1, exchangesFunc, "bool", args[0])
|
||||
}
|
||||
rtnValue := wrappers.GetWrapper().Exchanges(enabledOnly)
|
||||
|
||||
r := objects.Array{}
|
||||
r := objects.Array{
|
||||
Value: make([]objects.Object, len(rtnValue)),
|
||||
}
|
||||
for x := range rtnValue {
|
||||
r.Value = append(r.Value, &objects.String{Value: rtnValue[x]})
|
||||
r.Value[x] = &objects.String{Value: rtnValue[x]}
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
@@ -186,56 +209,64 @@ func ExchangePairs(args ...objects.Object) (objects.Object, error) {
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, pairsFunc, "string", args[0])
|
||||
}
|
||||
enabledOnly, ok := objects.ToBool(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, enabledOnly)
|
||||
return nil, constructRuntimeError(2, pairsFunc, "bool", args[1])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
return nil, constructRuntimeError(3, pairsFunc, "string", args[2])
|
||||
}
|
||||
assetType, err := asset.New(assetTypeParam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
rtnValue, err := wrappers.GetWrapper().Pairs(exchangeName, enabledOnly, assetType)
|
||||
pairs, err := wrappers.GetWrapper().Pairs(exchangeName, enabledOnly, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
r := objects.Array{}
|
||||
pairs := *(*[]currency.Pair)(rtnValue)
|
||||
for x := range pairs {
|
||||
r.Value = append(r.Value, &objects.String{Value: pairs[x].String()})
|
||||
r := objects.Array{
|
||||
Value: make([]objects.Object, len(*pairs)),
|
||||
}
|
||||
|
||||
for x := range *pairs {
|
||||
r.Value[x] = &objects.String{Value: (*pairs)[x].String()}
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// ExchangeAccountInfo returns account information for requested exchange
|
||||
func ExchangeAccountInfo(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 2 {
|
||||
if len(args) != 3 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, accountInfoFunc, "*gct.Context", args[0])
|
||||
}
|
||||
assetString, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetString)
|
||||
return nil, constructRuntimeError(2, accountInfoFunc, "string", args[1])
|
||||
}
|
||||
assetString, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(3, accountInfoFunc, "string", args[2])
|
||||
}
|
||||
assetType, err := asset.New(assetString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
rtnValue, err := wrappers.GetWrapper().
|
||||
AccountInformation(context.TODO(), exchangeName, assetType)
|
||||
AccountInformation(ctx, exchangeName, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
var funds objects.Array
|
||||
@@ -252,62 +283,65 @@ func ExchangeAccountInfo(args ...objects.Object) (objects.Object, error) {
|
||||
data := make(map[string]objects.Object, 2)
|
||||
data["exchange"] = &objects.String{Value: rtnValue.Exchange}
|
||||
data["currencies"] = &funds
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
return &objects.Map{Value: data}, nil
|
||||
}
|
||||
|
||||
// ExchangeOrderQuery query order on exchange
|
||||
func ExchangeOrderQuery(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) < 2 {
|
||||
if len(args) < 3 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, orderQueryFunc, "*gct.Context", args[0])
|
||||
}
|
||||
orderID, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderID)
|
||||
return nil, constructRuntimeError(2, orderQueryFunc, "string", args[1])
|
||||
}
|
||||
orderID, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(3, orderQueryFunc, "string", args[2])
|
||||
}
|
||||
|
||||
var pair currency.Pair
|
||||
assetTypeString := asset.Spot.String()
|
||||
|
||||
switch len(args) {
|
||||
case 4:
|
||||
assetTypeString, ok = objects.ToString(args[3])
|
||||
case 5:
|
||||
assetTypeString, ok = objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeString)
|
||||
return nil, constructRuntimeError(5, orderQueryFunc, "string", args[4])
|
||||
}
|
||||
fallthrough
|
||||
case 3:
|
||||
currencyPairString, isOk := objects.ToString(args[2])
|
||||
case 4:
|
||||
currencyPairString, isOk := objects.ToString(args[3])
|
||||
if !isOk {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPairString)
|
||||
return nil, constructRuntimeError(4, orderQueryFunc, "string", args[3])
|
||||
}
|
||||
|
||||
var err error
|
||||
pair, err = currency.NewPairFromString(currencyPairString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPairString)
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
}
|
||||
|
||||
assetType, err := asset.New(assetTypeString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
orderDetails, err := wrappers.GetWrapper().
|
||||
QueryOrder(context.TODO(), exchangeName, orderID, pair, assetType)
|
||||
QueryOrder(ctx, exchangeName, orderID, pair, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
var tradeHistory objects.Array
|
||||
tradeHistory.Value = make([]objects.Object, len(orderDetails.Trades))
|
||||
for x := range orderDetails.Trades {
|
||||
temp := make(map[string]objects.Object, 7)
|
||||
temp["timestamp"] = &objects.Time{Value: orderDetails.Trades[x].Timestamp}
|
||||
@@ -317,7 +351,7 @@ func ExchangeOrderQuery(args ...objects.Object) (objects.Object, error) {
|
||||
temp["type"] = &objects.String{Value: orderDetails.Trades[x].Type.String()}
|
||||
temp["side"] = &objects.String{Value: orderDetails.Trades[x].Side.String()}
|
||||
temp["description"] = &objects.String{Value: orderDetails.Trades[x].Description}
|
||||
tradeHistory.Value = append(tradeHistory.Value, &objects.Map{Value: temp})
|
||||
tradeHistory.Value[x] = &objects.Map{Value: temp}
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 14)
|
||||
@@ -336,63 +370,65 @@ func ExchangeOrderQuery(args ...objects.Object) (objects.Object, error) {
|
||||
data["status"] = &objects.String{Value: orderDetails.Status.String()}
|
||||
data["trades"] = &tradeHistory
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
return &objects.Map{Value: data}, nil
|
||||
}
|
||||
|
||||
// ExchangeOrderCancel cancels order on requested exchange
|
||||
func ExchangeOrderCancel(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) < 2 || len(args) > 4 {
|
||||
if len(args) < 3 || len(args) > 5 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, orderCancelFunc, "*gct.Context", args[0])
|
||||
}
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(2, orderCancelFunc, "string", args[1])
|
||||
}
|
||||
if exchangeName == "" {
|
||||
return nil, fmt.Errorf(ErrEmptyParameter, "exchange name")
|
||||
}
|
||||
var orderID string
|
||||
orderID, ok = objects.ToString(args[1])
|
||||
orderID, ok = objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderID)
|
||||
return nil, constructRuntimeError(3, orderCancelFunc, "string", args[2])
|
||||
}
|
||||
if orderID == "" {
|
||||
return nil, fmt.Errorf(ErrEmptyParameter, "orderID")
|
||||
}
|
||||
var err error
|
||||
var cp currency.Pair
|
||||
if len(args) > 2 {
|
||||
if len(args) > 3 {
|
||||
var currencyPair string
|
||||
currencyPair, ok = objects.ToString(args[2])
|
||||
currencyPair, ok = objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
return nil, constructRuntimeError(4, orderCancelFunc, "string", args[3])
|
||||
}
|
||||
cp, err = currency.NewPairFromString(currencyPair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
}
|
||||
var a asset.Item
|
||||
if len(args) > 3 {
|
||||
if len(args) > 4 {
|
||||
var assetType string
|
||||
assetType, ok = objects.ToString(args[3])
|
||||
assetType, ok = objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetType)
|
||||
return nil, constructRuntimeError(5, orderCancelFunc, "string", args[4])
|
||||
}
|
||||
a, err = asset.New(assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
}
|
||||
|
||||
var isCancelled bool
|
||||
isCancelled, err = wrappers.GetWrapper().
|
||||
CancelOrder(context.TODO(), exchangeName, orderID, cp, a)
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
isCancelled, err := wrappers.GetWrapper().
|
||||
CancelOrder(ctx, exchangeName, orderID, cp, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
if isCancelled {
|
||||
@@ -403,63 +439,69 @@ func ExchangeOrderCancel(args ...objects.Object) (objects.Object, error) {
|
||||
|
||||
// ExchangeOrderSubmit submit order on exchange
|
||||
func ExchangeOrderSubmit(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 9 {
|
||||
if len(args) != 10 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, orderSubmitFunc, "*gct.Context", args[0])
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
return nil, constructRuntimeError(2, orderSubmitFunc, "string", args[1])
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
currencyPair, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
return nil, constructRuntimeError(3, orderSubmitFunc, "string", args[2])
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(4, orderSubmitFunc, "string", args[3])
|
||||
}
|
||||
orderType, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(5, orderSubmitFunc, "string", args[4])
|
||||
}
|
||||
orderSide, ok := objects.ToString(args[5])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(6, orderSubmitFunc, "string", args[5])
|
||||
}
|
||||
orderPrice, ok := objects.ToFloat64(args[6])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(7, orderSubmitFunc, "float64", args[6])
|
||||
}
|
||||
orderAmount, ok := objects.ToFloat64(args[7])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(8, orderSubmitFunc, "float64", args[7])
|
||||
}
|
||||
orderClientID, ok := objects.ToString(args[8])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(9, orderSubmitFunc, "string", args[8])
|
||||
}
|
||||
assetType, ok := objects.ToString(args[9])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(10, orderSubmitFunc, "string", args[9])
|
||||
}
|
||||
|
||||
pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orderType, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderType)
|
||||
}
|
||||
orderSide, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderSide)
|
||||
}
|
||||
orderPrice, ok := objects.ToFloat64(args[5])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderPrice)
|
||||
}
|
||||
orderAmount, ok := objects.ToFloat64(args[6])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderAmount)
|
||||
}
|
||||
orderClientID, ok := objects.ToString(args[7])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderClientID)
|
||||
}
|
||||
assetType, ok := objects.ToString(args[8])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, orderClientID)
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
a, err := asset.New(assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
side, err := order.StringToOrderSide(orderSide)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
oType, err := order.StringToOrderType(orderType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
tempSubmit := &order.Submit{
|
||||
@@ -473,18 +515,17 @@ func ExchangeOrderSubmit(args ...objects.Object) (objects.Object, error) {
|
||||
Exchange: exchangeName,
|
||||
}
|
||||
|
||||
rtn, err := wrappers.GetWrapper().SubmitOrder(context.TODO(), tempSubmit)
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
rtn, err := wrappers.GetWrapper().SubmitOrder(ctx, tempSubmit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 2)
|
||||
data["orderid"] = &objects.String{Value: rtn.OrderID}
|
||||
data["isorderplaced"] = objects.TrueValue
|
||||
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
return &objects.Map{Value: data}, nil
|
||||
}
|
||||
|
||||
// ExchangeDepositAddress returns deposit address (if supported by exchange)
|
||||
@@ -495,65 +536,67 @@ func ExchangeDepositAddress(args ...objects.Object) (objects.Object, error) {
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, depositAddressFunc, "string", args[0])
|
||||
}
|
||||
currencyCode, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyCode)
|
||||
return nil, constructRuntimeError(2, depositAddressFunc, "string", args[1])
|
||||
}
|
||||
chain, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, chain)
|
||||
return nil, constructRuntimeError(3, depositAddressFunc, "string", args[2])
|
||||
}
|
||||
|
||||
currCode := currency.NewCode(currencyCode)
|
||||
|
||||
rtn, err := wrappers.GetWrapper().DepositAddress(exchangeName, chain, currCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
data := make(map[string]objects.Object, 2)
|
||||
data["address"] = &objects.String{Value: rtn.Address}
|
||||
data["tag"] = &objects.String{Value: rtn.Tag}
|
||||
return &objects.Map{
|
||||
Value: data,
|
||||
}, nil
|
||||
return &objects.Map{Value: data}, nil
|
||||
}
|
||||
|
||||
// ExchangeWithdrawCrypto submit request to withdraw crypto assets
|
||||
func ExchangeWithdrawCrypto(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 7 {
|
||||
if len(args) != 8 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, withdrawCryptoFunc, "*gct.Context", args[0])
|
||||
}
|
||||
cur, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, cur)
|
||||
return nil, constructRuntimeError(2, withdrawCryptoFunc, "string", args[1])
|
||||
}
|
||||
address, ok := objects.ToString(args[2])
|
||||
cur, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, address)
|
||||
return nil, constructRuntimeError(3, withdrawCryptoFunc, "string", args[2])
|
||||
}
|
||||
addressTag, ok := objects.ToString(args[3])
|
||||
address, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, addressTag)
|
||||
return nil, constructRuntimeError(4, withdrawCryptoFunc, "string", args[3])
|
||||
}
|
||||
amount, ok := objects.ToFloat64(args[4])
|
||||
addressTag, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, amount)
|
||||
return nil, constructRuntimeError(5, withdrawCryptoFunc, "string", args[4])
|
||||
}
|
||||
feeAmount, ok := objects.ToFloat64(args[5])
|
||||
amount, ok := objects.ToFloat64(args[5])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, feeAmount)
|
||||
return nil, constructRuntimeError(6, withdrawCryptoFunc, "float64", args[5])
|
||||
}
|
||||
description, ok := objects.ToString(args[6])
|
||||
feeAmount, ok := objects.ToFloat64(args[6])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, description)
|
||||
return nil, constructRuntimeError(7, withdrawCryptoFunc, "float64", args[6])
|
||||
}
|
||||
description, ok := objects.ToString(args[7])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(8, withdrawCryptoFunc, "string", args[7])
|
||||
}
|
||||
|
||||
withdrawRequest := &withdraw.Request{
|
||||
@@ -568,10 +611,10 @@ func ExchangeWithdrawCrypto(args ...objects.Object) (objects.Object, error) {
|
||||
Amount: amount,
|
||||
}
|
||||
|
||||
rtn, err := wrappers.GetWrapper().
|
||||
WithdrawalCryptoFunds(context.TODO(), withdrawRequest)
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
rtn, err := wrappers.GetWrapper().WithdrawalCryptoFunds(ctx, withdrawRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
return &objects.String{Value: rtn}, nil
|
||||
@@ -579,29 +622,33 @@ func ExchangeWithdrawCrypto(args ...objects.Object) (objects.Object, error) {
|
||||
|
||||
// ExchangeWithdrawFiat submit request to withdraw fiat assets
|
||||
func ExchangeWithdrawFiat(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 5 {
|
||||
if len(args) != 6 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, withdrawFiatFunc, "*gct.Context", args[0])
|
||||
}
|
||||
cur, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, cur)
|
||||
return nil, constructRuntimeError(2, withdrawFiatFunc, "string", args[1])
|
||||
}
|
||||
description, ok := objects.ToString(args[2])
|
||||
cur, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, description)
|
||||
return nil, constructRuntimeError(3, withdrawFiatFunc, "string", args[2])
|
||||
}
|
||||
amount, ok := objects.ToFloat64(args[3])
|
||||
description, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, amount)
|
||||
return nil, constructRuntimeError(4, withdrawFiatFunc, "string", args[3])
|
||||
}
|
||||
bankAccountID, ok := objects.ToString(args[4])
|
||||
amount, ok := objects.ToFloat64(args[4])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, bankAccountID)
|
||||
return nil, constructRuntimeError(5, withdrawFiatFunc, "float64", args[4])
|
||||
}
|
||||
bankAccountID, ok := objects.ToString(args[5])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(6, withdrawFiatFunc, "string", args[5])
|
||||
}
|
||||
|
||||
withdrawRequest := &withdraw.Request{
|
||||
@@ -611,10 +658,11 @@ func ExchangeWithdrawFiat(args ...objects.Object) (objects.Object, error) {
|
||||
Amount: amount,
|
||||
}
|
||||
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
rtn, err := wrappers.GetWrapper().
|
||||
WithdrawalFiatFunds(context.TODO(), bankAccountID, withdrawRequest)
|
||||
WithdrawalFiatFunds(ctx, bankAccountID, withdrawRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
return &objects.String{Value: rtn}, nil
|
||||
@@ -631,56 +679,61 @@ func (o *OHLCV) TypeName() string {
|
||||
}
|
||||
|
||||
func exchangeOHLCV(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 7 {
|
||||
if len(args) != 8 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
exchangeName, ok := objects.ToString(args[0])
|
||||
scriptCtx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, exchangeName)
|
||||
return nil, constructRuntimeError(1, ohlcvFunc, "*gct.Context", args[0])
|
||||
}
|
||||
currencyPair, ok := objects.ToString(args[1])
|
||||
exchangeName, ok := objects.ToString(args[1])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, currencyPair)
|
||||
return nil, constructRuntimeError(2, ohlcvFunc, "string", args[1])
|
||||
}
|
||||
delimiter, ok := objects.ToString(args[2])
|
||||
currencyPair, ok := objects.ToString(args[2])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, delimiter)
|
||||
return nil, constructRuntimeError(3, ohlcvFunc, "string", args[2])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[3])
|
||||
delimiter, ok := objects.ToString(args[3])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
|
||||
return nil, constructRuntimeError(4, ohlcvFunc, "string", args[3])
|
||||
}
|
||||
assetTypeParam, ok := objects.ToString(args[4])
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(5, ohlcvFunc, "string", args[4])
|
||||
}
|
||||
|
||||
startTime, ok := objects.ToTime(args[4])
|
||||
startTime, ok := objects.ToTime(args[5])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, startTime)
|
||||
return nil, constructRuntimeError(6, ohlcvFunc, "string", args[5])
|
||||
}
|
||||
|
||||
endTime, ok := objects.ToTime(args[5])
|
||||
endTime, ok := objects.ToTime(args[6])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, endTime)
|
||||
return nil, constructRuntimeError(7, ohlcvFunc, "time.Time", args[6])
|
||||
}
|
||||
|
||||
intervalStr, ok := objects.ToString(args[6])
|
||||
intervalStr, ok := objects.ToString(args[7])
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(ErrParameterConvertFailed, endTime)
|
||||
return nil, constructRuntimeError(8, ohlcvFunc, "string", args[7])
|
||||
}
|
||||
interval, err := parseInterval(intervalStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
assetType, err := asset.New(assetTypeParam)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
ctx := processScriptContext(scriptCtx)
|
||||
ret, err := wrappers.GetWrapper().
|
||||
OHLCV(context.TODO(),
|
||||
OHLCV(ctx,
|
||||
exchangeName,
|
||||
pair,
|
||||
assetType,
|
||||
@@ -688,21 +741,21 @@ func exchangeOHLCV(args ...objects.Object) (objects.Object, error) {
|
||||
endTime,
|
||||
kline.Interval(interval))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errorResponsef(standardFormatting, err)
|
||||
}
|
||||
|
||||
var candles objects.Array
|
||||
candles := objects.Array{Value: make([]objects.Object, len(ret.Candles))}
|
||||
for x := range ret.Candles {
|
||||
candle := &objects.Array{}
|
||||
candle.Value = append(candle.Value, &objects.Int{Value: ret.Candles[x].Time.Unix()},
|
||||
&objects.Float{Value: ret.Candles[x].Open},
|
||||
&objects.Float{Value: ret.Candles[x].High},
|
||||
&objects.Float{Value: ret.Candles[x].Low},
|
||||
&objects.Float{Value: ret.Candles[x].Close},
|
||||
&objects.Float{Value: ret.Candles[x].Volume},
|
||||
)
|
||||
|
||||
candles.Value = append(candles.Value, candle)
|
||||
candles.Value[x] = &objects.Array{
|
||||
Value: []objects.Object{
|
||||
&objects.Int{Value: ret.Candles[x].Time.Unix()},
|
||||
&objects.Float{Value: ret.Candles[x].Open},
|
||||
&objects.Float{Value: ret.Candles[x].High},
|
||||
&objects.Float{Value: ret.Candles[x].Low},
|
||||
&objects.Float{Value: ret.Candles[x].Close},
|
||||
&objects.Float{Value: ret.Candles[x].Volume},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
retValue := make(map[string]objects.Object, 5)
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
package gct
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
objects "github.com/d5/tengo/v2"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
const (
|
||||
setVerboseFunc = "set_verbose"
|
||||
setAccountFunc = "set_account"
|
||||
setSubAccountFunc = "set_sub_account"
|
||||
)
|
||||
|
||||
var globalModules = map[string]objects.Object{
|
||||
setVerboseFunc: &objects.UserFunction{Name: setVerboseFunc, Value: setVerbose},
|
||||
setAccountFunc: &objects.UserFunction{Name: setAccountFunc, Value: setAccount},
|
||||
setSubAccountFunc: &objects.UserFunction{Name: setSubAccountFunc, Value: setSubAccount},
|
||||
}
|
||||
|
||||
// AllModuleNames returns a list of all default module names.
|
||||
func AllModuleNames() []string {
|
||||
names := make([]string, 0, len(Modules))
|
||||
@@ -8,3 +28,183 @@ func AllModuleNames() []string {
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// setVerbose specifically sets verbosity for http rest requests for this script
|
||||
// Params: scriptCTX
|
||||
func setVerbose(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
ctx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(1, setVerboseFunc, "*gct.Context", args[0])
|
||||
}
|
||||
if ctx.Value == nil {
|
||||
ctx.Value = make(map[string]objects.Object)
|
||||
}
|
||||
ctx.Value["verbose"] = objects.TrueValue
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
// setAccount sets account details which overrides default credentials for
|
||||
// script account management, api key and secret are required.
|
||||
// Params: scriptCTX, apiKey, apiSecret, subAccount, clientID, PEMKey, OneTimePassword string
|
||||
func setAccount(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) < 3 || len(args) > 7 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
ctx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(1, setAccountFunc, "*gct.Context", args[0])
|
||||
}
|
||||
|
||||
apikey, ok := objects.ToInterface(args[1]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(2, setAccountFunc, "string", args[1])
|
||||
}
|
||||
|
||||
if ctx.Value == nil {
|
||||
ctx.Value = make(map[string]objects.Object)
|
||||
}
|
||||
|
||||
ctx.Value["apikey"] = &objects.String{Value: apikey}
|
||||
|
||||
apisecret, ok := objects.ToInterface(args[2]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(3, setAccountFunc, "string", args[2])
|
||||
}
|
||||
|
||||
ctx.Value["apisecret"] = &objects.String{Value: apisecret}
|
||||
|
||||
if len(args) > 3 {
|
||||
var subaccount string
|
||||
subaccount, ok = objects.ToInterface(args[3]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(4, setAccountFunc, "string", args[3])
|
||||
}
|
||||
|
||||
if subaccount != "" {
|
||||
ctx.Value["subaccount"] = &objects.String{Value: subaccount}
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) > 4 {
|
||||
var clientID string
|
||||
clientID, ok = objects.ToInterface(args[4]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(5, setAccountFunc, "string", args[4])
|
||||
}
|
||||
if clientID != "" {
|
||||
ctx.Value["clientid"] = &objects.String{Value: clientID}
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) > 5 {
|
||||
var pemKey string
|
||||
pemKey, ok = objects.ToInterface(args[5]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(6, setAccountFunc, "string", args[5])
|
||||
}
|
||||
if pemKey != "" {
|
||||
ctx.Value["pemkey"] = &objects.String{Value: pemKey}
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) > 5 {
|
||||
var oneTimePassword string
|
||||
oneTimePassword, ok = objects.ToInterface(args[6]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(7, setAccountFunc, "string", args[6])
|
||||
}
|
||||
if oneTimePassword != "" {
|
||||
ctx.Value["otp"] = &objects.String{Value: oneTimePassword}
|
||||
}
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
// setSubAccount sets sub account details which overrides default credential
|
||||
// sub account but uses the same configured api keys.
|
||||
// Params: scriptCTX, subAccount string
|
||||
func setSubAccount(args ...objects.Object) (objects.Object, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, objects.ErrWrongNumArguments
|
||||
}
|
||||
|
||||
ctx, ok := objects.ToInterface(args[0]).(*Context)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(1, setSubAccountFunc, "*gct.Context", args[0])
|
||||
}
|
||||
|
||||
sub, ok := objects.ToInterface(args[1]).(string)
|
||||
if !ok {
|
||||
return nil, constructRuntimeError(2, setSubAccountFunc, "string", args[1])
|
||||
}
|
||||
|
||||
if ctx.Value == nil {
|
||||
ctx.Value = make(map[string]objects.Object)
|
||||
}
|
||||
|
||||
ctx.Value["subaccount"] = &objects.String{Value: sub}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func processScriptContext(scriptCtx *Context) context.Context {
|
||||
ctx := context.Background()
|
||||
if scriptCtx == nil || scriptCtx.Value == nil {
|
||||
return ctx
|
||||
}
|
||||
var object objects.Object
|
||||
if object = scriptCtx.Value["verbose"]; object != nil {
|
||||
ctx = request.WithVerbose(ctx)
|
||||
}
|
||||
|
||||
if object = scriptCtx.Value["apikey"]; object != nil {
|
||||
key, _ := objects.ToString(object)
|
||||
|
||||
var secret string
|
||||
if object = scriptCtx.Value["apisecret"]; object != nil {
|
||||
secret, _ = objects.ToString(object)
|
||||
}
|
||||
|
||||
var subAccount string
|
||||
if object = scriptCtx.Value["subaccount"]; object != nil {
|
||||
subAccount, _ = objects.ToString(object)
|
||||
}
|
||||
|
||||
var clientID string
|
||||
if object = scriptCtx.Value["clientid"]; object != nil {
|
||||
clientID, _ = objects.ToString(object)
|
||||
}
|
||||
|
||||
var pemKey string
|
||||
if object = scriptCtx.Value["pemkey"]; object != nil {
|
||||
pemKey, _ = objects.ToString(object)
|
||||
}
|
||||
|
||||
var otp string
|
||||
if object = scriptCtx.Value["otp"]; object != nil {
|
||||
otp, _ = objects.ToString(object)
|
||||
}
|
||||
|
||||
ctx = account.DeployCredentialsToContext(ctx, &account.Credentials{
|
||||
Key: key,
|
||||
Secret: secret,
|
||||
SubAccount: subAccount,
|
||||
ClientID: clientID,
|
||||
PEMKey: pemKey,
|
||||
OneTimePassword: otp,
|
||||
})
|
||||
} else if object = scriptCtx.Value["subaccount"]; object != nil {
|
||||
subAccount, _ := objects.ToString(object)
|
||||
ctx = account.DeploySubAccountOverrideToContext(ctx, subAccount)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// TypeName returns the name of the custom type.
|
||||
func (c *Context) TypeName() string {
|
||||
return "scriptContext"
|
||||
}
|
||||
|
||||
@@ -8,12 +8,15 @@ import (
|
||||
"time"
|
||||
|
||||
objects "github.com/d5/tengo/v2"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/modules"
|
||||
"github.com/thrasher-corp/gocryptotrader/gctscript/wrappers/validator"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = &Context{}
|
||||
exch = &objects.String{
|
||||
Value: "BTC Markets",
|
||||
}
|
||||
@@ -48,7 +51,7 @@ func TestMain(m *testing.M) {
|
||||
|
||||
func TestExchangeOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := ExchangeOrderbook(exch, currencyPair, delimiter, assetType)
|
||||
_, err := ExchangeOrderbook(ctx, exch, currencyPair, delimiter, assetType)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -66,7 +69,7 @@ func TestExchangeOrderbook(t *testing.T) {
|
||||
|
||||
func TestExchangeTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := ExchangeTicker(exch, currencyPair, delimiter, assetType)
|
||||
_, err := ExchangeTicker(ctx, exch, currencyPair, delimiter, assetType)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -133,12 +136,12 @@ func TestAccountInfo(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeAccountInfo(exch, assetType)
|
||||
_, err = ExchangeAccountInfo(ctx, exch, assetType)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeAccountInfo(exchError, assetType)
|
||||
_, err = ExchangeAccountInfo(ctx, exchError, assetType)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -152,12 +155,12 @@ func TestExchangeOrderQuery(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderQuery(exch, orderID)
|
||||
_, err = ExchangeOrderQuery(ctx, exch, orderID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderQuery(exchError, orderID)
|
||||
_, err = ExchangeOrderQuery(ctx, exchError, orderID)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -180,17 +183,17 @@ func TestExchangeOrderCancel(t *testing.T) {
|
||||
t.Error("expecting error")
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderCancel(exch, orderID)
|
||||
_, err = ExchangeOrderCancel(ctx, exch, orderID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderCancel(exch, orderID, currencyPair)
|
||||
_, err = ExchangeOrderCancel(ctx, exch, orderID, currencyPair)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderCancel(exch, orderID, currencyPair, assetType)
|
||||
_, err = ExchangeOrderCancel(ctx, exch, orderID, currencyPair, assetType)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -209,19 +212,19 @@ func TestExchangeOrderSubmit(t *testing.T) {
|
||||
orderAmount := &objects.Float{Value: 1}
|
||||
orderAsset := &objects.String{Value: asset.Spot.String()}
|
||||
|
||||
_, err = ExchangeOrderSubmit(exch, currencyPair, delimiter,
|
||||
_, err = ExchangeOrderSubmit(ctx, exch, currencyPair, delimiter,
|
||||
orderType, orderSide, orderPrice, orderAmount, orderID, orderAsset)
|
||||
if err != nil && !errors.Is(err, errTestFailed) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderSubmit(exch, currencyPair, delimiter,
|
||||
_, err = ExchangeOrderSubmit(ctx, exch, currencyPair, delimiter,
|
||||
orderType, orderSide, orderPrice, orderAmount, orderID, orderAsset)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = ExchangeOrderSubmit(objects.TrueValue, currencyPair, delimiter,
|
||||
_, err = ExchangeOrderSubmit(ctx, objects.TrueValue, currencyPair, delimiter,
|
||||
orderType, orderSide, orderPrice, orderAmount, orderID, orderAsset)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -269,7 +272,7 @@ func TestExchangeWithdrawCrypto(t *testing.T) {
|
||||
address := &objects.String{Value: "0xTHISISALEGITBTCADDRESSS"}
|
||||
amount := &objects.Float{Value: 1.0}
|
||||
|
||||
_, err = ExchangeWithdrawCrypto(exch, currCode, address, address, amount, amount, desc)
|
||||
_, err = ExchangeWithdrawCrypto(ctx, exch, currCode, address, address, amount, amount, desc)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -286,7 +289,7 @@ func TestExchangeWithdrawFiat(t *testing.T) {
|
||||
desc := &objects.String{Value: "Hello"}
|
||||
amount := &objects.Float{Value: 1.0}
|
||||
bankID := &objects.String{Value: "test-bank-01"}
|
||||
_, err = ExchangeWithdrawFiat(exch, currCode, desc, amount, bankID)
|
||||
_, err = ExchangeWithdrawFiat(ctx, exch, currCode, desc, amount, bankID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -333,3 +336,193 @@ func TestParseInterval(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetVerbose(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := setVerbose()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, objects.ErrWrongNumArguments)
|
||||
}
|
||||
|
||||
_, err = setVerbose(objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
resp, err := setVerbose(&Context{})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
ctx, ok := objects.ToInterface(resp).(*Context)
|
||||
if !ok {
|
||||
t.Fatal("should be of type *Context")
|
||||
}
|
||||
|
||||
val := ctx.Value["verbose"]
|
||||
if val.String() != objects.TrueValue.String() {
|
||||
t.Fatal("should contain verbose string in map")
|
||||
}
|
||||
}
|
||||
|
||||
var dummyStr = &objects.String{Value: "xxxx"}
|
||||
|
||||
func TestSetAccount(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := setAccount()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, objects.ErrWrongNumArguments)
|
||||
}
|
||||
|
||||
_, err = setAccount(objects.TrueValue, objects.TrueValue, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setAccount(&Context{}, objects.TrueValue, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setAccount(&Context{}, dummyStr, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setAccount(&Context{}, dummyStr, dummyStr, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setAccount(&Context{}, dummyStr, dummyStr, dummyStr, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setAccount(&Context{}, dummyStr, dummyStr, dummyStr, dummyStr, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setAccount(&Context{}, dummyStr, dummyStr, dummyStr, dummyStr, dummyStr, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
resp, err := setAccount(&Context{}, dummyStr, dummyStr, dummyStr, dummyStr, dummyStr, dummyStr)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
ctx, ok := objects.ToInterface(resp).(*Context)
|
||||
if !ok {
|
||||
t.Fatal("should be of type *Context")
|
||||
}
|
||||
|
||||
val := ctx.Value["apikey"]
|
||||
if val.String() != dummyStr.String() {
|
||||
t.Fatal("should contain apikey string in map")
|
||||
}
|
||||
val = ctx.Value["apisecret"]
|
||||
if val.String() != dummyStr.String() {
|
||||
t.Fatal("should contain apisecret string in map")
|
||||
}
|
||||
val = ctx.Value["subaccount"]
|
||||
if val.String() != dummyStr.String() {
|
||||
t.Fatal("should contain subaccount string in map")
|
||||
}
|
||||
val = ctx.Value["clientid"]
|
||||
if val.String() != dummyStr.String() {
|
||||
t.Fatal("should contain clientid string in map")
|
||||
}
|
||||
val = ctx.Value["pemkey"]
|
||||
if val.String() != dummyStr.String() {
|
||||
t.Fatal("should contain pemkey string in map")
|
||||
}
|
||||
val = ctx.Value["otp"]
|
||||
if val.String() != dummyStr.String() {
|
||||
t.Fatal("should contain otp string in map")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetSubAccount(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := setSubAccount()
|
||||
if !errors.Is(err, objects.ErrWrongNumArguments) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, objects.ErrWrongNumArguments)
|
||||
}
|
||||
|
||||
_, err = setSubAccount(objects.TrueValue, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
_, err = setSubAccount(&Context{}, objects.TrueValue)
|
||||
if !errors.Is(err, common.ErrTypeAssertFailure) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, common.ErrTypeAssertFailure)
|
||||
}
|
||||
|
||||
subby, err := setSubAccount(&Context{}, dummyStr)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
ctxWSubAcc, ok := subby.(*Context)
|
||||
if !ok {
|
||||
t.Fatal("unexpected type returned")
|
||||
}
|
||||
|
||||
if ctxWSubAcc.Value["subaccount"].String() != dummyStr.String() {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", ctxWSubAcc.Value["subaccount"].String(), dummyStr.String())
|
||||
}
|
||||
|
||||
// Deploy override to actual context.Context type
|
||||
ctx := processScriptContext(ctxWSubAcc)
|
||||
if ctx == nil {
|
||||
t.Fatal("should not be nil")
|
||||
}
|
||||
|
||||
subaccount, ok := ctx.Value(account.ContextSubAccountFlag).(string)
|
||||
if !ok {
|
||||
t.Fatal("wrong type")
|
||||
}
|
||||
|
||||
if subaccount != dummyStr.String()[1:5] {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", subaccount, dummyStr.String()[1:5])
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessScriptContext(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := processScriptContext(nil)
|
||||
if ctx == nil {
|
||||
t.Fatal("should not be nil")
|
||||
}
|
||||
|
||||
fromScript, err := setAccount(&Context{}, dummyStr, dummyStr, dummyStr, dummyStr, dummyStr, dummyStr)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
fromScript, err = setVerbose(fromScript)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
|
||||
scriptCTX, ok := objects.ToInterface(fromScript).(*Context)
|
||||
if !ok {
|
||||
t.Fatal("should assert correctly")
|
||||
}
|
||||
|
||||
ctx = processScriptContext(scriptCTX)
|
||||
if ctx == nil {
|
||||
t.Fatal("should not be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestScriptCredentialTypeName(t *testing.T) {
|
||||
t.Parallel()
|
||||
if name := (&Context{}).TypeName(); name != "scriptContext" {
|
||||
t.Fatal("unexpected value")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package gct
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/d5/tengo/v2"
|
||||
objects "github.com/d5/tengo/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -17,7 +17,13 @@ var errInvalidInterval = errors.New("invalid interval")
|
||||
var supportedDurations = []string{"1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "24h", "1d", "3d", "1w"}
|
||||
|
||||
// Modules map of all loadable modules
|
||||
var Modules = map[string]map[string]tengo.Object{
|
||||
var Modules = map[string]map[string]objects.Object{
|
||||
"exchange": exchangeModule,
|
||||
"common": commonModule,
|
||||
"global": globalModules,
|
||||
}
|
||||
|
||||
// Context defines a juncture for script context to go context awareness
|
||||
type Context struct {
|
||||
objects.Map
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user