From 78b48c4a4d1473d94e82cdbfd560ae8827649d26 Mon Sep 17 00:00:00 2001 From: Onur Yilmaz Date: Tue, 5 Jul 2016 01:40:47 +0300 Subject: [PATCH] Refactoring for public and trade APIs --- btce.go | 6 ++ btce_test.go | 22 ++++++++ public.go | 10 ++-- public_test.go | 13 +++-- structs.go | 18 +++--- trade.go | 146 +++++++++++++++++++++++++------------------------ trade_test.go | 29 +++++----- 7 files changed, 141 insertions(+), 103 deletions(-) create mode 100644 btce.go create mode 100644 btce_test.go diff --git a/btce.go b/btce.go new file mode 100644 index 0000000..06a7a20 --- /dev/null +++ b/btce.go @@ -0,0 +1,6 @@ +package btce + +type API struct { + public PublicAPI + trade TradeAPI +} diff --git a/btce_test.go b/btce_test.go new file mode 100644 index 0000000..2d06951 --- /dev/null +++ b/btce_test.go @@ -0,0 +1,22 @@ +package btce + +import ( + . "github.com/smartystreets/goconvey/convey" + "testing" +) + +var btce = API{} + +func TestBTCE(t *testing.T) { + + Convey("BTCE instance created", t, func() { + + Convey("Public API should be available", func() { + So(btce.public, ShouldNotBeNil) + }) + + Convey("Trade API should be available", func() { + So(btce.trade, ShouldNotBeNil) + }) + }) +} diff --git a/public.go b/public.go index ae8e098..0263ae8 100644 --- a/public.go +++ b/public.go @@ -5,9 +5,11 @@ import ( "net/http" ) +type PublicAPI struct{} + const API_URL = "https://btc-e.com/api/3/" -func GetTicker(currency []string) (Ticker, error) { +func (api *PublicAPI) Ticker(currency []string) (Ticker, error) { url := API_URL + "ticker/" for _, c := range currency { @@ -25,7 +27,7 @@ func GetTicker(currency []string) (Ticker, error) { } -func GetInfo() (Info, error) { +func (api *PublicAPI) Info() (Info, error) { url := API_URL + "info" r, err := http.Get(url) @@ -40,7 +42,7 @@ func GetInfo() (Info, error) { } -func GetDepth(currency []string) (Depth, error) { +func (api *PublicAPI) Depth(currency []string) (Depth, error) { url := API_URL + "depth/" for _, c := range currency { @@ -58,7 +60,7 @@ func GetDepth(currency []string) (Depth, error) { } -func GetTrade(currency []string) (Trade, error) { +func (api *PublicAPI) Trade(currency []string) (Trade, error) { url := API_URL + "trades/" for _, c := range currency { diff --git a/public_test.go b/public_test.go index 3a61e9d..c559558 100644 --- a/public_test.go +++ b/public_test.go @@ -5,10 +5,12 @@ import ( "testing" ) +var api = PublicAPI{} + func TestTicker(t *testing.T) { Convey("Ticker data for BTC-USD", t, func() { - tickers, err := GetTicker([]string{"btc_usd"}) + tickers, err := api.Ticker([]string{"btc_usd"}) Convey("No error should occur", func() { So(err, ShouldBeNil) @@ -26,7 +28,7 @@ func TestTicker(t *testing.T) { func TestInfo(t *testing.T) { Convey("Information data", t, func() { - information, err := GetInfo() + information, err := api.Info() Convey("No error should occur", func() { So(err, ShouldBeNil) @@ -34,7 +36,7 @@ func TestInfo(t *testing.T) { Convey("Information data for 'btc_usd' should be returned", func() { So(information, ShouldHaveSameTypeAs, Info{}) - So(information.Pairs["btc_usd"], ShouldHaveSameTypeAs, PairInfo{}) + So(information.Pairs["btc_usd"], ShouldHaveSameTypeAs, InfoPair{}) }) }) @@ -43,7 +45,7 @@ func TestInfo(t *testing.T) { func TestDepth(t *testing.T) { Convey("Depth data", t, func() { - depth, err := GetDepth([]string{"btc_usd"}) + depth, err := api.Depth([]string{"btc_usd"}) Convey("No error should occur", func() { So(err, ShouldBeNil) @@ -60,7 +62,7 @@ func TestDepth(t *testing.T) { func TestTrade(t *testing.T) { Convey("Trade data", t, func() { - trade, err := GetTrade([]string{"btc_usd"}) + trade, err := api.Trade([]string{"btc_usd"}) Convey("No error should occur", func() { So(err, ShouldBeNil) @@ -69,7 +71,6 @@ func TestTrade(t *testing.T) { Convey("Trade data for 'btc_usd' should be returned", func() { So(trade, ShouldHaveSameTypeAs, Trade{}) So(len(trade["btc_usd"]), ShouldBeGreaterThanOrEqualTo, 0) - //So(trade["btc_usd"][0].TID, ShouldBeGreaterThanOrEqualTo, 0) }) }) diff --git a/structs.go b/structs.go index 3400279..1853b36 100644 --- a/structs.go +++ b/structs.go @@ -21,10 +21,10 @@ type TickerPair struct { type Info struct { ServerTime int64 `json:"server_time"` - Pairs map[string]PairInfo `json:"pairs"` + Pairs map[string]InfoPair `json:"pairs"` } -type PairInfo struct { +type InfoPair struct { DecimalPlaces int `json:"decimal_places"` MinPrice float64 `json:"min_price"` MaxPrice float64 `json:"max_price"` @@ -83,14 +83,14 @@ type ActiveOrder struct { type ActiveOrders map[string]ActiveOrder -type TradeResponse struct { +type Trade struct { Received float64 `json:"received"` Remains float64 `json:"remains"` OrderID string `json:"order_id"` Funds map[string]float64 `json:"funds"` } -type OrderInfo struct { +type OrderInfoItem struct { Pair string `json:"pair"` Type string `json:"type"` StartAmount float64 `json:"start_amount"` @@ -100,9 +100,9 @@ type OrderInfo struct { Status int `json:"status"` } -type OrderInfos map[string]OrderInfo +type OrderInfo map[string]OrderInfoItem -type CancelOrderResponse struct { +type CancelOrder struct { OrderID int `json:"order_id"` Funds map[string]float64 `json:"funds"` } @@ -140,19 +140,19 @@ type TransactionHistoryItem struct { type TransactionHistory map[string]TransactionHistoryItem -type WithdrawCoinResponse struct { +type WithdrawCoin struct { TransactionID int `json:"tId"` AmountSent float64 `json:"amountSent"` Funds map[string]float64 `json:"funds"` } -type CreateCouponResponse struct { +type CreateCoupon struct { Coupon string `json:"coupon"` TransactionID int `json:"transID"` Funds map[string]float64 `json:"funds"` } -type RedeemCouponResponse struct { +type RedeemCoupon struct { CouponAmount string `json:"couponAmount"` CouponCurrency string `json:"couponCurrency"` TransactionID int `json:"transID"` diff --git a/trade.go b/trade.go index 2c236b9..9fc16a8 100644 --- a/trade.go +++ b/trade.go @@ -15,21 +15,22 @@ import ( "time" ) -var API_KEY = "" -var API_SECRET = "" -var lastNonce int64 = 0 +type TradeAPI struct { + API_KEY string + API_SECRET string + lastNonce int64 +} const TRADE_URL = "https://btc-e.com/tapi" -func encodePostData(method string, params map[string]string) string { +func (tapi *TradeAPI) encodePostData(method string, params map[string]string) string { nonce := time.Now().Unix() - if nonce <= lastNonce { - nonce = nonce + 1 + if nonce <= tapi.lastNonce { + nonce = tapi.lastNonce + 1 } - lastNonce = nonce + tapi.lastNonce = nonce result := fmt.Sprintf("method=%s&nonce=%d", method, nonce) - // params are unordered, but after method and nonce if len(params) > 0 { v := url.Values{} for key := range params { @@ -46,13 +47,13 @@ func sign(secret string, payload string) string { return hex.EncodeToString(mac.Sum(nil)) } -func call(method string, v interface{}, params map[string]string) error { +func (tapi *TradeAPI) call(method string, v interface{}, params map[string]string) error { - postData := encodePostData(method, params) + postData := tapi.encodePostData(method, params) req, err := http.NewRequest("POST", TRADE_URL, bytes.NewBufferString(postData)) - req.Header.Add("Key", API_KEY) - req.Header.Add("Sign", sign(API_SECRET, postData)) + req.Header.Add("Key", tapi.API_KEY) + req.Header.Add("Sign", sign(tapi.API_SECRET, postData)) req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Content-Length", strconv.Itoa(len(postData))) @@ -95,47 +96,49 @@ func marshalResponse(resp *http.Response, v interface{}) error { return nil } -func Auth(key string, secret string) { - API_KEY = key - API_SECRET = secret +func (tapi *TradeAPI) Auth(key string, secret string) { + tapi.API_KEY = key + tapi.API_SECRET = secret } -func GetAccountInfo() (AccountInfo, error) { + +func (tapi *TradeAPI) AccountInfo() (AccountInfo, error) { info := AccountInfo{} - err := call("getInfo", &info, nil) + err := tapi.call("getInfo", &info, nil) if err == nil { return info, nil } else { return info, err } } -func GetAccountInfoAuth(key string, secret string) (AccountInfo, error) { - Auth(key, secret) - return GetAccountInfo() + +func (tapi *TradeAPI) AccountInfoAuth(key string, secret string) (AccountInfo, error) { + tapi.Auth(key, secret) + return tapi.AccountInfo() } -func GetActiveOrders(pair string) (ActiveOrders, error) { +func (tapi *TradeAPI) ActiveOrders(pair string) (ActiveOrders, error) { orderParams := make(map[string]string, 4) orderParams["pair"] = pair activeOrders := make(ActiveOrders, 0) - err := call("ActiveOrders", &activeOrders, orderParams) + err := tapi.call("ActiveOrders", &activeOrders, orderParams) if err == nil { return activeOrders, nil } else { return activeOrders, err } } -func GetActiveOrdersAuth(key string, secret string, pair string) (ActiveOrders, error) { - Auth(key, secret) - return GetActiveOrders(pair) +func (tapi *TradeAPI) ActiveOrdersAuth(key string, secret string, pair string) (ActiveOrders, error) { + tapi.Auth(key, secret) + return tapi.ActiveOrders(pair) } -func OrderTrade(pair string, orderType string, rate float64, amount float64) (TradeResponse, error) { +func (tapi *TradeAPI) Trade(pair string, orderType string, rate float64, amount float64) (Trade, error) { - tradeResponse := TradeResponse{} + tradeResponse := Trade{} orderParams := make(map[string]string, 4) orderParams["pair"] = pair @@ -143,7 +146,7 @@ func OrderTrade(pair string, orderType string, rate float64, amount float64) (Tr orderParams["rate"] = strconv.FormatFloat(rate, 'f', -1, 64) orderParams["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) - err := call("Trade", &tradeResponse, orderParams) + err := tapi.call("Trade", &tradeResponse, orderParams) if err == nil { return tradeResponse, nil @@ -153,20 +156,20 @@ func OrderTrade(pair string, orderType string, rate float64, amount float64) (Tr } -func OrderTradeAuth(key string, secret string, pair string, orderType string, rate float64, amount float64) (TradeResponse, error) { - Auth(key, secret) - return OrderTrade(pair, orderType, rate, amount) +func (tapi *TradeAPI) TradeAuth(key string, secret string, pair string, orderType string, rate float64, amount float64) (Trade, error) { + tapi.Auth(key, secret) + return tapi.Trade(pair, orderType, rate, amount) } -func GetOrderInfo(orderID string) (OrderInfos, error) { +func (tapi *TradeAPI) OrderInfo(orderID string) (OrderInfo, error) { - orderInfo := OrderInfos{} + orderInfo := OrderInfo{} orderParams := make(map[string]string, 1) orderParams["order_id"] = orderID - err := call("OrderInfo", &orderInfo, orderParams) + err := tapi.call("OrderInfo", &orderInfo, orderParams) if err == nil { fmt.Println(err) return orderInfo, nil @@ -176,20 +179,20 @@ func GetOrderInfo(orderID string) (OrderInfos, error) { } -func GetOrderInfoAuth(key string, secret string, orderID string) (OrderInfos, error) { - Auth(key, secret) - return GetOrderInfo(orderID) +func (tapi *TradeAPI) OrderInfoAuth(key string, secret string, orderID string) (OrderInfo, error) { + tapi.Auth(key, secret) + return tapi.OrderInfo(orderID) } -func CancelOrder(orderID string) (CancelOrderResponse, error) { +func (tapi *TradeAPI) CancelOrder(orderID string) (CancelOrder, error) { - cancelReponse := CancelOrderResponse{} + cancelReponse := CancelOrder{} orderParams := make(map[string]string, 1) orderParams["order_id"] = orderID - err := call("CancelOrder", &cancelReponse, orderParams) + err := tapi.call("CancelOrder", &cancelReponse, orderParams) if err == nil { return cancelReponse, nil @@ -199,13 +202,13 @@ func CancelOrder(orderID string) (CancelOrderResponse, error) { } -func CancelOrderAuth(key string, secret string, orderID string) (CancelOrderResponse, error) { - Auth(key, secret) - return CancelOrder(orderID) +func (tapi *TradeAPI) CancelOrderAuth(key string, secret string, orderID string) (CancelOrder, error) { + tapi.Auth(key, secret) + return tapi.CancelOrder(orderID) } -func GetTradeHistory(filter HistoryFilter, pair string) (TradeHistory, error) { +func (tapi *TradeAPI) TradeHistory(filter HistoryFilter, pair string) (TradeHistory, error) { tradeHistory := TradeHistory{} @@ -214,7 +217,7 @@ func GetTradeHistory(filter HistoryFilter, pair string) (TradeHistory, error) { historyParams["pair"] = pair } - err := call("TradeHistory", &tradeHistory, historyParams) + err := tapi.call("TradeHistory", &tradeHistory, historyParams) if err == nil { return tradeHistory, nil @@ -224,19 +227,19 @@ func GetTradeHistory(filter HistoryFilter, pair string) (TradeHistory, error) { } -func GetTradeHistoryAuth(key string, secret string, filter HistoryFilter, pair string) (TradeHistory, error) { - Auth(key, secret) - return GetTradeHistory(filter, pair) +func (tapi *TradeAPI) TradeHistoryAuth(key string, secret string, filter HistoryFilter, pair string) (TradeHistory, error) { + tapi.Auth(key, secret) + return tapi.TradeHistory(filter, pair) } -func GetTransactionHistory(filter HistoryFilter) (TransactionHistory, error) { +func (tapi *TradeAPI) TransactionHistory(filter HistoryFilter) (TransactionHistory, error) { transactionHistory := TransactionHistory{} historyParams := historyFilterParams(filter) - err := call("TransHistory", &transactionHistory, historyParams) + err := tapi.call("TransHistory", &transactionHistory, historyParams) if err == nil { return transactionHistory, nil @@ -246,11 +249,12 @@ func GetTransactionHistory(filter HistoryFilter) (TransactionHistory, error) { } -func GetTransactionHistoryAuth(key string, secret string, filter HistoryFilter) (TransactionHistory, error) { - Auth(key, secret) - return GetTransactionHistory(filter) +func (tapi *TradeAPI) TransactionHistoryAuth(key string, secret string, filter HistoryFilter) (TransactionHistory, error) { + tapi.Auth(key, secret) + return tapi.TransactionHistory(filter) } + func historyFilterParams(filter HistoryFilter) map[string]string { params := make(map[string]string, 0) @@ -278,16 +282,16 @@ func historyFilterParams(filter HistoryFilter) map[string]string { return params } -func WithdrawCoin(coinName string, amount float64, address string) (WithdrawCoinResponse, error) { +func (tapi *TradeAPI) WithdrawCoin(coinName string, amount float64, address string) (WithdrawCoin, error) { - response := WithdrawCoinResponse{} + response := WithdrawCoin{} orderParams := make(map[string]string, 3) orderParams["coinName"] = coinName orderParams["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) orderParams["address"] = address - err := call("WithdrawCoin", &response, orderParams) + err := tapi.call("WithdrawCoin", &response, orderParams) if err == nil { return response, nil @@ -297,21 +301,21 @@ func WithdrawCoin(coinName string, amount float64, address string) (WithdrawCoin } -func WithdrawCoinAuth(key string, secret string, coinName string, amount float64, address string) (WithdrawCoinResponse, error) { - Auth(key, secret) - return WithdrawCoin(coinName, amount, address) +func (tapi *TradeAPI) WithdrawCoinAuth(key string, secret string, coinName string, amount float64, address string) (WithdrawCoin, error) { + tapi.Auth(key, secret) + return tapi.WithdrawCoin(coinName, amount, address) } -func CreateCoupon(currency string, amount float64) (CreateCouponResponse, error) { +func (tapi *TradeAPI) CreateCoupon(currency string, amount float64) (CreateCoupon, error) { - response := CreateCouponResponse{} + response := CreateCoupon{} params := make(map[string]string, 2) params["currency"] = currency params["amount"] = strconv.FormatFloat(amount, 'f', -1, 64) - err := call("CreateCoupon", &response, params) + err := tapi.call("CreateCoupon", &response, params) if err == nil { return response, nil @@ -321,19 +325,19 @@ func CreateCoupon(currency string, amount float64) (CreateCouponResponse, error) } -func CreateCouponAuth(key string, secret string, currency string, amount float64) (CreateCouponResponse, error) { - Auth(key, secret) - return CreateCoupon(currency, amount) +func (tapi *TradeAPI) CreateCouponAuth(key string, secret string, currency string, amount float64) (CreateCoupon, error) { + tapi.Auth(key, secret) + return tapi.CreateCoupon(currency, amount) } -func RedeemCoupon(coupon string) (RedeemCouponResponse, error) { +func (tapi *TradeAPI) RedeemCoupon(coupon string) (RedeemCoupon, error) { - response := RedeemCouponResponse{} + response := RedeemCoupon{} params := make(map[string]string, 1) params["coupon"] = coupon - err := call("RedeemCoupon", &response, params) + err := tapi.call("RedeemCoupon", &response, params) if err == nil { return response, nil @@ -343,7 +347,7 @@ func RedeemCoupon(coupon string) (RedeemCouponResponse, error) { } -func RedeemCouponAuth(key string, secret string, coupon string) (RedeemCouponResponse, error) { - Auth(key, secret) - return RedeemCoupon(coupon) +func (tapi *TradeAPI) RedeemCouponAuth(key string, secret string, coupon string) (RedeemCoupon, error) { + tapi.Auth(key, secret) + return tapi.RedeemCoupon(coupon) } diff --git a/trade_test.go b/trade_test.go index c14bcef..1dcf2e8 100644 --- a/trade_test.go +++ b/trade_test.go @@ -3,19 +3,22 @@ package btce import ( "errors" "fmt" - . "github.com/smartystreets/goconvey/convey" "os" "strconv" "testing" "time" + + . "github.com/smartystreets/goconvey/convey" ) const SLEEP = 5 +var tapi = TradeAPI{} + func TestAccountInfo(t *testing.T) { time.Sleep(SLEEP * time.Second) Convey("Account information data", t, func() { - info, err := GetAccountInfoAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST")) + info, err := tapi.AccountInfoAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST")) Convey("No error should occur", func() { So(err, ShouldBeNil) }) @@ -32,7 +35,7 @@ func TestAccountInfo(t *testing.T) { func TestActiveOrders(t *testing.T) { time.Sleep(SLEEP * time.Second) Convey("Active orders data", t, func() { - orders, err := GetActiveOrdersAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "btc_usd") + orders, err := tapi.ActiveOrdersAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "btc_usd") if err != nil { Convey("If error is returned, it should be 'no orders'", func() { @@ -50,7 +53,7 @@ func TestActiveOrders(t *testing.T) { func TestOrderTrade(t *testing.T) { time.Sleep(SLEEP * time.Second) Convey("Trade new order", t, func() { - orderResponse, err := OrderTradeAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "btc_usd", "buy", 900, 1) + orderResponse, err := tapi.TradeAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "btc_usd", "buy", 900, 1) if err != nil { Convey("If error is returned, it should be 'not enough USD'", func() { @@ -66,9 +69,9 @@ func TestOrderTrade(t *testing.T) { func TestOrderInfo(t *testing.T) { time.Sleep(SLEEP * time.Second) - orderID := "1140186935" + orderID := "1" Convey("Get order info", t, func() { - orderResponse, err := GetOrderInfoAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), orderID) + orderResponse, err := tapi.OrderInfoAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), orderID) if err != nil { Convey("If error is returned, it should be 'invalid order'", func() { @@ -85,9 +88,9 @@ func TestOrderInfo(t *testing.T) { func TestCancelOrder(t *testing.T) { time.Sleep(SLEEP * time.Second) - orderID := "1140186997" + orderID := "1" Convey("Cancel order", t, func() { - orderResponse, err := CancelOrderAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), orderID) + orderResponse, err := tapi.CancelOrderAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), orderID) if err != nil { Convey("If error is returned, it should be 'bad status'", func() { @@ -106,7 +109,7 @@ func TestTradeHistory(t *testing.T) { Convey("Trade history data", t, func() { filter := HistoryFilter{} - tradeHistory, err := GetTradeHistoryAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), filter, "btc_usd") + tradeHistory, err := tapi.TradeHistoryAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), filter, "btc_usd") if err != nil { Convey("If error is returned, it should be 'no trades'", func() { @@ -126,7 +129,7 @@ func TestTransactionHistory(t *testing.T) { Convey("Transaction history data", t, func() { filter := HistoryFilter{} - transactionHistory, err := GetTransactionHistoryAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), filter) + transactionHistory, err := tapi.TransactionHistoryAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), filter) if err != nil { Convey("If error is returned, it should be 'no transactions'", func() { @@ -145,7 +148,7 @@ func TestWithdrawCoin(t *testing.T) { time.Sleep(SLEEP * time.Second) Convey("Withdraw coin", t, func() { - response, err := WithdrawCoinAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "BTC", 0.001, "address") + response, err := tapi.WithdrawCoinAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "BTC", 0.001, "address") if err != nil { Convey("If error is returned, it should be 'api permission'", func() { @@ -164,7 +167,7 @@ func TestCreateCoupon(t *testing.T) { time.Sleep(SLEEP * time.Second) Convey("Create coupon", t, func() { - response, err := CreateCouponAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "BTC", 0.001) + response, err := tapi.CreateCouponAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "BTC", 0.001) if err != nil { Convey("If error is returned, it should be 'api permission'", func() { @@ -183,7 +186,7 @@ func TestRedeemCoupon(t *testing.T) { time.Sleep(SLEEP * time.Second) Convey("Redeem coupon", t, func() { - response, err := RedeemCouponAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "BTC-USD-XYZ") + response, err := tapi.RedeemCouponAuth(os.Getenv("API_KEY_TEST"), os.Getenv("API_SECRET_TEST"), "BTC-USD-XYZ") if err != nil { Convey("If error is returned, it should be 'api permission'", func() {