Calculating each exchange's fees (#188)

* Adds some constants for fee types
Adds some fee calculation in an attempt to be generic
Adds fee stuff to Bittrex
Adds fee stuff to bitstamp

* Fixes bitstamp fee calculation

* Tests
Tests all scenarios for GetFeeByType

* Adds method to wrapper
Adds err to response
Checks for err

* Adds support for Bittrex fees

* Adds maker/taker dynamic to fees
Updates tests
Adds bitmex fee support
Removes unused switch case scenarios to not waste space

* Adds bithumb support for fee calculation

* Adds Bitfinex fee support
Adds list of currencies as const strings
Sets up bitflyer

* Fixes arguments

* Greatly expands symbols
Adds Binance fee calculation support
Cleans up previous exchanges

* Fixes errors for fee calculations

* Adds ANX fee support

* Adds btcc fee support
Adds alphapoint fee wrapper support
Renames method to match "enum"
Uses symbols in tests, not inline strings

* Adds support for BTCMarkets fee calculation
Adds new method to retrieve fee amount from BTCMarkets
Adds new fee type struct: FeeBuilder
Updates ANX and BTCMarkets to use new FeeBuilder type struct
Standardises the tests to run when it comes to fee calculation

* Migrates all existing exchange fee to use new feebuilder type struct
Uses standard testing model

* Fixes unit tests

* Updates maker taker fees in test config

* Removes parallel from fee testing

* Removes more parallel from tests

* Adds coinbasepro fee support

* Adds Coinut fee support

* Adds Exmo fee support
Adds maker fee support to coinut
Introduces a type for fees and bank transfers to prevent random strings being used

* Adds partial bitflyer support
Moves bitflyer to feeBuilder struct

* Adds gateio fee support

* Adds Gemini fee support

* Adds hitbtc fee support

* Adds huobi fee support

* Adds HuobiHadax fee support

* Adds itbit fee support

* Adds partial kraken fee support with trading fees

* Finishes basic Kraken fee support

* Adds basic LakeBTC fee support

* Adds basic liqui fee support

* Adds localbitcoins fee support.......

* Adds basic okcoin fee support

* Adds simple OKEX fee support
Adds many new currency symbols
Fixes liqui's fees

* Adds poloniex fee support

* Adds fee support for Yobit

* Adds WEX fee support

* Adds ZB fee support

* Removes bad reference

* Improves accuracy of variable name

* trading fee method names are now consistent

(cherry picked from commit 21c82e8b90cae590cfd73d365d7be39e1a00e973)

* Fixes rebasing issues

* Fixes issues from rebase
Removes "IsTaker" as IsMaker bool can imply taker
Updates tests to actually work.

* Adds a zero to the test

* Fixes bitfinex api endpoints and fixes fee calculations

* Updates btcmarkets trading fee calculation

* Verifies tests with apis for all exchanges except coinbasepro, itbit and bitflyer
Removes taker fee test as taker is default

* Removes redundant all exchange wrapper error checks due to the error checks being redundant

* Addresses review comments:
- Renames variables
- Changes how functions return data
- Fixes typo
This commit is contained in:
Scott
2018-10-29 12:32:46 +11:00
committed by Adrian Gallagher
parent 83263f3245
commit e4c443b901
108 changed files with 8468 additions and 538 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -176,3 +176,8 @@ func (a *Alphapoint) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amoun
func (a *Alphapoint) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (a *Alphapoint) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return 0, errors.New("not yet implemented")
}

View File

@@ -8,6 +8,8 @@ import (
"strconv"
"time"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/exchanges"
@@ -44,8 +46,8 @@ type ANX struct {
func (a *ANX) SetDefaults() {
a.Name = "ANX"
a.Enabled = false
a.TakerFee = 0.6
a.MakerFee = 0.3
a.TakerFee = 0.02
a.MakerFee = 0.01
a.Verbose = false
a.RESTPollingDelay = 10
a.RequestCurrencyPairFormat.Delimiter = ""
@@ -118,14 +120,6 @@ func (a *ANX) GetCurrencies() (CurrenciesStore, error) {
return result.CurrenciesResponse, nil
}
// GetFee returns maker or taker fees
func (a *ANX) GetFee(maker bool) float64 {
if maker {
return a.MakerFee
}
return a.TakerFee
}
// GetTicker returns the current ticker
func (a *ANX) GetTicker(currency string) (Ticker, error) {
var ticker Ticker
@@ -405,3 +399,47 @@ func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interf
return a.SendPayload("POST", a.APIUrl+path, headers, bytes.NewBuffer(PayloadJSON), result, true, a.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (a *ANX) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = a.calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func (a *ANX) calculateTradingFee(purchasePrice, amount float64, isMaker bool) float64 {
var fee float64
if isMaker {
fee = a.MakerFee * amount * purchasePrice
} else {
fee = a.TakerFee * amount * purchasePrice
}
return fee
}
func getCryptocurrencyWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func getInternationalBankWithdrawalFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.HKD {
fee = 250 + (WithdrawalFees[currency] * amount)
}
//TODO, other fiat currencies require consultation with ANXPRO
return fee
}

View File

@@ -4,32 +4,34 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var anx ANX
var a ANX
func TestSetDefaults(t *testing.T) {
anx.SetDefaults()
a.SetDefaults()
if anx.Name != "ANX" {
if a.Name != "ANX" {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
if anx.Enabled != false {
if a.Enabled != false {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
if anx.TakerFee != 0.6 {
if a.TakerFee != 0.02 {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
if anx.MakerFee != 0.3 {
if a.MakerFee != 0.01 {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
if anx.Verbose != false {
if a.Verbose != false {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
if anx.Websocket.IsEnabled() != false {
if a.Websocket.IsEnabled() != false {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
if anx.RESTPollingDelay != 10 {
if a.RESTPollingDelay != 10 {
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
}
}
@@ -41,67 +43,56 @@ func TestSetup(t *testing.T) {
if err != nil {
t.Error("Test Failed - ANX Setup() init error")
}
anx.Setup(anxConfig)
a.Setup(anxConfig)
if anx.Enabled != true {
if a.Enabled != true {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if anx.AuthenticatedAPISupport != false {
if a.AuthenticatedAPISupport != false {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if len(anx.APIKey) != 0 {
if len(a.APIKey) != 0 {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if len(anx.APISecret) != 0 {
if len(a.APISecret) != 0 {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if anx.RESTPollingDelay != 10 {
if a.RESTPollingDelay != 10 {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if anx.Verbose != false {
if a.Verbose != false {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if anx.Websocket.IsEnabled() != false {
if a.Websocket.IsEnabled() != false {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if len(anx.BaseCurrencies) <= 0 {
if len(a.BaseCurrencies) <= 0 {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if len(anx.AvailablePairs) <= 0 {
if len(a.AvailablePairs) <= 0 {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
if len(anx.EnabledPairs) <= 0 {
if len(a.EnabledPairs) <= 0 {
t.Error("Test Failed - ANX Setup() incorrect values set")
}
}
func TestGetCurrencies(t *testing.T) {
_, err := anx.GetCurrencies()
_, err := a.GetCurrencies()
if err != nil {
t.Fatalf("Test failed. TestGetCurrencies failed. Err: %s", err)
}
}
func TestGetTradablePairs(t *testing.T) {
_, err := anx.GetTradablePairs()
_, err := a.GetTradablePairs()
if err != nil {
t.Fatalf("Test failed. TestGetTradablePairs failed. Err: %s", err)
}
}
func TestGetFee(t *testing.T) {
makerFeeExpected, takerFeeExpected := 0.3, 0.6
if anx.GetFee(true) != makerFeeExpected {
t.Error("Test Failed - ANX GetFee() incorrect return value")
}
if anx.GetFee(false) != takerFeeExpected {
t.Error("Test Failed - ANX GetFee() incorrect return value")
}
}
func TestGetTicker(t *testing.T) {
ticker, err := anx.GetTicker("BTCUSD")
ticker, err := a.GetTicker("BTCUSD")
if err != nil {
t.Errorf("Test Failed - ANX GetTicker() error: %s", err)
}
@@ -111,7 +102,7 @@ func TestGetTicker(t *testing.T) {
}
func TestGetDepth(t *testing.T) {
ticker, err := anx.GetDepth("BTCUSD")
ticker, err := a.GetDepth("BTCUSD")
if err != nil {
t.Errorf("Test Failed - ANX GetDepth() error: %s", err)
}
@@ -121,7 +112,7 @@ func TestGetDepth(t *testing.T) {
}
func TestGetAPIKey(t *testing.T) {
apiKey, apiSecret, err := anx.GetAPIKey("userName", "passWord", "", "1337")
apiKey, apiSecret, err := a.GetAPIKey("userName", "passWord", "", "1337")
if err == nil {
t.Error("Test Failed - ANX GetAPIKey() Incorrect")
}
@@ -132,3 +123,87 @@ func TestGetAPIKey(t *testing.T) {
t.Error("Test Failed - ANX GetAPIKey() Incorrect")
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
a.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := a.GetFee(feeBuilder); resp != float64(0.02) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := a.GetFee(feeBuilder); resp != float64(20000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(20000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := a.GetFee(feeBuilder); resp != float64(0.01) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.01), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := a.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := a.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := a.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := a.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := a.GetFee(feeBuilder); resp != float64(250.01) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(250.01), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package anx
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Currency holds the currency information
type Currency struct {
Decimals int `json:"decimals"`
@@ -146,3 +148,16 @@ type Depth struct {
Bids []DepthItem `json:"bids"`
} `json:"data"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.BTC: 0.002,
symbol.DOGE: 0.1,
symbol.ETH: 0.005,
symbol.GNT: 0.001,
symbol.LTC: 0.02,
symbol.OAX: 0.001,
symbol.XRP: 1,
symbol.HKD: 0.01,
}

View File

@@ -249,3 +249,8 @@ func (a *ANX) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Currenc
func (a *ANX) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (a *ANX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return a.GetFee(feeBuilder)
}

View File

@@ -652,3 +652,48 @@ func (b *Binance) SetValues() {
TimeIntervalMonth,
}
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Binance) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
multiplier, err := b.getMultiplier(feeBuilder.IsMaker)
if err != nil {
return 0, err
}
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, multiplier)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency, feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// getMultiplier retrieves account based taker/maker fees
func (b *Binance) getMultiplier(isMaker bool) (float64, error) {
var multiplier float64
account, err := b.GetAccount()
if err != nil {
return 0, err
}
if isMaker {
multiplier = float64(account.MakerCommission)
} else {
multiplier = float64(account.TakerCommission)
}
return multiplier, nil
}
// calculateTradingFee returns the fee for trading any currency on Bittrex
func calculateTradingFee(purchasePrice, amount, multiplier float64) float64 {
return (multiplier / 100) * purchasePrice * amount
}
// getCryptocurrencyWithdrawalFee returns the fee for withdrawing from the exchange
func getCryptocurrencyWithdrawalFee(currency string, purchasePrice, amount float64) float64 {
return WithdrawalFees[currency]
}

View File

@@ -3,7 +3,10 @@ package binance
import (
"testing"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/config"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own keys here for due diligence testing
@@ -29,7 +32,6 @@ func TestSetup(t *testing.T) {
binanceConfig.AuthenticatedAPISupport = true
binanceConfig.APIKey = testAPIKey
binanceConfig.APISecret = testAPISecret
b.Setup(binanceConfig)
}
@@ -205,3 +207,112 @@ func TestAllOrders(t *testing.T) {
t.Error("Test Failed - Binance AllOrders() error", err)
}
}
func TestGetAccount(t *testing.T) {
if testAPIKey == "" || testAPISecret == "" {
t.Skip()
}
t.Parallel()
b.SetDefaults()
TestSetup(t)
account, err := b.GetAccount()
if err != nil {
t.Fatal("Test Failed - Binance GetAccount() error", err)
}
if account.MakerCommission <= 0 {
t.Fatalf("Test Failed. Expected > 0, Recieved %d", account.MakerCommission)
}
if account.TakerCommission <= 0 {
t.Fatalf("Test Failed. Expected > 0, Recieved %d", account.TakerCommission)
}
t.Logf("Current makerFee: %d", account.MakerCommission)
t.Logf("Current takerFee: %d", account.TakerCommission)
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if testAPIKey != "" || testAPISecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.1) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(100000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(100000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.1) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.1), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0005), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -2,6 +2,8 @@ package binance
import (
"encoding/json"
"github.com/thrasher-/gocryptotrader/currency/symbol"
)
// Response holds basic binance api response data
@@ -432,3 +434,172 @@ var (
TimeIntervalWeek = TimeInterval("1w")
TimeIntervalMonth = TimeInterval("1M")
)
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.BNB: 0.13,
symbol.BTC: 0.0005,
symbol.NEO: 0,
symbol.ETH: 0.01,
symbol.LTC: 0.001,
symbol.QTUM: 0.01,
symbol.EOS: 0.1,
symbol.SNT: 35,
symbol.BNT: 1,
symbol.GAS: 0,
symbol.BCC: 0.001,
symbol.BTM: 5,
symbol.USDT: 3.4,
symbol.HCC: 0.0005,
symbol.OAX: 6.5,
symbol.DNT: 54,
symbol.MCO: 0.31,
symbol.ICN: 3.5,
symbol.ZRX: 1.9,
symbol.OMG: 0.4,
symbol.WTC: 0.5,
symbol.LRC: 12.3,
symbol.LLT: 67.8,
symbol.YOYO: 1,
symbol.TRX: 1,
symbol.STRAT: 0.1,
symbol.SNGLS: 54,
symbol.BQX: 3.9,
symbol.KNC: 3.5,
symbol.SNM: 25,
symbol.FUN: 86,
symbol.LINK: 4,
symbol.XVG: 0.1,
symbol.CTR: 35,
symbol.SALT: 2.3,
symbol.MDA: 2.3,
symbol.IOTA: 0.5,
symbol.SUB: 11.4,
symbol.ETC: 0.01,
symbol.MTL: 2,
symbol.MTH: 45,
symbol.ENG: 2.2,
symbol.AST: 14.4,
symbol.DASH: 0.002,
symbol.BTG: 0.001,
symbol.EVX: 2.8,
symbol.REQ: 29.9,
symbol.VIB: 30,
symbol.POWR: 8.2,
symbol.ARK: 0.2,
symbol.XRP: 0.25,
symbol.MOD: 2,
symbol.ENJ: 26,
symbol.STORJ: 5.1,
symbol.KMD: 0.002,
symbol.RCN: 47,
symbol.NULS: 0.01,
symbol.RDN: 2.5,
symbol.XMR: 0.04,
symbol.DLT: 19.8,
symbol.AMB: 8.9,
symbol.BAT: 8,
symbol.ZEC: 0.005,
symbol.BCPT: 14.5,
symbol.ARN: 3,
symbol.GVT: 0.13,
symbol.CDT: 81,
symbol.GXS: 0.3,
symbol.POE: 134,
symbol.QSP: 36,
symbol.BTS: 1,
symbol.XZC: 0.02,
symbol.LSK: 0.1,
symbol.TNT: 47,
symbol.FUEL: 79,
symbol.MANA: 18,
symbol.BCD: 0.01,
symbol.DGD: 0.04,
symbol.ADX: 6.3,
symbol.ADA: 1,
symbol.PPT: 0.41,
symbol.CMT: 12,
symbol.XLM: 0.01,
symbol.CND: 58,
symbol.LEND: 84,
symbol.WABI: 6.6,
symbol.SBTC: 0.0005,
symbol.BCX: 0.5,
symbol.WAVES: 0.002,
symbol.TNB: 139,
symbol.GTO: 20,
symbol.ICX: 0.02,
symbol.OST: 32,
symbol.ELF: 3.9,
symbol.AION: 3.2,
symbol.CVC: 10.9,
symbol.REP: 0.2,
symbol.GNT: 8.9,
symbol.DATA: 37,
symbol.ETF: 1,
symbol.BRD: 3.8,
symbol.NEBL: 0.01,
symbol.VIBE: 17.3,
symbol.LUN: 0.36,
symbol.CHAT: 60.7,
symbol.RLC: 3.4,
symbol.INS: 3.5,
symbol.IOST: 105.6,
symbol.STEEM: 0.01,
symbol.NANO: 0.01,
symbol.AE: 1.3,
symbol.VIA: 0.01,
symbol.BLZ: 10.3,
symbol.SYS: 1,
symbol.NCASH: 247.6,
symbol.POA: 0.01,
symbol.ONT: 1,
symbol.ZIL: 37.2,
symbol.STORM: 152,
symbol.XEM: 4,
symbol.WAN: 0.1,
symbol.WPR: 43.4,
symbol.QLC: 1,
symbol.GRS: 0.2,
symbol.CLOAK: 0.02,
symbol.LOOM: 11.9,
symbol.BCN: 1,
symbol.TUSD: 1.35,
symbol.ZEN: 0.002,
symbol.SKY: 0.01,
symbol.THETA: 24,
symbol.IOTX: 90.5,
symbol.QKC: 24.6,
symbol.AGI: 29.81,
symbol.NXS: 0.02,
symbol.SC: 0.1,
symbol.EON: 10,
symbol.NPXS: 897,
symbol.KEY: 223,
symbol.NAS: 0.1,
symbol.ADD: 100,
symbol.MEETONE: 300,
symbol.ATD: 100,
symbol.MFT: 175,
symbol.EOP: 5,
symbol.DENT: 596,
symbol.IQ: 50,
symbol.ARDR: 2,
symbol.HOT: 1210,
symbol.VET: 100,
symbol.DOCK: 68,
symbol.POLY: 7,
symbol.VTHO: 21,
symbol.ONG: 0.1,
symbol.PHX: 1,
symbol.HC: 0.005,
symbol.GO: 0.01,
symbol.PAX: 1.4,
symbol.EDO: 1.3,
symbol.WINGS: 8.9,
symbol.NAV: 0.2,
symbol.TRIG: 49.1,
symbol.APPC: 12.4,
symbol.PIVX: 0.02,
}

View File

@@ -194,3 +194,8 @@ func (b *Binance) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cur
func (b *Binance) GetWebsocket() (*exchange.Websocket, error) {
return b.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Binance) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -489,36 +489,19 @@ func (b *Bitfinex) GetSymbolsDetails() ([]SymbolDetails, error) {
}
// GetAccountInfo returns information about your account incl. trading fees
func (b *Bitfinex) GetAccountInfo() (AccountInfo, error) {
func (b *Bitfinex) GetAccountInfo() ([]AccountInfo, error) {
var result AccountInfo
var response []interface{}
err := b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountInfo, nil, &response)
var responses []AccountInfo
err := b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountInfo, nil, &responses)
if err != nil {
return result, err
return responses, err
}
result = AccountInfo{}
result.MakerFees = response[0].(map[string]interface{})["maker_fees"].(string)
result.TakerFees = response[0].(map[string]interface{})["taker_fees"].(string)
feeslist := response[0].(map[string]interface{})["fees"].([]interface{})
for _, v := range feeslist {
item := v.(map[string]interface{})
result.Fees = append(result.Fees, AccountInfoFees{
Pairs: item["pairs"].(string),
MakerFees: item["maker_fees"].(string),
TakerFees: item["taker_fees"].(string),
})
}
return result, nil
return responses, nil
}
// GetAccountFees - NOT YET IMPLEMENTED
// GetAccountFees - Gets all fee rates for all currencies
func (b *Bitfinex) GetAccountFees() (AccountFees, error) {
response := AccountFees{}
@@ -903,7 +886,7 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[
}
request := make(map[string]interface{})
request["request"] = fmt.Sprintf("/v%s/%s", bitfinexAPIVersion, path)
request["request"] = fmt.Sprintf("%s%s", bitfinexAPIVersion, path)
request["nonce"] = b.Nonce.String()
if params != nil {
@@ -934,3 +917,83 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[
}
return nil
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Bitfinex) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
accountInfos, err := b.GetAccountInfo()
if err != nil {
return 0, err
}
fee, err = b.CalculateTradingFee(accountInfos, feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.FirstCurrency, feeBuilder.IsMaker)
if err != nil {
return 0, err
}
case exchange.CyptocurrencyDepositFee:
//TODO: fee is charged when < $1000USD is transferred, need to infer value in some way
fee = 0
case exchange.CryptocurrencyWithdrawalFee:
accountFees, err := b.GetAccountFees()
if err != nil {
return 0, err
}
fee, err = b.GetCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency, accountFees)
if err != nil {
return 0, err
}
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.Amount)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// GetCryptocurrencyWithdrawalFee returns an estimate of fee based on type of transaction
func (b *Bitfinex) GetCryptocurrencyWithdrawalFee(currency string, accountFees AccountFees) (fee float64, err error) {
switch accountFees.Withdraw[currency].(type) {
case string:
fee, err = strconv.ParseFloat(accountFees.Withdraw[currency].(string), 64)
if err != nil {
return 0, err
}
case float64:
fee = accountFees.Withdraw[currency].(float64)
}
return fee, nil
}
func getInternationalBankDepositFee(amount float64) float64 {
return 0.001 * amount
}
func getInternationalBankWithdrawalFee(amount float64) float64 {
return 0.001 * amount
}
// CalculateTradingFee returns an estimate of fee based on type of whether is maker or taker fee
func (b *Bitfinex) CalculateTradingFee(accountInfos []AccountInfo, purchasePrice, amount float64, currency string, isMaker bool) (fee float64, err error) {
for _, i := range accountInfos {
for _, j := range i.Fees {
if currency == j.Pairs {
if isMaker {
fee = j.MakerFees
} else {
fee = j.TakerFees
}
break
}
}
if fee > 0 {
break
}
}
return (fee / 100) * purchasePrice * amount, err
}

View File

@@ -8,6 +8,8 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own keys here to do better tests
@@ -27,7 +29,8 @@ func TestSetup(t *testing.T) {
t.Error("Test Failed - Bitfinex Setup() init error")
}
b.Setup(bfxConfig)
b.APIKey = testAPIKey
b.APISecret = testAPISecret
if !b.Enabled || b.AuthenticatedAPISupport || b.RESTPollingDelay != time.Duration(10) ||
b.Verbose || b.Websocket.IsEnabled() || len(b.BaseCurrencies) < 1 ||
len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 {
@@ -617,3 +620,89 @@ func TestCloseMarginFunding(t *testing.T) {
t.Error("Test Failed - CloseMarginFunding() error")
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
b.Verbose = true
TestSetup(t)
var feeBuilder = setFeeBuilder()
if testAPIKey != "" || testAPISecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0004) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0004), resp)
t.Error(err)
}
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
}

View File

@@ -133,36 +133,22 @@ type AccountInfoFull struct {
// AccountInfo general account information with fees
type AccountInfo struct {
MakerFees string `json:"maker_fees"`
TakerFees string `json:"taker_fees"`
MakerFees float64 `json:"maker_fees,string"`
TakerFees float64 `json:"taker_fees,string"`
Fees []AccountInfoFees `json:"fees"`
Message string `json:"message"`
}
// AccountInfoFees general account information with fees
type AccountInfoFees struct {
Pairs string `json:"pairs"`
MakerFees string `json:"maker_fees"`
TakerFees string `json:"taker_fees"`
Pairs string `json:"pairs"`
MakerFees float64 `json:"maker_fees,string"`
TakerFees float64 `json:"taker_fees,string"`
}
// AccountFees stores withdrawal account fee data from Bitfinex
type AccountFees struct {
Withdraw struct {
BTC float64 `json:"BTC,string"`
LTC float64 `json:"LTC,string"`
ETH float64 `json:"ETH,string"`
ETC float64 `json:"ETC,string"`
ZEC float64 `json:"ZEC,string"`
XMR float64 `json:"XMR,string"`
DSH float64 `json:"DSH,string"`
XRP float64 `json:"XRP,string"`
IOT float64 `json:"IOT"`
EOS float64 `json:"EOS,string"`
SAN float64 `json:"SAN,string"`
OMG float64 `json:"OMG,string"`
BCH float64 `json:"BCH,string"`
} `json:"withdraw"`
Withdraw map[string]interface{} `json:"withdraw"`
}
// AccountSummary holds account summary data

View File

@@ -226,3 +226,8 @@ func (b *Bitfinex) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cu
func (b *Bitfinex) GetWebsocket() (*exchange.Websocket, error) {
return b.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitfinex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -385,3 +386,55 @@ func (b *Bitflyer) SendAuthHTTPRequest(path string, params url.Values, result in
headers["ACCESS-KEY"] = b.APIKey
headers["ACCESS-TIMESTAMP"] = strconv.FormatInt(int64(time.Now().UnixNano()), 10)
}
// GetFee returns an estimate of fee based on type of transaction
// TODO: Figure out the weird fee structure. Do we use Bitcoin Easy Exchange,Lightning Spot,Bitcoin Market,Lightning FX/Futures ???
func (b *Bitflyer) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.InternationalBankDepositFee:
fee = getDepositFee(feeBuilder.BankTransactionType, feeBuilder.CurrencyItem, feeBuilder.Amount)
case exchange.InternationalBankWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.BankTransactionType, feeBuilder.CurrencyItem, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// getDepositFee returns fee when performing a trade
func calculateTradingFee(purchasePrice float64, amount float64) float64 {
fee := 0.0015
// bitflyer has fee tiers, but does not disclose them via API, so the largest has to be assumed
return fee * amount * purchasePrice
}
func getDepositFee(bankTransactionType exchange.InternationalBankTransactionType, currency string, amount float64) (fee float64) {
switch bankTransactionType {
case exchange.WireTransfer:
switch currency {
case symbol.JPY:
fee = 324
}
}
return fee
}
func getWithdrawalFee(bankTransactionType exchange.InternationalBankTransactionType, currency string, amount float64) (fee float64) {
switch bankTransactionType {
case exchange.WireTransfer:
switch currency {
case symbol.JPY:
if amount < 30000 {
fee = 540
} else {
fee = 756
}
}
}
return fee
}

View File

@@ -4,6 +4,9 @@ import (
"log"
"testing"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/pair"
)
@@ -118,33 +121,6 @@ func TestGetExchangeStatus(t *testing.T) {
}
}
// func TestGetChats(t *testing.T) {
// t.Parallel()
// time := time.Now().Format(time.RFC3339)
// _, err := b.GetChats(time)
// if err != nil {
// t.Error("test failed - Bitflyer - GetChats() error:", err)
// }
// }
// func TestUpdateTicker(t *testing.T) {
// t.Parallel()
// p := pair.NewCurrencyPairFromString("BTC_JPY")
// _, err := b.UpdateTicker(p, "SPOT")
// if err != nil {
// t.Error("test failed - Bitflyer - UpdateTicker() error:", err)
// }
// }
//
// func TestUpdateOrderbook(t *testing.T) {
// t.Parallel()
// p := pair.NewCurrencyPairFromString("BTC_JPY")
// _, err := b.UpdateOrderbook(p, "SPOT")
// if err != nil {
// t.Error("test failed - Bitflyer - UpdateOrderbook() error:", err)
// }
// }
func TestCheckFXString(t *testing.T) {
t.Parallel()
p := pair.NewCurrencyPairDelimiter("FXBTC_JPY", "_")
@@ -171,3 +147,91 @@ func TestGetTickerPrice(t *testing.T) {
t.Error("test failed - Bitflyer - GetTickerPrice() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.JPY,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if testAPIKey != "" || testAPISecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.1) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.1), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.JPY
if resp, err := b.GetFee(feeBuilder); resp != float64(324) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(324), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.JPY
if resp, err := b.GetFee(feeBuilder); resp != float64(540) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(540), resp)
t.Error(err)
}
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -564,3 +565,67 @@ func (b *Bithumb) SendAuthenticatedHTTPRequest(path string, params url.Values, r
return b.SendPayload("POST", b.APIUrl+path, headers, bytes.NewBufferString(payload), result, true, b.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Bithumb) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CyptocurrencyDepositFee:
fee = getDepositFee(feeBuilder.FirstCurrency, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// getDepositFee returns fee when performing a trade
func calculateTradingFee(purchasePrice float64, amount float64) float64 {
fee := 0.0015
return fee * amount * purchasePrice
}
// getDepositFee returns fee on a currency when depositing small amounts to bithumb
func getDepositFee(currency string, amount float64) float64 {
var fee float64
switch currency {
case symbol.BTC:
if amount <= 0.005 {
fee = 0.001
}
case symbol.LTC:
if amount <= 0.3 {
fee = 0.01
}
case symbol.DASH:
if amount <= 0.04 {
fee = 0.01
}
case symbol.BCH:
if amount <= 0.03 {
fee = 0.001
}
case symbol.ZEC:
if amount <= 0.02 {
fee = 0.001
}
case symbol.BTG:
if amount <= 0.15 {
fee = 0.001
}
}
return fee
}
// getWithdrawalFee returns fee on a currency when withdrawing out of bithumb
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own keys here for due diligence testing
@@ -185,34 +187,86 @@ func TestMarketSellOrder(t *testing.T) {
}
}
// func TestRun(t *testing.T) {
// t.Parallel()
// b.Run()
// }
//
// func TestUpdateTicker(t *testing.T) {
// t.Parallel()
// pair := b.GetEnabledCurrencies()[0]
// _, err := b.UpdateTicker(pair, b.AssetTypes[0])
// if err != nil {
// t.Error("test failed - Bithumb UpdateTicker() error", err)
// }
// }
//
// func TestGetTickerPrice(t *testing.T) {
// t.Parallel()
// pair := b.GetEnabledCurrencies()[0]
// _, err := b.GetTickerPrice(pair, b.AssetTypes[0])
// if err != nil {
// t.Error("test failed - Bithumb GetTickerPrice() error", err)
// }
// }
//
// func TestGetOrderbookEx(t *testing.T) {
// t.Parallel()
// pair := b.GetEnabledCurrencies()[0]
// _, err := b.GetOrderbookEx(pair, b.AssetTypes[0])
// if err != nil {
// t.Error("test failed - Bithumb GetOrderbookEx() error", err)
// }
// }
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0015), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(1500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(1500), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0015), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package bithumb
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Ticker holds ticker data
type Ticker struct {
OpeningPrice float64 `json:"opening_price,string"`
@@ -227,3 +229,52 @@ type MarketSell struct {
} `json:"data"`
Message string `json:"message"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.KRW: 1000,
symbol.BTC: 0.001,
symbol.ETH: 0.01,
symbol.DASH: 0.01,
symbol.LTC: 0.01,
symbol.ETC: 0.01,
symbol.XRP: 1,
symbol.BCH: 0.001,
symbol.XMR: 0.05,
symbol.ZEC: 0.001,
symbol.QTUM: 0.05,
symbol.BTG: 0.001,
symbol.ICX: 1,
symbol.TRX: 5,
symbol.ELF: 5,
symbol.MITH: 5,
symbol.MCO: 0.5,
symbol.OMG: 0.4,
symbol.KNC: 3,
symbol.GNT: 12,
symbol.HSR: 0.2,
symbol.ZIL: 30,
symbol.ETHOS: 2,
symbol.PAY: 2.4,
symbol.WAX: 5,
symbol.POWR: 5,
symbol.LRC: 10,
symbol.GTO: 15,
symbol.STEEM: 0.01,
symbol.STRAT: 0.2,
symbol.PPT: 0.5,
symbol.CTXC: 4,
symbol.CMT: 20,
symbol.THETA: 24,
symbol.WTC: 0.7,
symbol.ITC: 5,
symbol.TRUE: 4,
symbol.ABT: 5,
symbol.RNT: 20,
symbol.PLY: 20,
symbol.WAVES: 0.01,
symbol.LINK: 10,
symbol.ENJ: 35,
symbol.PST: 30,
}

View File

@@ -193,3 +193,8 @@ func (b *Bithumb) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cur
func (b *Bithumb) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bithumb) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -912,3 +912,29 @@ func (b *Bitmex) CaptureError(resp, reType interface{}) error {
}
return nil
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Bitmex) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
var err error
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
}
if fee < 0 {
fee = 0
}
return fee, err
}
// calculateTradingFee returns the fee for trading any currency on Bittrex
func calculateTradingFee(purchasePrice float64, amount float64, isMaker bool) float64 {
var fee = 0.000750
if isMaker {
fee -= 0.000250
}
return fee * purchasePrice * amount
}

View File

@@ -6,6 +6,8 @@ import (
"time"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own keys here for due diligence testing
@@ -363,3 +365,87 @@ func TestGetPreviousTrades(t *testing.T) {
t.Error("test failed - GetPreviousTrades() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00075) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.00075), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(750) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(750), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0005), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -197,3 +197,8 @@ func (b *Bitmex) WithdrawExchangeFiatFundsToInternationalBank(currency pair.Curr
func (b *Bitmex) GetWebsocket() (*exchange.Websocket, error) {
return b.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitmex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -129,22 +130,74 @@ func (b *Bitstamp) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns fee on a currency pair
func (b *Bitstamp) GetFee(currencyPair string) float64 {
switch currencyPair {
case "BTCUSD":
return b.Balance.BTCUSDFee
case "BTCEUR":
return b.Balance.BTCEURFee
case "XRPEUR":
return b.Balance.XRPEURFee
case "XRPUSD":
return b.Balance.XRPUSDFee
case "EURUSD":
return b.Balance.EURUSDFee
default:
return 0
// GetFee returns an estimate of fee based on type of transaction
func (b *Bitstamp) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
var err error
b.Balance, err = b.GetBalance()
if err != nil {
return 0, err
}
fee = b.CalculateTradingFee(feeBuilder.FirstCurrency+feeBuilder.SecondCurrency, feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CyptocurrencyDepositFee:
fee = 0
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.Amount)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
// getInternationalBankWithdrawalFee returns international withdrawal fee
func getInternationalBankWithdrawalFee(amount float64) float64 {
fee := amount * 0.0009
if fee < 15 {
return 15
}
return fee
}
// getInternationalBankDepositFee returns international deposit fee
func getInternationalBankDepositFee(amount float64) float64 {
fee := amount * 0.0005
if fee < 7.5 {
return 7.5
}
if fee > 300 {
return 300
}
return fee
}
// CalculateTradingFee returns fee on a currency pair
func (b *Bitstamp) CalculateTradingFee(currency string, purchasePrice float64, amount float64) float64 {
var fee float64
switch currency {
case symbol.BTC + symbol.USD:
fee = b.Balance.BTCUSDFee
case symbol.BTC + symbol.EUR:
fee = b.Balance.BTCEURFee
case symbol.XRP + symbol.EUR:
fee = b.Balance.XRPEURFee
case symbol.XRP + symbol.USD:
fee = b.Balance.XRPUSDFee
case symbol.EUR + symbol.USD:
fee = b.Balance.EURUSDFee
default:
fee = 0
}
return fee * purchasePrice * amount
}
// GetTicker returns ticker information

View File

@@ -5,6 +5,9 @@ import (
"testing"
"time"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/config"
)
@@ -53,23 +56,118 @@ func TestSetup(t *testing.T) {
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
if resp := b.GetFee("BTCUSD"); resp != 0 {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(7.5) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(7.5), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(15) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(15), resp)
t.Error(err)
}
}
func TestCalculateTradingFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
b.Balance = Balances{}
b.Balance.BTCUSDFee = 1
b.Balance.BTCEURFee = 0
if resp := b.CalculateTradingFee(symbol.BTC+symbol.USD, 0, 0); resp != 0 {
t.Error("Test Failed - GetFee() error")
}
if resp := b.GetFee("bla"); resp != 0 {
if resp := b.CalculateTradingFee(symbol.BTC+symbol.USD, 2, 2); resp != float64(4) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(4), resp)
}
if resp := b.CalculateTradingFee(symbol.BTC+symbol.EUR, 2, 2); resp != float64(0) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
if resp := b.CalculateTradingFee("bla", 0, 0); resp != 0 {
t.Error("Test Failed - GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := b.GetTicker("BTCUSD", false)
_, err := b.GetTicker(symbol.BTC+symbol.USD, false)
if err != nil {
t.Error("Test Failed - GetTicker() error", err)
}
_, err = b.GetTicker("BTCUSD", true)
_, err = b.GetTicker(symbol.BTC+symbol.USD, true)
if err != nil {
t.Error("Test Failed - GetTicker() error", err)
}
@@ -77,7 +175,7 @@ func TestGetTicker(t *testing.T) {
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := b.GetOrderbook("BTCUSD")
_, err := b.GetOrderbook(symbol.BTC + symbol.USD)
if err != nil {
t.Error("Test Failed - GetOrderbook() error", err)
}
@@ -96,7 +194,7 @@ func TestGetTransactions(t *testing.T) {
value := url.Values{}
value.Set("time", "hour")
_, err := b.GetTransactions("BTCUSD", value)
_, err := b.GetTransactions(symbol.BTC+symbol.USD, value)
if err != nil {
t.Error("Test Failed - GetTransactions() error", err)
}

View File

@@ -77,6 +77,12 @@ func (b *Bitstamp) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker
return tick, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitstamp) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetOrderbookEx returns the orderbook for a currency pair
func (b *Bitstamp) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
ob, err := orderbook.GetOrderbook(b.GetName(), p, assetType)

View File

@@ -511,3 +511,43 @@ func (b *Bittrex) SendAuthenticatedHTTPRequest(path string, values url.Values, r
return b.SendPayload("GET", rawQuery, headers, nil, result, true, b.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Bittrex) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
var err error
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee, err = b.GetWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, err
}
// GetWithdrawalFee returns the fee for withdrawing from the exchange
func (b *Bittrex) GetWithdrawalFee(currency string) (float64, error) {
var fee float64
currencies, err := b.GetCurrencies()
if err != nil {
return 0, err
}
for _, result := range currencies.Result {
if result.Currency == currency {
fee = result.TxFee
}
}
return fee, nil
}
// calculateTradingFee returns the fee for trading any currency on Bittrex
func calculateTradingFee(purchasePrice float64, amount float64) float64 {
var fee = 0.0025
return fee * purchasePrice * amount
}

View File

@@ -5,6 +5,8 @@ import (
"time"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply you own test keys here to run better tests.
@@ -229,3 +231,87 @@ func TestGetDepositHistory(t *testing.T) {
t.Error("Test Failed - Bittrex - GetDepositHistory() error")
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0025), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(2500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2500), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0025), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0005), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.HKD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -222,3 +222,9 @@ func (b *Bittrex) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cur
func (b *Bittrex) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bittrex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -93,7 +93,31 @@ func (b *BTCC) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the fees associated with transactions
func (b *BTCC) GetFee() float64 {
return b.Fee
// GetFee returns an estimate of fee based on type of transaction
func (b *BTCC) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func getCryptocurrencyWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func getInternationalBankWithdrawalFee(currency string, amount float64) float64 {
var fee float64
fee = WithdrawalFees[currency] * amount
return fee
}

View File

@@ -5,6 +5,8 @@ import (
"time"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own APIkeys here to do better tests
@@ -36,12 +38,6 @@ func TestSetup(t *testing.T) {
}
}
func TestGetFee(t *testing.T) {
if b.GetFee() != 0 {
t.Error("Test failed - GetFee() error")
}
}
// func TestGetTicker(t *testing.T) {
// t.Skip()
// _, err := b.GetTicker("BTCUSD")
@@ -77,3 +73,86 @@ func TestGetFee(t *testing.T) {
// t.Error("Test failed - GetAccountInfo() error", err)
// }
// }
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := b.GetFee(feeBuilder); resp != float64(0.005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.005), resp)
t.Error(err)
}
}

View File

@@ -1,6 +1,7 @@
package btcc
import "encoding/json"
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// WsAllTickerData defines multiple ticker data
type WsAllTickerData []WsTicker
@@ -80,3 +81,15 @@ type WsTicker struct {
ExecutionLimitUp float64 `json:"ExecutionLimitUp"`
MsgType string `json:"MsgType"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.USD: 0.005,
symbol.USDT: 10,
symbol.BTC: 0.001,
symbol.ETH: 0.01,
symbol.BCH: 0.0001,
symbol.LTC: 0.001,
symbol.DASH: 0.002,
}

View File

@@ -204,3 +204,8 @@ func (b *BTCC) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curren
func (b *BTCC) GetWebsocket() (*exchange.Websocket, error) {
return b.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *BTCC) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -19,6 +20,7 @@ const (
btcMarketsAPIURL = "https://api.btcmarkets.net"
btcMarketsAPIVersion = "0"
btcMarketsAccountBalance = "/account/balance"
btcMarketsTradingFee = "/account/%s/%s/tradingfee"
btcMarketsOrderCreate = "/order/create"
btcMarketsOrderCancel = "/order/cancel"
btcMarketsOrderHistory = "/order/history"
@@ -110,11 +112,6 @@ func (b *BTCMarkets) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the BTCMarkets fee on transactions
func (b *BTCMarkets) GetFee() float64 {
return b.Fee
}
// GetMarkets returns the BTCMarkets instruments
func (b *BTCMarkets) GetMarkets() ([]Market, error) {
type marketsResp struct {
@@ -347,6 +344,13 @@ func (b *BTCMarkets) GetAccountBalance() ([]AccountBalance, error) {
return balance, nil
}
// GetTradingFee returns the account's trading fee for a currency pair
func (b *BTCMarkets) GetTradingFee(firstPair, secondPair string) (TradingFee, error) {
var tradingFee TradingFee
path := fmt.Sprintf(btcMarketsTradingFee, firstPair, secondPair)
return tradingFee, b.SendAuthenticatedRequest("GET", path, nil, &tradingFee)
}
// WithdrawCrypto withdraws cryptocurrency into a designated address
func (b *BTCMarkets) WithdrawCrypto(amount float64, currency, address string) (string, error) {
newAmount := int64(amount * float64(common.SatoshisPerBTC))
@@ -442,3 +446,44 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interfa
return b.SendPayload(reqType, b.APIUrl+path, headers, bytes.NewBuffer(payload), result, true, b.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (b *BTCMarkets) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
tradingFee, err := b.GetTradingFee(feeBuilder.FirstCurrency, feeBuilder.SecondCurrency)
if err != nil {
return 0, err
}
fee = calculateTradingFee(feeBuilder.FirstCurrency+feeBuilder.Delimiter+feeBuilder.SecondCurrency, tradingFee, feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(curr string, tradingFee TradingFee, purchasePrice, amount float64) (fee float64) {
fee = tradingFee.TradingFeeRate / 100000000
return fee * amount * purchasePrice
}
func getCryptocurrencyWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func getInternationalBankWithdrawalFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.AUD {
fee = 0
}
return fee
}

View File

@@ -6,10 +6,11 @@ import (
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var bm BTCMarkets
var b BTCMarkets
// Please supply your own keys here to do better tests
const (
@@ -18,7 +19,7 @@ const (
)
func TestSetDefaults(t *testing.T) {
bm.SetDefaults()
b.SetDefaults()
}
func TestSetup(t *testing.T) {
@@ -35,19 +36,12 @@ func TestSetup(t *testing.T) {
bConfig.AuthenticatedAPISupport = true
}
bm.Setup(bConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if fee := bm.GetFee(); fee == 0 {
t.Error("Test failed - GetFee() error")
}
b.Setup(bConfig)
}
func TestGetMarkets(t *testing.T) {
t.Parallel()
_, err := bm.GetMarkets()
_, err := b.GetMarkets()
if err != nil {
t.Error("Test failed - GetMarkets() error", err)
}
@@ -55,7 +49,7 @@ func TestGetMarkets(t *testing.T) {
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := bm.GetTicker("BTC", "AUD")
_, err := b.GetTicker("BTC", "AUD")
if err != nil {
t.Error("Test failed - GetTicker() error", err)
}
@@ -63,7 +57,7 @@ func TestGetTicker(t *testing.T) {
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := bm.GetOrderbook("BTC", "AUD")
_, err := b.GetOrderbook("BTC", "AUD")
if err != nil {
t.Error("Test failed - GetOrderbook() error", err)
}
@@ -71,14 +65,14 @@ func TestGetOrderbook(t *testing.T) {
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := bm.GetTrades("BTC", "AUD", nil)
_, err := b.GetTrades("BTC", "AUD", nil)
if err != nil {
t.Error("Test failed - GetTrades() error", err)
}
val := url.Values{}
val.Set("since", "0")
_, err = bm.GetTrades("BTC", "AUD", val)
_, err = b.GetTrades("BTC", "AUD", val)
if err != nil {
t.Error("Test failed - GetTrades() error", err)
}
@@ -86,7 +80,7 @@ func TestGetTrades(t *testing.T) {
func TestNewOrder(t *testing.T) {
t.Parallel()
_, err := bm.NewOrder("AUD", "BTC", 0, 0, "Bid", "limit", "testTest")
_, err := b.NewOrder("AUD", "BTC", 0, 0, "Bid", "limit", "testTest")
if err == nil {
t.Error("Test failed - NewOrder() error", err)
}
@@ -94,7 +88,7 @@ func TestNewOrder(t *testing.T) {
func TestCancelOrder(t *testing.T) {
t.Parallel()
_, err := bm.CancelOrder([]int64{1337})
_, err := b.CancelOrder([]int64{1337})
if err == nil {
t.Error("Test failed - CancelOrder() error", err)
}
@@ -102,11 +96,11 @@ func TestCancelOrder(t *testing.T) {
func TestGetOrders(t *testing.T) {
t.Parallel()
_, err := bm.GetOrders("AUD", "BTC", 10, 0, false)
_, err := b.GetOrders("AUD", "BTC", 10, 0, false)
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
_, err = bm.GetOrders("AUD", "BTC", 10, 0, true)
_, err = b.GetOrders("AUD", "BTC", 10, 0, true)
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
@@ -114,7 +108,7 @@ func TestGetOrders(t *testing.T) {
func TestGetOrderDetail(t *testing.T) {
t.Parallel()
_, err := bm.GetOrderDetail([]int64{1337})
_, err := b.GetOrderDetail([]int64{1337})
if err == nil {
t.Error("Test failed - GetOrderDetail() error", err)
}
@@ -122,7 +116,7 @@ func TestGetOrderDetail(t *testing.T) {
func TestGetAccountBalance(t *testing.T) {
t.Parallel()
_, err := bm.GetAccountBalance()
_, err := b.GetAccountBalance()
if err == nil {
t.Error("Test failed - GetAccountBalance() error", err)
}
@@ -130,7 +124,7 @@ func TestGetAccountBalance(t *testing.T) {
func TestWithdrawCrypto(t *testing.T) {
t.Parallel()
_, err := bm.WithdrawCrypto(0, "BTC", "LOLOLOL")
_, err := b.WithdrawCrypto(0, "BTC", "LOLOLOL")
if err == nil {
t.Error("Test failed - WithdrawCrypto() error", err)
}
@@ -138,21 +132,21 @@ func TestWithdrawCrypto(t *testing.T) {
func TestWithdrawAUD(t *testing.T) {
t.Parallel()
_, err := bm.WithdrawAUD("BLA", "1337", "blawest", "1336", 10000000)
_, err := b.WithdrawAUD("BLA", "1337", "blawest", "1336", 10000000)
if err == nil {
t.Error("Test failed - WithdrawAUD() error", err)
}
}
func TestGetExchangeAccountInfo(t *testing.T) {
_, err := bm.GetExchangeAccountInfo()
_, err := b.GetExchangeAccountInfo()
if err == nil {
t.Error("Test failed - GetExchangeAccountInfo() error", err)
}
}
func TestGetExchangeFundTransferHistory(t *testing.T) {
_, err := bm.GetExchangeFundTransferHistory()
_, err := b.GetExchangeFundTransferHistory()
if err == nil {
t.Error("Test failed - GetExchangeAccountInfo() error", err)
}
@@ -160,50 +154,145 @@ func TestGetExchangeFundTransferHistory(t *testing.T) {
func TestSubmitExchangeOrder(t *testing.T) {
p := pair.NewCurrencyPair("LTC", "AUD")
_, err := bm.SubmitExchangeOrder(p, exchange.OrderSideSell(), exchange.OrderTypeMarket(), 0, 0.0, "testID001")
_, err := b.SubmitExchangeOrder(p, exchange.OrderSideSell(), exchange.OrderTypeMarket(), 0, 0.0, "testID001")
if err == nil {
t.Error("Test failed - SubmitExchangeOrder() error", err)
}
}
func TestModifyExchangeOrder(t *testing.T) {
_, err := bm.ModifyExchangeOrder(1337, exchange.ModifyOrder{})
_, err := b.ModifyExchangeOrder(1337, exchange.ModifyOrder{})
if err == nil {
t.Error("Test failed - ModifyExchangeOrder() error", err)
}
}
func TestCancelExchangeOrder(t *testing.T) {
err := bm.CancelExchangeOrder(1337)
err := b.CancelExchangeOrder(1337)
if err == nil {
t.Error("Test failed - CancelExchangeOrder() error", err)
}
}
func TestCancelAllExchangeOrders(t *testing.T) {
err := bm.CancelAllExchangeOrders()
err := b.CancelAllExchangeOrders()
if err == nil {
t.Error("Test failed - CancelAllExchangeOrders() error", err)
}
}
func TestGetExchangeOrderInfo(t *testing.T) {
_, err := bm.GetExchangeOrderInfo(1337)
_, err := b.GetExchangeOrderInfo(1337)
if err == nil {
t.Error("Test failed - GetExchangeOrderInfo() error", err)
}
}
func TestWithdrawCryptoExchangeFunds(t *testing.T) {
_, err := bm.WithdrawCryptoExchangeFunds("someaddress", "ltc", 0)
_, err := b.WithdrawCryptoExchangeFunds("someaddress", "ltc", 0)
if err == nil {
t.Error("Test failed - WithdrawExchangeFunds() error", err)
}
}
func TestWithdrawFiatExchangeFunds(t *testing.T) {
_, err := bm.WithdrawFiatExchangeFunds("AUD", 0)
_, err := b.WithdrawFiatExchangeFunds("AUD", 0)
if err == nil {
t.Error("Test failed - WithdrawFiatExchangeFunds() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
b.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if apiKey != "" || apiSecret != "" {
// CryptocurrencyTradeFee Fiat
feeBuilder = setFeeBuilder()
feeBuilder.SecondCurrency = symbol.USD
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00849999) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.00849999), resp)
}
// CryptocurrencyTradeFee Basic
feeBuilder = setFeeBuilder()
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0022) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0022), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := b.GetFee(feeBuilder); resp != float64(2200) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(22000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0022) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0022), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.AUD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.AUD
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package btcmarkets
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Response is the genralized response type
type Response struct {
Success bool `json:"success"`
@@ -51,6 +53,15 @@ type Trade struct {
Date int64 `json:"date"`
}
// 30 day trade volume
type TradingFee struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
TradingFeeRate float64 `json:"tradingfeerate"`
Volume30Day float64 `json:"volume30day"`
}
// OrderToGo holds order information to be sent to the exchange
type OrderToGo struct {
Currency string `json:"currency"`
@@ -112,3 +123,17 @@ type WithdrawRequestAUD struct {
BankName string `json:"bankName"`
BSBNumber string `json:"bsbNumber"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.AUD: 0,
symbol.BTC: 0.001,
symbol.ETH: 0.001,
symbol.ETC: 0.001,
symbol.LTC: 0.0001,
symbol.XRP: 0.15,
symbol.BCH: 0.0001,
symbol.OMG: 0.15,
symbol.POWR: 5,
}

View File

@@ -255,3 +255,8 @@ func (b *BTCMarkets) WithdrawFiatExchangeFundsToInternationalBank(currency pair.
func (b *BTCMarkets) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *BTCMarkets) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}

View File

@@ -7,11 +7,13 @@ import (
"log"
"net/url"
"strconv"
"strings"
"time"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -134,14 +136,6 @@ func (c *CoinbasePro) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the current fee for the exchange
func (c *CoinbasePro) GetFee(maker bool) float64 {
if maker {
return c.MakerFee
}
return c.TakerFee
}
// GetProducts returns supported currency pairs on the exchange with specific
// information about the pair
func (c *CoinbasePro) GetProducts() ([]Product, error) {
@@ -828,3 +822,70 @@ func (c *CoinbasePro) SendAuthenticatedHTTPRequest(method, path string, params m
return c.SendPayload(method, c.APIUrl+path, headers, bytes.NewBuffer(payload), result, true, c.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (c *CoinbasePro) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
trailingVolume, err := c.GetTrailingVolume()
if err != nil {
return 0, err
}
fee = c.calculateTradingFee(trailingVolume, feeBuilder.FirstCurrency, feeBuilder.Delimiter, feeBuilder.SecondCurrency, feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func (c *CoinbasePro) calculateTradingFee(trailingVolume []Volume, firstCurrency, delimiter, secondCurrency string, purchasePrice, amount float64, isMaker bool) float64 {
var fee float64
for _, i := range trailingVolume {
if strings.EqualFold(i.ProductID, firstCurrency+delimiter+secondCurrency) {
if isMaker {
fee = 0
} else if i.Volume <= 10000000 {
fee = 0.003
} else if i.Volume > 10000000 && i.Volume <= 100000000 {
fee = 0.002
} else if i.Volume > 100000000 {
fee = 0.001
}
break
}
}
return fee * amount * purchasePrice
}
func getInternationalBankWithdrawalFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.USD {
fee = 25
} else if currency == symbol.EUR {
fee = 0.15
}
return fee
}
func getInternationalBankDepositFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.USD {
fee = 10
} else if currency == symbol.EUR {
fee = 0.15
}
return fee
}

View File

@@ -5,6 +5,8 @@ import (
"time"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var c CoinbasePro
@@ -32,15 +34,6 @@ func TestSetup(t *testing.T) {
c.Setup(gdxConfig)
}
func TestGetFee(t *testing.T) {
if c.GetFee(false) == 0 {
t.Error("Test failed - GetFee() error")
}
if c.GetFee(true) != 0 {
t.Error("Test failed - GetFee() error")
}
}
func TestGetProducts(t *testing.T) {
_, err := c.GetProducts()
if err != nil {
@@ -224,3 +217,176 @@ func TestAuthRequests(t *testing.T) {
}
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
c.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if apiKey != "" || apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := c.GetFee(feeBuilder); resp != float64(0.003) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.003), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := c.GetFee(feeBuilder); resp != float64(3000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(3000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.01), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.EUR
if resp, err := c.GetFee(feeBuilder); resp != float64(0.15) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := c.GetFee(feeBuilder); resp != float64(25) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
func TestCalculateTradingFee(t *testing.T) {
t.Parallel()
// uppercase
var volume = []Volume{
Volume{
ProductID: "BTC_USD",
Volume: 100,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, false); resp != float64(0.003) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.003), resp)
}
// lowercase
volume = []Volume{
Volume{
ProductID: "btc_usd",
Volume: 100,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, false); resp != float64(0.003) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.003), resp)
}
// mixedCase
volume = []Volume{
Volume{
ProductID: "btc_USD",
Volume: 100,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, false); resp != float64(0.003) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.003), resp)
}
// medium volume
volume = []Volume{
Volume{
ProductID: "btc_USD",
Volume: 10000001,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, false); resp != float64(0.002) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// high volume
volume = []Volume{
Volume{
ProductID: "btc_USD",
Volume: 100000010000,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, false); resp != float64(0.001) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
}
// no match
volume = []Volume{
Volume{
ProductID: "btc_beeteesee",
Volume: 100000010000,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, false); resp != float64(0) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// taker
volume = []Volume{
Volume{
ProductID: "btc_USD",
Volume: 100000010000,
},
}
if resp := c.calculateTradingFee(volume, "btc", "_", "usd", 1, 1, true); resp != float64(0) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
}

View File

@@ -191,3 +191,8 @@ func (c *CoinbasePro) WithdrawFiatExchangeFunds(cryptocurrency pair.CurrencyItem
func (c *CoinbasePro) GetWebsocket() (*exchange.Websocket, error) {
return c.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (c *CoinbasePro) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return c.GetFee(feeBuilder)
}

View File

@@ -10,6 +10,8 @@ import (
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -330,3 +332,82 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{
return c.SendPayload("POST", c.APIUrl, headers, bytes.NewBuffer(payload), result, authenticated, c.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (c *COINUT) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = c.calculateTradingFee(feeBuilder.FirstCurrency, feeBuilder.SecondCurrency, feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.CurrencyItem, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func (c *COINUT) calculateTradingFee(firstCurrency, secondCurrency string, purchasePrice, amount float64, isMaker bool) float64 {
var fee float64
if isMaker {
fee = 0
} else if currency.IsCryptocurrency(firstCurrency) && !currency.IsCryptocurrency(secondCurrency) ||
!currency.IsCryptocurrency(firstCurrency) && currency.IsCryptocurrency(secondCurrency) {
fee = 0.002
} else {
fee = 0.001
}
return fee * amount * purchasePrice
}
func getInternationalBankWithdrawalFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.USD {
if amount*0.001 < 10 {
fee = 10
} else {
fee = amount * 0.001
}
} else if currency == symbol.CAD {
if amount*0.005 < 10 {
fee = 2
} else {
fee = amount * 0.005
}
} else if currency == symbol.SGD {
if amount*0.001 < 10 {
fee = 10
} else {
fee = amount * 0.001
}
}
return fee
}
func getInternationalBankDepositFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.USD {
if amount*0.001 < 10 {
fee = 10
} else {
fee = amount * 0.001
}
} else if currency == symbol.CAD {
if amount*0.005 < 10 {
fee = 2
} else {
fee = amount * 0.005
}
}
return fee
}

View File

@@ -5,6 +5,8 @@ import (
"time"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var c COINUT
@@ -42,3 +44,133 @@ func TestGetInstruments(t *testing.T) {
t.Error("Test failed - GetInstruments() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
}
}
func TestGetFee(t *testing.T) {
c.SetDefaults()
TestSetup(t)
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := c.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0010), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := c.GetFee(feeBuilder); resp != float64(1000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(1000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.EUR
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := c.GetFee(feeBuilder); resp != float64(10) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(10), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.SGD
if resp, err := c.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := c.GetFee(feeBuilder); resp != float64(10) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(10), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.CAD
if resp, err := c.GetFee(feeBuilder); resp != float64(2) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.SGD
if resp, err := c.GetFee(feeBuilder); resp != float64(10) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(10), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.CAD
if resp, err := c.GetFee(feeBuilder); resp != float64(2) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2), resp)
t.Error(err)
}
}

View File

@@ -194,3 +194,8 @@ func (c *COINUT) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curr
func (c *COINUT) GetWebsocket() (*exchange.Websocket, error) {
return c.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (c *COINUT) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return c.GetFee(feeBuilder)
}

View File

@@ -29,6 +29,59 @@ const (
DefaultHTTPTimeout = time.Second * 15
)
// FeeType custom type for calculating fees based on method
type FeeType string
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types
type InternationalBankTransactionType string
// Const declarations for fee types
const (
BankFee FeeType = "bankFee"
InternationalBankDepositFee FeeType = "internationalBankDepositFee"
InternationalBankWithdrawalFee FeeType = "internationalBankWithdrawalFee"
CryptocurrencyTradeFee FeeType = "cryptocurrencyTradeFee"
CyptocurrencyDepositFee FeeType = "cyptocurrencyDepositFee"
CryptocurrencyWithdrawalFee FeeType = "cryptocurrencyWithdrawalFee"
)
// Const declarations for international transaction types
const (
WireTransfer InternationalBankTransactionType = "wireTransfer"
PerfectMoney InternationalBankTransactionType = "perfectMoney"
Neteller InternationalBankTransactionType = "neteller"
AdvCash InternationalBankTransactionType = "advCash"
Payeer InternationalBankTransactionType = "payeer"
Skrill InternationalBankTransactionType = "skrill"
Simplex InternationalBankTransactionType = "simplex"
SEPA InternationalBankTransactionType = "sepa"
RapidTransfer InternationalBankTransactionType = "rapidTransfer"
MisterTangoSEPA InternationalBankTransactionType = "misterTangoSepa"
Qiwi InternationalBankTransactionType = "qiwi"
VisaMastercard InternationalBankTransactionType = "visaMastercard"
WebMoney InternationalBankTransactionType = "webMoney"
Capitalist InternationalBankTransactionType = "capitalist"
WesternUnion InternationalBankTransactionType = "westernUnion"
MoneyGram InternationalBankTransactionType = "moneyGram"
Contact InternationalBankTransactionType = "contact"
)
// FeeBuilder is the type which holds all parameters required to calculate a fee for an exchange
type FeeBuilder struct {
FeeType FeeType
//Used for calculating crypto trading fees, deposits & withdrawals
FirstCurrency string
SecondCurrency string
Delimiter string
IsMaker bool
// Fiat currency used for bank deposits & withdrawals
CurrencyItem string
BankTransactionType InternationalBankTransactionType
// Used to multiply for fee calculations
PurchasePrice float64
Amount float64
}
// AccountInfo is a Generic type to hold each exchange's holdings in
// all enabled currencies
type AccountInfo struct {

View File

@@ -11,6 +11,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -363,3 +364,161 @@ func (e *EXMO) SendAuthenticatedHTTPRequest(method, endpoint string, vals url.Va
return e.SendPayload(method, path, headers, strings.NewReader(payload), result, true, e.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (e *EXMO) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = e.calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount, feeBuilder.BankTransactionType)
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.CurrencyItem, feeBuilder.Amount, feeBuilder.BankTransactionType)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func getCryptocurrencyWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func (e *EXMO) calculateTradingFee(purchasePrice, amount float64) float64 {
fee := 0.002
return fee * amount * purchasePrice
}
func calculateTradingFee(purchasePrice, amount float64) float64 {
fee := 0.002
return fee * amount * purchasePrice
}
func getInternationalBankWithdrawalFee(currency string, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {
var fee float64
switch bankTransactionType {
case exchange.WireTransfer:
if currency == symbol.RUB {
fee = 3200
} else if currency == symbol.PLN {
fee = 125
} else if currency == symbol.TRY {
fee = 0
}
case exchange.PerfectMoney:
switch currency {
case symbol.USD:
fee = 0.01 * amount
case symbol.EUR:
fee = 0.0195 * amount
}
case exchange.Neteller:
switch currency {
case symbol.USD:
fee = 0.0195 * amount
case symbol.EUR:
fee = 0.0195 * amount
}
case exchange.AdvCash:
switch currency {
case symbol.USD:
fee = 0.0295 * amount
case symbol.EUR:
fee = 0.03 * amount
case symbol.RUB:
fee = 0.0195 * amount
case symbol.UAH:
fee = 0.0495 * amount
}
case exchange.Payeer:
switch currency {
case symbol.USD:
fee = 0.0395 * amount
case symbol.EUR:
fee = 0.01 * amount
case symbol.RUB:
fee = 0.0595 * amount
}
case exchange.Skrill:
switch currency {
case symbol.USD:
fee = 0.0145 * amount
case symbol.EUR:
fee = 0.03 * amount
case symbol.TRY:
fee = 0
}
case exchange.VisaMastercard:
switch currency {
case symbol.USD:
fee = 0.06 * amount
case symbol.EUR:
fee = 0.06 * amount
case symbol.PLN:
fee = 0.06 * amount
}
}
return fee
}
func getInternationalBankDepositFee(currency string, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {
var fee float64
switch bankTransactionType {
case exchange.WireTransfer:
if currency == symbol.RUB {
fee = 1600
} else if currency == symbol.PLN {
fee = 30
} else if currency == symbol.TRY {
fee = 0
}
case exchange.Neteller:
switch currency {
case symbol.USD:
fee = (0.035 * amount) + 0.29
case symbol.EUR:
fee = (0.035 * amount) + 0.25
}
case exchange.AdvCash:
switch currency {
case symbol.USD:
fee = 0.0295 * amount
case symbol.EUR:
fee = 0.01 * amount
case symbol.RUB:
fee = 0.0495 * amount
case symbol.UAH:
fee = 0.01 * amount
}
case exchange.Payeer:
switch currency {
case symbol.USD:
fee = 0.0195 * amount
case symbol.EUR:
fee = 0.0295 * amount
case symbol.RUB:
fee = 0.0345 * amount
}
case exchange.Skrill:
switch currency {
case symbol.USD:
fee = (0.0495 * amount) + 0.36
case symbol.EUR:
fee = (0.0295 * amount) + 0.29
case symbol.PLN:
fee = (0.035 * amount) + 1.21
case symbol.TRY:
fee = 0
}
}
return fee
}

View File

@@ -1,6 +1,11 @@
package exmo
import "testing"
import (
"testing"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
const (
APIKey = ""
@@ -96,3 +101,135 @@ func TestGetDepositAddress(t *testing.T) {
t.Errorf("Test failed. Err: %s", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
e.SetDefaults()
TestSetup(t)
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := e.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := e.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := e.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := e.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := e.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0005), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := e.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := e.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.RUB
if resp, err := e.GetFee(feeBuilder); resp != float64(1600) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(1600), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
feeBuilder.CurrencyItem = symbol.PLN
if resp, err := e.GetFee(feeBuilder); resp != float64(30) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(30), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.PLN
if resp, err := e.GetFee(feeBuilder); resp != float64(125) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(125), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.TRY
if resp, err := e.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.EUR
if resp, err := e.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.RUB
if resp, err := e.GetFee(feeBuilder); resp != float64(3200) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(3200), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package exmo
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Trades holds trade data
type Trades struct {
TradeID int64 `json:"trade_id"`
@@ -142,3 +144,33 @@ type WalletHistory struct {
Account string `json:"account,string"`
}
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.BTC: 0.0005,
symbol.LTC: 0.01,
symbol.DOGE: 1,
symbol.DASH: 0.01,
symbol.ETH: 0.01,
symbol.WAVES: 0.001,
symbol.ZEC: 0.001,
symbol.USDT: 5,
symbol.XMR: 0.05,
symbol.XRP: 0.02,
symbol.KICK: 50,
symbol.ETC: 0.01,
symbol.BCH: 0.001,
symbol.BTG: 0.001,
symbol.HBZ: 65,
symbol.BTCZ: 5,
symbol.DXT: 20,
symbol.STQ: 100,
symbol.XLM: 0.001,
symbol.OMG: 0.5,
symbol.TRX: 1,
symbol.ADA: 1,
symbol.INK: 50,
symbol.ZRX: 1,
symbol.GNT: 1,
}

View File

@@ -229,3 +229,8 @@ func (e *EXMO) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curren
func (e *EXMO) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (e *EXMO) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return e.GetFee(feeBuilder)
}

View File

@@ -403,3 +403,41 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(method, endpoint, param string, re
return g.SendPayload(method, url, headers, strings.NewReader(param), result, true, g.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (g *Gateio) GetFee(feeBuilder exchange.FeeBuilder) (fee float64, err error) {
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
feePairs, err := g.GetMarketInfo()
if err != nil {
return 0, err
}
currencyPair := feeBuilder.FirstCurrency + feeBuilder.Delimiter + feeBuilder.SecondCurrency
var feeForPair float64
for _, i := range feePairs.Pairs {
if strings.EqualFold(currencyPair, i.Symbol) {
feeForPair = i.Fee
}
}
if feeForPair == 0 {
return 0, fmt.Errorf("Currency: '%s' failed to find fee data", currencyPair)
}
fee = calculateTradingFee(feeForPair, feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(feeForPair, purchasePrice, amount float64) float64 {
return (feeForPair / 100) * purchasePrice * amount
}
func getCryptocurrencyWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own APIKEYS here for due diligence testing
@@ -139,3 +141,97 @@ func TestGetSpotKline(t *testing.T) {
t.Errorf("Test failed - Gateio GetSpotKline: %s", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.USDT,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
g.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if apiKey != "" && apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := g.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := g.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := g.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := g.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := g.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := g.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := g.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := g.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := g.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,6 +1,10 @@
package gateio
import "time"
import (
"time"
"github.com/thrasher-/gocryptotrader/currency/symbol"
)
// SpotNewOrderRequestParamsType order type (buy or sell)
type SpotNewOrderRequestParamsType string
@@ -125,3 +129,212 @@ type SpotNewOrderResponse struct {
FilledAmount float64 `json:"filledAmount,string"` // The filled amount
Filledrate float64 `json:"filledRate,string"` // FilledPrice
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.USDT: 10,
symbol.USDT_ETH: 10,
symbol.BTC: 0.001,
symbol.BCH: 0.0006,
symbol.BTG: 0.002,
symbol.LTC: 0.002,
symbol.ZEC: 0.001,
symbol.ETH: 0.003,
symbol.ETC: 0.01,
symbol.DASH: 0.02,
symbol.QTUM: 0.1,
symbol.QTUM_ETH: 0.1,
symbol.DOGE: 50,
symbol.REP: 0.1,
symbol.BAT: 10,
symbol.SNT: 30,
symbol.BTM: 10,
symbol.BTM_ETH: 10,
symbol.CVC: 5,
symbol.REQ: 20,
symbol.RDN: 1,
symbol.STX: 3,
symbol.KNC: 1,
symbol.LINK: 8,
symbol.FIL: 0.1,
symbol.CDT: 20,
symbol.AE: 1,
symbol.INK: 10,
symbol.BOT: 5,
symbol.POWR: 5,
symbol.WTC: 0.2,
symbol.VET: 10,
symbol.RCN: 5,
symbol.PPT: 0.1,
symbol.ARN: 2,
symbol.BNT: 0.5,
symbol.VERI: 0.005,
symbol.MCO: 0.1,
symbol.MDA: 0.5,
symbol.FUN: 50,
symbol.DATA: 10,
symbol.RLC: 1,
symbol.ZSC: 20,
symbol.WINGS: 2,
symbol.GVT: 0.2,
symbol.KICK: 5,
symbol.CTR: 1,
symbol.HC: 0.2,
symbol.QBT: 5,
symbol.QSP: 5,
symbol.BCD: 0.02,
symbol.MED: 100,
symbol.QASH: 1,
symbol.DGD: 0.05,
symbol.GNT: 10,
symbol.MDS: 20,
symbol.SBTC: 0.05,
symbol.MANA: 50,
symbol.GOD: 0.1,
symbol.BCX: 30,
symbol.SMT: 50,
symbol.BTF: 0.1,
symbol.IOTA: 0.1,
symbol.NAS: 0.5,
symbol.NAS_ETH: 0.5,
symbol.TSL: 10,
symbol.ADA: 1,
symbol.LSK: 0.1,
symbol.WAVES: 0.1,
symbol.BIFI: 0.2,
symbol.XTZ: 0.1,
symbol.BNTY: 10,
symbol.ICX: 0.5,
symbol.LEND: 20,
symbol.LUN: 0.2,
symbol.ELF: 2,
symbol.SALT: 0.2,
symbol.FUEL: 2,
symbol.DRGN: 2,
symbol.GTC: 2,
symbol.MDT: 2,
symbol.QUN: 2,
symbol.GNX: 2,
symbol.DDD: 10,
symbol.OST: 4,
symbol.BTO: 10,
symbol.TIO: 10,
symbol.THETA: 10,
symbol.SNET: 10,
symbol.OCN: 10,
symbol.ZIL: 10,
symbol.RUFF: 10,
symbol.TNC: 10,
symbol.COFI: 10,
symbol.ZPT: 0.1,
symbol.JNT: 10,
symbol.GXS: 1,
symbol.MTN: 10,
symbol.BLZ: 2,
symbol.GEM: 2,
symbol.DADI: 2,
symbol.ABT: 2,
symbol.LEDU: 10,
symbol.RFR: 10,
symbol.XLM: 1,
symbol.MOBI: 1,
symbol.ONT: 1,
symbol.NEO: 0,
symbol.GAS: 0.02,
symbol.DBC: 10,
symbol.QLC: 10,
symbol.MKR: 0.003,
symbol.MKR_OLD: 0.003,
symbol.DAI: 2,
symbol.LRC: 10,
symbol.OAX: 10,
symbol.ZRX: 10,
symbol.PST: 5,
symbol.TNT: 20,
symbol.LLT: 10,
symbol.DNT: 1,
symbol.DPY: 2,
symbol.BCDN: 20,
symbol.STORJ: 3,
symbol.OMG: 0.2,
symbol.PAY: 1,
symbol.EOS: 0.1,
symbol.EON: 20,
symbol.IQ: 20,
symbol.EOSDAC: 20,
symbol.TIPS: 100,
symbol.XRP: 1,
symbol.CNC: 0.1,
symbol.TIX: 0.1,
symbol.XMR: 0.05,
symbol.BTS: 1,
symbol.XTC: 10,
symbol.BU: 0.1,
symbol.DCR: 0.02,
symbol.BCN: 10,
symbol.XMC: 0.05,
symbol.PPS: 0.01,
symbol.BOE: 5,
symbol.PLY: 10,
symbol.MEDX: 100,
symbol.TRX: 0.1,
symbol.SMT_ETH: 50,
symbol.CS: 10,
symbol.MAN: 10,
symbol.REM: 10,
symbol.LYM: 10,
symbol.INSTAR: 10,
symbol.BFT: 10,
symbol.IHT: 10,
symbol.SENC: 10,
symbol.TOMO: 10,
symbol.ELEC: 10,
symbol.SHIP: 10,
symbol.TFD: 10,
symbol.HAV: 10,
symbol.HUR: 10,
symbol.LST: 10,
symbol.LINO: 10,
symbol.SWTH: 5,
symbol.NKN: 5,
symbol.SOUL: 5,
symbol.GALA_NEO: 5,
symbol.LRN: 5,
symbol.ADD: 20,
symbol.MEETONE: 5,
symbol.DOCK: 20,
symbol.GSE: 20,
symbol.RATING: 20,
symbol.HSC: 100,
symbol.HIT: 100,
symbol.DX: 100,
symbol.BXC: 100,
symbol.PAX: 5,
symbol.GARD: 100,
symbol.FTI: 100,
symbol.SOP: 100,
symbol.LEMO: 20,
symbol.NPXS: 40,
symbol.QKC: 20,
symbol.IOTX: 20,
symbol.RED: 20,
symbol.LBA: 20,
symbol.KAN: 20,
symbol.OPEN: 20,
symbol.MITH: 20,
symbol.SKM: 20,
symbol.XVG: 20,
symbol.NANO: 20,
symbol.NBAI: 20,
symbol.UPP: 20,
symbol.ATMI: 20,
symbol.TMT: 20,
symbol.HT: 1,
symbol.BNB: 0.3,
symbol.BBK: 20,
symbol.EDR: 20,
symbol.MET: 0.3,
symbol.TCT: 20,
symbol.EXC: 10,
}

View File

@@ -180,3 +180,8 @@ func (g *Gateio) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curr
func (g *Gateio) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (g *Gateio) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return g.GetFee(feeBuilder)
}

View File

@@ -40,6 +40,7 @@ const (
geminiNewAddress = "newAddress"
geminiWithdraw = "withdraw/"
geminiHeartbeat = "heartbeat"
geminiVolume = "notionalvolume"
// gemini limit rates
geminiAuthRate = 600
@@ -389,6 +390,14 @@ func (g *Gemini) GetTradeHistory(currencyPair string, timestamp int64) ([]TradeH
g.SendAuthenticatedHTTPRequest("POST", geminiMyTrades, request, &response)
}
// GetNotionalVolume returns the volume in price currency that has been traded across all pairs over a period of 30 days
func (g *Gemini) GetNotionalVolume() (NotionalVolume, error) {
response := NotionalVolume{}
return response,
g.SendAuthenticatedHTTPRequest("POST", geminiVolume, nil, &response)
}
// GetTradeVolume returns a multi-arrayed volume response
func (g *Gemini) GetTradeVolume() ([][]TradeVolume, error) {
response := [][]TradeVolume{}
@@ -496,3 +505,35 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[st
return g.SendPayload(method, g.APIUrl+"/v1/"+path, headers, strings.NewReader(""), result, true, g.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (g *Gemini) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
notionVolume, err := g.GetNotionalVolume()
if err != nil {
return 0, err
}
fee = calculateTradingFee(notionVolume, feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CryptocurrencyWithdrawalFee:
// TODO: no free transactions after 10; Need database to know how many trades have been done
// Could do via trade history, but would require analysis of response and dates to determine level of fee
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(notionVolume NotionalVolume, purchasePrice, amount float64, isMaker bool) float64 {
var volumeFee float64
if isMaker {
volumeFee = (float64(notionVolume.MakerFee) / 100)
} else {
volumeFee = (float64(notionVolume.TakerFee) / 100)
}
return volumeFee * amount * purchasePrice
}

View File

@@ -5,6 +5,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please enter sandbox API keys & assigned roles for better testing procedures
@@ -58,14 +60,6 @@ func TestSetup(t *testing.T) {
Session[2].Setup(geminiConfig)
}
// func TestSandbox(t *testing.T) {
// t.Parallel()
// g.Sandbox(1)
// if Management[1].URL != geminiSandboxAPIURL {
// t.Error("Test Failed - Sandbox() error")
// }
// }
func TestGetSymbols(t *testing.T) {
t.Parallel()
_, err := Session[1].GetSymbols()
@@ -102,6 +96,16 @@ func TestGetTrades(t *testing.T) {
}
}
func TestGetNotionalVolume(t *testing.T) {
if apiKey2 != "" && apiSecret2 != "" {
t.Parallel()
_, err := Session[2].GetNotionalVolume()
if err != nil {
t.Error("Test Failed - GetNotionalVolume() error", err)
}
}
}
func TestGetAuction(t *testing.T) {
t.Parallel()
_, err := Session[1].GetAuction("btcusd")
@@ -213,3 +217,95 @@ func TestPostHeartbeat(t *testing.T) {
t.Error("Test Failed - PostHeartbeat() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
if apiKey1 != "" && apiSecret1 != "" {
// CryptocurrencyTradeFee Basic
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0.01) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.01), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(100) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(100), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0.01) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.01), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := Session[1].GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -140,6 +140,24 @@ type TradeVolume struct {
SellTakerCount float64 `json:"sell_taker_count"`
}
// NotionalVolume api call for fees
type NotionalVolume struct {
MakerFee int64 `json:"maker_fee_bps"`
TakerFee int64 `json:"taker_fee_bps"`
AuctionFee int64 `json:"auction_fee_bps"`
ThirtyDayVolume float64 `json:"notional_30d_volume"`
LastedUpdated int64 `json:"last_updated_ms"`
AccountID int64 `json:"account_id"`
Date string `json:"date"`
OneDayNotionalVolumes []OneDayNotionalVolume `json:"notional_1d_volume"`
}
// OneDayNotionalVolume Contains the notioanl volume for a single day
type OneDayNotionalVolume struct {
Date string `json:"date"`
NotationalVolume float64 `json:"notional_volume"`
}
// Balance is a simple balance type
type Balance struct {
Currency string `json:"currency"`

View File

@@ -180,3 +180,8 @@ func (g *Gemini) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curr
func (g *Gemini) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (g *Gemini) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return g.GetFee(feeBuilder)
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -54,65 +55,65 @@ type HitBTC struct {
}
// SetDefaults sets default settings for hitbtc
func (p *HitBTC) SetDefaults() {
p.Name = "HitBTC"
p.Enabled = false
p.Fee = 0
p.Verbose = false
p.RESTPollingDelay = 10
p.RequestCurrencyPairFormat.Delimiter = ""
p.RequestCurrencyPairFormat.Uppercase = true
p.ConfigCurrencyPairFormat.Delimiter = "-"
p.ConfigCurrencyPairFormat.Uppercase = true
p.AssetTypes = []string{ticker.Spot}
p.SupportsAutoPairUpdating = true
p.SupportsRESTTickerBatching = true
p.Requester = request.New(p.Name,
func (h *HitBTC) SetDefaults() {
h.Name = "HitBTC"
h.Enabled = false
h.Fee = 0
h.Verbose = false
h.RESTPollingDelay = 10
h.RequestCurrencyPairFormat.Delimiter = ""
h.RequestCurrencyPairFormat.Uppercase = true
h.ConfigCurrencyPairFormat.Delimiter = "-"
h.ConfigCurrencyPairFormat.Uppercase = true
h.AssetTypes = []string{ticker.Spot}
h.SupportsAutoPairUpdating = true
h.SupportsRESTTickerBatching = true
h.Requester = request.New(h.Name,
request.NewRateLimit(time.Second, hitbtcAuthRate),
request.NewRateLimit(time.Second, hitbtcUnauthRate),
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
p.APIUrlDefault = apiURL
p.APIUrl = p.APIUrlDefault
p.WebsocketInit()
h.APIUrlDefault = apiURL
h.APIUrl = h.APIUrlDefault
h.WebsocketInit()
}
// Setup sets user exchange configuration settings
func (p *HitBTC) Setup(exch config.ExchangeConfig) {
func (h *HitBTC) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
p.SetEnabled(false)
h.SetEnabled(false)
} else {
p.Enabled = true
p.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
p.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
p.SetHTTPClientTimeout(exch.HTTPTimeout)
p.SetHTTPClientUserAgent(exch.HTTPUserAgent)
p.RESTPollingDelay = exch.RESTPollingDelay // Max 60000ms
p.Verbose = exch.Verbose
p.Websocket.SetEnabled(exch.Websocket)
p.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
p.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
p.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
err := p.SetCurrencyPairFormat()
h.Enabled = true
h.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
h.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
h.SetHTTPClientTimeout(exch.HTTPTimeout)
h.SetHTTPClientUserAgent(exch.HTTPUserAgent)
h.RESTPollingDelay = exch.RESTPollingDelay // Max 60000ms
h.Verbose = exch.Verbose
h.Websocket.SetEnabled(exch.Websocket)
h.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
h.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
h.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
err := h.SetCurrencyPairFormat()
if err != nil {
log.Fatal(err)
}
err = p.SetAssetTypes()
err = h.SetAssetTypes()
if err != nil {
log.Fatal(err)
}
err = p.SetAutoPairDefaults()
err = h.SetAutoPairDefaults()
if err != nil {
log.Fatal(err)
}
err = p.SetAPIURL(exch)
err = h.SetAPIURL(exch)
if err != nil {
log.Fatal(err)
}
err = p.SetClientProxyAddress(exch.ProxyAddress)
err = h.SetClientProxyAddress(exch.ProxyAddress)
if err != nil {
log.Fatal(err)
}
err = p.WebsocketSetup(p.WsConnect,
err = h.WebsocketSetup(h.WsConnect,
exch.Name,
exch.Websocket,
hitbtcWebsocketAddress,
@@ -123,25 +124,20 @@ func (p *HitBTC) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the fee for hitbtc
func (p *HitBTC) GetFee() float64 {
return p.Fee
}
// Public Market Data
// https://api.hitbtc.com/?python#market-data
// GetCurrencies returns the actual list of available currencies, tokens, ICO
// etc.
func (p *HitBTC) GetCurrencies(currency string) (map[string]Currencies, error) {
func (h *HitBTC) GetCurrencies() (map[string]Currencies, error) {
type Response struct {
Data []Currencies
}
resp := Response{}
path := fmt.Sprintf("%s/%s/%s", p.APIUrl, apiV2Currency, currency)
path := fmt.Sprintf("%s/%s", h.APIUrl, apiV2Currency)
ret := make(map[string]Currencies)
err := p.SendHTTPRequest(path, &resp.Data)
err := h.SendHTTPRequest(path, &resp.Data)
if err != nil {
return ret, err
}
@@ -152,17 +148,29 @@ func (p *HitBTC) GetCurrencies(currency string) (map[string]Currencies, error) {
return ret, err
}
// GetCurrency returns the actual list of available currencies, tokens, ICO
// etc.
func (h *HitBTC) GetCurrency(currency string) (Currencies, error) {
type Response struct {
Data Currencies
}
resp := Response{}
path := fmt.Sprintf("%s/%s/%s", h.APIUrl, apiV2Currency, currency)
return resp.Data, h.SendHTTPRequest(path, &resp.Data)
}
// GetSymbols Return the actual list of currency symbols (currency pairs) traded
// on HitBTC exchange. The first listed currency of a symbol is called the base
// currency, and the second currency is called the quote currency. The currency
// pair indicates how much of the quote currency is needed to purchase one unit
// of the base currency.
func (p *HitBTC) GetSymbols(symbol string) ([]string, error) {
func (h *HitBTC) GetSymbols(symbol string) ([]string, error) {
resp := []Symbol{}
path := fmt.Sprintf("%s/%s/%s", p.APIUrl, apiV2Symbol, symbol)
path := fmt.Sprintf("%s/%s/%s", h.APIUrl, apiV2Symbol, symbol)
ret := make([]string, 0, len(resp))
err := p.SendHTTPRequest(path, &resp)
err := h.SendHTTPRequest(path, &resp)
if err != nil {
return ret, err
}
@@ -175,24 +183,24 @@ func (p *HitBTC) GetSymbols(symbol string) ([]string, error) {
// GetSymbolsDetailed is the same as above but returns an array of symbols with
// all their details.
func (p *HitBTC) GetSymbolsDetailed() ([]Symbol, error) {
func (h *HitBTC) GetSymbolsDetailed() ([]Symbol, error) {
resp := []Symbol{}
path := fmt.Sprintf("%s/%s", p.APIUrl, apiV2Symbol)
path := fmt.Sprintf("%s/%s", h.APIUrl, apiV2Symbol)
return resp, p.SendHTTPRequest(path, &resp)
return resp, h.SendHTTPRequest(path, &resp)
}
// GetTicker returns ticker information
func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
func (h *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
resp1 := []TickerResponse{}
resp2 := TickerResponse{}
ret := make(map[string]TickerResponse)
result := make(map[string]Ticker)
path := fmt.Sprintf("%s/%s/%s", p.APIUrl, apiV2Ticker, symbol)
path := fmt.Sprintf("%s/%s/%s", h.APIUrl, apiV2Ticker, symbol)
var err error
if symbol == "" {
err = p.SendHTTPRequest(path, &resp1)
err = h.SendHTTPRequest(path, &resp1)
if err != nil {
return nil, err
}
@@ -203,7 +211,7 @@ func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
}
}
} else {
err = p.SendHTTPRequest(path, &resp2)
err = h.SendHTTPRequest(path, &resp2)
ret[resp2.Symbol] = resp2
}
@@ -245,12 +253,12 @@ func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
}
// GetTrades returns trades from hitbtc
func (p *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort string) ([]TradeHistory, error) {
func (h *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort string) ([]TradeHistory, error) {
// start Number or Datetime
// end Number or Datetime
// limit Number
// offset Number
// by Filtration definition. Accepted values: id, timestamp. Default timestamp
// by Filtration definition. Accepted values: id, timestamh. Default timestamp
// sort Default DESC
vals := url.Values{}
@@ -279,14 +287,14 @@ func (p *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort str
}
resp := []TradeHistory{}
path := fmt.Sprintf("%s/%s/%s?%s", p.APIUrl, apiV2Trades, currencyPair, vals.Encode())
path := fmt.Sprintf("%s/%s/%s?%s", h.APIUrl, apiV2Trades, currencyPair, vals.Encode())
return resp, p.SendHTTPRequest(path, &resp)
return resp, h.SendHTTPRequest(path, &resp)
}
// GetOrderbook an order book is an electronic list of buy and sell orders for a
// specific symbol, organized by price level.
func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error) {
func (h *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error) {
// limit Limit of orderbook levels, default 100. Set 0 to view full orderbook levels
vals := url.Values{}
@@ -295,9 +303,9 @@ func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error)
}
resp := OrderbookResponse{}
path := fmt.Sprintf("%s/%s/%s?%s", p.APIUrl, apiV2Orderbook, currencyPair, vals.Encode())
path := fmt.Sprintf("%s/%s/%s?%s", h.APIUrl, apiV2Orderbook, currencyPair, vals.Encode())
err := p.SendHTTPRequest(path, &resp)
err := h.SendHTTPRequest(path, &resp)
if err != nil {
return Orderbook{}, err
}
@@ -315,7 +323,7 @@ func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error)
// GetCandles returns candles which is used for OHLC a specific symbol.
// Note: Result contain candles only with non zero volume.
func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, error) {
func (h *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, error) {
// limit Limit of candles, default 100.
// period One of: M1 (one minute), M3, M5, M15, M30, H1, H4, D1, D7, 1M (one month). Default is M30 (30 minutes).
vals := url.Values{}
@@ -329,18 +337,18 @@ func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, er
}
resp := []ChartData{}
path := fmt.Sprintf("%s/%s/%s?%s", p.APIUrl, apiV2Candles, currencyPair, vals.Encode())
path := fmt.Sprintf("%s/%s/%s?%s", h.APIUrl, apiV2Candles, currencyPair, vals.Encode())
return resp, p.SendHTTPRequest(path, &resp)
return resp, h.SendHTTPRequest(path, &resp)
}
// Authenticated Market Data
// https://api.hitbtc.com/?python#market-data
// GetBalances returns full balance for your account
func (p *HitBTC) GetBalances() (map[string]Balance, error) {
func (h *HitBTC) GetBalances() (map[string]Balance, error) {
result := []Balance{}
err := p.SendAuthenticatedHTTPRequest("GET", apiV2Balance, url.Values{}, &result)
err := h.SendAuthenticatedHTTPRequest("GET", apiV2Balance, url.Values{}, &result)
ret := make(map[string]Balance)
if err != nil {
@@ -355,31 +363,31 @@ func (p *HitBTC) GetBalances() (map[string]Balance, error) {
}
// GetDepositAddresses returns a deposit address for a specific currency
func (p *HitBTC) GetDepositAddresses(currency string) (DepositCryptoAddresses, error) {
func (h *HitBTC) GetDepositAddresses(currency string) (DepositCryptoAddresses, error) {
resp := DepositCryptoAddresses{}
err := p.SendAuthenticatedHTTPRequest("GET", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp)
err := h.SendAuthenticatedHTTPRequest("GET", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp)
return resp, err
}
// GenerateNewAddress generates a new deposit address for a currency
func (p *HitBTC) GenerateNewAddress(currency string) (DepositCryptoAddresses, error) {
func (h *HitBTC) GenerateNewAddress(currency string) (DepositCryptoAddresses, error) {
resp := DepositCryptoAddresses{}
err := p.SendAuthenticatedHTTPRequest("POST", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp)
err := h.SendAuthenticatedHTTPRequest("POST", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp)
return resp, err
}
// GetActiveorders returns all your active orders
func (p *HitBTC) GetActiveorders(currency string) ([]Order, error) {
func (h *HitBTC) GetActiveorders(currency string) ([]Order, error) {
resp := []Order{}
err := p.SendAuthenticatedHTTPRequest("GET", orders+"?symbol="+currency, url.Values{}, &resp)
err := h.SendAuthenticatedHTTPRequest("GET", orders+"?symbol="+currency, url.Values{}, &resp)
return resp, err
}
// GetAuthenticatedTradeHistory returns your trade history
func (p *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (interface{}, error) {
func (h *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (interface{}, error) {
values := url.Values{}
if start != "" {
@@ -394,17 +402,17 @@ func (p *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (inte
values.Set("currencyPair", currency)
result := AuthenticatedTradeHistoryResponse{}
return result, p.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data)
return result, h.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data)
}
values.Set("currencyPair", "all")
result := AuthenticatedTradeHistoryAll{}
return result, p.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data)
return result, h.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data)
}
// PlaceOrder places an order on the exchange
func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) {
func (h *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) {
result := OrderResponse{}
values := url.Values{}
@@ -427,7 +435,7 @@ func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fi
values.Set("fillOrKill", "1")
}
err := p.SendAuthenticatedHTTPRequest("POST", orderType, values, &result)
err := h.SendAuthenticatedHTTPRequest("POST", orderType, values, &result)
if err != nil {
return result, err
@@ -437,12 +445,12 @@ func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fi
}
// CancelOrder cancels a specific order by OrderID
func (p *HitBTC) CancelOrder(orderID int64) (bool, error) {
func (h *HitBTC) CancelOrder(orderID int64) (bool, error) {
result := GenericResponse{}
values := url.Values{}
values.Set("orderNumber", strconv.FormatInt(orderID, 10))
err := p.SendAuthenticatedHTTPRequest("POST", orderCancel, values, &result)
err := h.SendAuthenticatedHTTPRequest("POST", orderCancel, values, &result)
if err != nil {
return false, err
@@ -456,7 +464,7 @@ func (p *HitBTC) CancelOrder(orderID int64) (bool, error) {
}
// MoveOrder generates a new move order
func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderResponse, error) {
func (h *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderResponse, error) {
result := MoveOrderResponse{}
values := url.Values{}
values.Set("orderNumber", strconv.FormatInt(orderID, 10))
@@ -466,7 +474,7 @@ func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
}
err := p.SendAuthenticatedHTTPRequest("POST", orderMove, values, &result)
err := h.SendAuthenticatedHTTPRequest("POST", orderMove, values, &result)
if err != nil {
return result, err
@@ -480,7 +488,7 @@ func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon
}
// Withdraw allows for the withdrawal to a specific address
func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error) {
func (h *HitBTC) Withdraw(currency, address string, amount float64) (bool, error) {
result := Withdraw{}
values := url.Values{}
@@ -488,7 +496,7 @@ func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
values.Set("address", address)
err := p.SendAuthenticatedHTTPRequest("POST", apiV2CryptoWithdraw, values, &result)
err := h.SendAuthenticatedHTTPRequest("POST", apiV2CryptoWithdraw, values, &result)
if err != nil {
return false, err
@@ -502,21 +510,21 @@ func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error
}
// GetFeeInfo returns current fee information
func (p *HitBTC) GetFeeInfo(currencyPair string) (Fee, error) {
func (h *HitBTC) GetFeeInfo(currencyPair string) (Fee, error) {
result := Fee{}
err := p.SendAuthenticatedHTTPRequest("GET", apiV2FeeInfo+"/"+currencyPair, url.Values{}, &result)
err := h.SendAuthenticatedHTTPRequest("GET", apiV2FeeInfo+"/"+currencyPair, url.Values{}, &result)
return result, err
}
// GetTradableBalances returns current tradable balances
func (p *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) {
func (h *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) {
type Response struct {
Data map[string]map[string]interface{}
}
result := Response{}
err := p.SendAuthenticatedHTTPRequest("POST", tradableBalances, url.Values{}, &result.Data)
err := h.SendAuthenticatedHTTPRequest("POST", tradableBalances, url.Values{}, &result.Data)
if err != nil {
return nil, err
@@ -535,7 +543,7 @@ func (p *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) {
}
// TransferBalance transfers a balance
func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (bool, error) {
func (h *HitBTC) TransferBalance(currency, from, to string, amount float64) (bool, error) {
values := url.Values{}
result := GenericResponse{}
@@ -544,7 +552,7 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
values.Set("fromAccount", from)
values.Set("toAccount", to)
err := p.SendAuthenticatedHTTPRequest("POST", transferBalance, values, &result)
err := h.SendAuthenticatedHTTPRequest("POST", transferBalance, values, &result)
if err != nil {
return false, err
@@ -558,19 +566,64 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
}
// SendHTTPRequest sends an unauthenticated HTTP request
func (p *HitBTC) SendHTTPRequest(path string, result interface{}) error {
return p.SendPayload("GET", path, nil, nil, result, false, p.Verbose)
func (h *HitBTC) SendHTTPRequest(path string, result interface{}) error {
return h.SendPayload("GET", path, nil, nil, result, false, h.Verbose)
}
// SendAuthenticatedHTTPRequest sends an authenticated http request
func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
if !p.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, p.Name)
func (h *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
if !h.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, h.Name)
}
headers := make(map[string]string)
headers["Authorization"] = "Basic " + common.Base64Encode([]byte(p.APIKey+":"+p.APISecret))
headers["Authorization"] = "Basic " + common.Base64Encode([]byte(h.APIKey+":"+h.APISecret))
path := fmt.Sprintf("%s/%s", p.APIUrl, endpoint)
path := fmt.Sprintf("%s/%s", h.APIUrl, endpoint)
return p.SendPayload(method, path, headers, bytes.NewBufferString(values.Encode()), result, true, p.Verbose)
return h.SendPayload(method, path, headers, bytes.NewBufferString(values.Encode()), result, true, h.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (h *HitBTC) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
feeInfo, err := h.GetFeeInfo(feeBuilder.FirstCurrency + feeBuilder.Delimiter + feeBuilder.SecondCurrency)
if err != nil {
return 0, err
}
fee = calculateTradingFee(feeInfo, feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CryptocurrencyWithdrawalFee:
currencyInfo, err := h.GetCurrency(feeBuilder.FirstCurrency)
if err != nil {
return 0, err
}
fee, err = strconv.ParseFloat(currencyInfo.PayoutFee, 64)
if err != nil {
return 0, err
}
case exchange.CyptocurrencyDepositFee:
fee = calculateCryptocurrencyDepositFee(feeBuilder.FirstCurrency, feeBuilder.Amount)
}
return fee, nil
}
func calculateCryptocurrencyDepositFee(currency string, amount float64) float64 {
var fee float64
if currency == symbol.BTC {
fee = 0.0006
}
return fee * amount
}
func calculateTradingFee(feeInfo Fee, purchasePrice, amount float64, isMaker bool) float64 {
var volumeFee float64
if isMaker {
volumeFee = feeInfo.ProvideLiquidityRate
} else {
volumeFee = feeInfo.TakeLiquidityRate
}
return volumeFee * amount * purchasePrice
}

View File

@@ -4,9 +4,11 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var p HitBTC
var h HitBTC
// Please supply your own APIKEYS here for due diligence testing
@@ -16,7 +18,7 @@ const (
)
func TestSetDefaults(t *testing.T) {
p.SetDefaults()
h.SetDefaults()
}
func TestSetup(t *testing.T) {
@@ -31,39 +33,130 @@ func TestSetup(t *testing.T) {
hitbtcConfig.APIKey = apiKey
hitbtcConfig.APISecret = apiSecret
p.Setup(hitbtcConfig)
}
func TestGetFee(t *testing.T) {
if p.GetFee() != 0 {
t.Error("Test faild - HitBTC GetFee() error")
}
h.Setup(hitbtcConfig)
}
func TestGetOrderbook(t *testing.T) {
_, err := p.GetOrderbook("BTCUSD", 50)
_, err := h.GetOrderbook("BTCUSD", 50)
if err != nil {
t.Error("Test faild - HitBTC GetOrderbook() error", err)
}
}
func TestGetTrades(t *testing.T) {
_, err := p.GetTrades("BTCUSD", "", "", "", "", "", "")
_, err := h.GetTrades("BTCUSD", "", "", "", "", "", "")
if err != nil {
t.Error("Test faild - HitBTC GetTradeHistory() error", err)
}
}
func TestGetChartCandles(t *testing.T) {
_, err := p.GetCandles("BTCUSD", "", "")
_, err := h.GetCandles("BTCUSD", "", "")
if err != nil {
t.Error("Test faild - HitBTC GetChartData() error", err)
}
}
func TestGetCurrencies(t *testing.T) {
_, err := p.GetCurrencies("")
_, err := h.GetCurrencies()
if err != nil {
t.Error("Test faild - HitBTC GetCurrencies() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.ETH,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
h.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if apiKey != "" && apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := h.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := h.GetFee(feeBuilder); resp != float64(1000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(1000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := h.GetFee(feeBuilder); resp != float64(-0.0001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(-0.0001), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := h.GetFee(feeBuilder); resp != float64(-1) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(-1), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0.009580) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.009580), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err == nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
feeBuilder.FirstCurrency = symbol.BTC
feeBuilder.SecondCurrency = symbol.LTC
if resp, err := h.GetFee(feeBuilder); resp != float64(0.0006) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0006), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -91,6 +91,8 @@ type Currencies struct {
PayoutEnabled bool `json:"payoutEnabled"` // Is allowed for withdraw (false for ICO)
PayoutIsPaymentID bool `json:"payoutIsPaymentId"` // Is allowed to provide additional information for withdraw
TransferEnabled bool `json:"transferEnabled"` // Is allowed to transfer between trading and account (may be disabled on maintain)
Delisted bool `json:"delisted"` // True if currency delisted (stopped deposit and trading)
PayoutFee string `json:"payoutFee"` // Default withdraw fee
}
// LoanOrder contains information about your loans

View File

@@ -208,3 +208,8 @@ func (h *HitBTC) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curr
func (h *HitBTC) GetWebsocket() (*exchange.Websocket, error) {
return h.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HitBTC) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return h.GetFee(feeBuilder)
}

View File

@@ -138,11 +138,6 @@ func (h *HUOBI) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns Huobi fee
func (h *HUOBI) GetFee() float64 {
return h.Fee
}
// GetSpotKline returns kline data
// KlinesRequestParams contains symbol, period and size
func (h *HUOBI) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) {
@@ -853,3 +848,22 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
return h.SendPayload(method, url, headers, bytes.NewReader(body), result, true, h.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (h *HUOBI) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64) float64 {
feePercent := 0.002
return feePercent * purchasePrice * amount
}

View File

@@ -12,6 +12,8 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply you own test keys here for due diligence testing.
@@ -70,13 +72,6 @@ func TestSetup(t *testing.T) {
h.Setup(hConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if h.GetFee() != 0 {
t.Errorf("test failed - Huobi GetFee() error")
}
}
func TestGetSpotKline(t *testing.T) {
t.Parallel()
_, err := h.GetSpotKline(KlinesRequestParams{
@@ -296,3 +291,93 @@ func TestPEMLoadAndSign(t *testing.T) {
t.Fatalf("Test Failed. TestPEMLoadAndSign Unable to sign: %s", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := h.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := h.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := h.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -223,3 +223,8 @@ func (h *HUOBI) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curre
func (h *HUOBI) GetWebsocket() (*exchange.Websocket, error) {
return h.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HUOBI) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return h.GetFee(feeBuilder)
}

View File

@@ -121,11 +121,6 @@ func (h *HUOBIHADAX) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns Huobi fee
func (h *HUOBIHADAX) GetFee() float64 {
return h.Fee
}
// GetSpotKline returns kline data
// KlinesRequestParams holds the Kline request params
func (h *HUOBIHADAX) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) {
@@ -809,3 +804,22 @@ func (h *HUOBIHADAX) SendAuthenticatedHTTPRequest(method, endpoint string, value
return h.SendPayload(method, url, headers, bytes.NewBufferString(""), result, true, h.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (h *HUOBIHADAX) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64) float64 {
feePercent := 0.002
return feePercent * purchasePrice * amount
}

View File

@@ -6,6 +6,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
// Please supply your own APIKEYS here for due diligence testing
@@ -65,13 +67,6 @@ func TestSetup(t *testing.T) {
h.Setup(hadaxConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if h.GetFee() != 0 {
t.Errorf("test failed - Huobi GetFee() error")
}
}
func TestGetSpotKline(t *testing.T) {
t.Parallel()
_, err := h.GetSpotKline(KlinesRequestParams{
@@ -275,3 +270,93 @@ func TestCancelWithdraw(t *testing.T) {
t.Error("Test failed - Huobi TestCancelWithdraw: Invalid withdraw-ID was valid")
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := h.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := h.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := h.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := h.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -188,3 +188,8 @@ func (h *HUOBIHADAX) WithdrawFiatExchangeFundsToInternationalBank(currency pair.
func (h *HUOBIHADAX) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HUOBIHADAX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return h.GetFee(feeBuilder)
}

View File

@@ -101,14 +101,6 @@ func (i *ItBit) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the maker or taker fee
func (i *ItBit) GetFee(maker bool) float64 {
if maker {
return i.MakerFee
}
return i.TakerFee
}
// GetTicker returns ticker info for a specified market.
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
func (i *ItBit) GetTicker(currencyPair string) (Ticker, error) {
@@ -376,3 +368,27 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params
return i.SendPayload(method, url, headers, bytes.NewBuffer([]byte(PayloadJSON)), result, true, i.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (i *ItBit) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) float64 {
// TODO: Itbit has volume discounts, but not API endpoint to get the exact volume numbers
// When support is added, this needs to be updated to calculate the accurate volume fee
feePercent := 0.0025
if isMaker {
feePercent = 0
}
return feePercent * purchasePrice * amount
}

View File

@@ -5,6 +5,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var i ItBit
@@ -36,13 +38,6 @@ func TestSetup(t *testing.T) {
i.Setup(itbitConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if i.GetFee(true) != -0.1 || i.GetFee(false) != 0.5 {
t.Error("Test Failed - GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := i.GetTicker("XBTUSD")
@@ -144,3 +139,93 @@ func TestWalletTransfer(t *testing.T) {
t.Error("Test Failed - WalletTransfer() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := i.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := i.GetFee(feeBuilder); resp != float64(2500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2500), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := i.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -182,3 +182,8 @@ func (i *ItBit) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curre
func (i *ItBit) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (i *ItBit) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return i.GetFee(feeBuilder)
}

View File

@@ -16,29 +16,31 @@ import (
)
const (
krakenAPIURL = "https://api.kraken.com"
krakenAPIVersion = "0"
krakenServerTime = "Time"
krakenAssets = "Assets"
krakenAssetPairs = "AssetPairs"
krakenTicker = "Ticker"
krakenOHLC = "OHLC"
krakenDepth = "Depth"
krakenTrades = "Trades"
krakenSpread = "Spread"
krakenBalance = "Balance"
krakenTradeBalance = "TradeBalance"
krakenOpenOrders = "OpenOrders"
krakenClosedOrders = "ClosedOrders"
krakenQueryOrders = "QueryOrders"
krakenTradeHistory = "TradesHistory"
krakenQueryTrades = "QueryTrades"
krakenOpenPositions = "OpenPositions"
krakenLedgers = "Ledgers"
krakenQueryLedgers = "QueryLedgers"
krakenTradeVolume = "TradeVolume"
krakenOrderCancel = "CancelOrder"
krakenOrderPlace = "AddOrder"
krakenAPIURL = "https://api.kraken.com"
krakenAPIVersion = "0"
krakenServerTime = "Time"
krakenAssets = "Assets"
krakenAssetPairs = "AssetPairs"
krakenTicker = "Ticker"
krakenOHLC = "OHLC"
krakenDepth = "Depth"
krakenTrades = "Trades"
krakenSpread = "Spread"
krakenBalance = "Balance"
krakenTradeBalance = "TradeBalance"
krakenOpenOrders = "OpenOrders"
krakenClosedOrders = "ClosedOrders"
krakenQueryOrders = "QueryOrders"
krakenTradeHistory = "TradesHistory"
krakenQueryTrades = "QueryTrades"
krakenOpenPositions = "OpenPositions"
krakenLedgers = "Ledgers"
krakenQueryLedgers = "QueryLedgers"
krakenTradeVolume = "TradeVolume"
krakenOrderCancel = "CancelOrder"
krakenOrderPlace = "AddOrder"
krakenWithdrawInfo = "WithdrawInfo"
krakenDepositMethods = "DepositMethods"
krakenAuthRate = 0
krakenUnauthRate = 0
@@ -115,14 +117,6 @@ func (k *Kraken) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns current fee for either crypto or fiat
func (k *Kraken) GetFee(cryptoTrade bool) float64 {
if cryptoTrade {
return k.CryptoFee
}
return k.FiatFee
}
// GetServerTime returns current server time
func (k *Kraken) GetServerTime() (TimeResponse, error) {
path := fmt.Sprintf("%s/%s/public/%s", k.APIUrl, krakenAPIVersion, krakenServerTime)
@@ -416,6 +410,40 @@ func (k *Kraken) GetBalance() (map[string]float64, error) {
return result, GetError(response.Error)
}
// GetWithdrawInfo gets withdrawal fees
func (k *Kraken) GetWithdrawInfo(currency string, amount float64) (WithdrawInformation, error) {
var response struct {
Error []string `json:"error"`
Result WithdrawInformation `json:"result"`
}
params := url.Values{}
params.Set("asset ", currency)
params.Set("key ", "")
params.Set("amount ", fmt.Sprintf("%f", amount))
if err := k.SendAuthenticatedHTTPRequest(krakenWithdrawInfo, params, &response); err != nil {
return response.Result, err
}
return response.Result, GetError(response.Error)
}
// GetDepositMethods gets withdrawal fees
func (k *Kraken) GetDepositMethods(currency string) ([]DepositMethods, error) {
var response struct {
Error []string `json:"error"`
Result []DepositMethods `json:"result"`
}
params := url.Values{}
params.Set("asset ", currency)
if err := k.SendAuthenticatedHTTPRequest(krakenDepositMethods, params, &response); err != nil {
return response.Result, err
}
return response.Result, GetError(response.Error)
}
// GetTradeBalance returns full information about your trades on Kraken
func (k *Kraken) GetTradeBalance(args ...TradeBalanceOptions) (TradeBalanceInfo, error) {
params := url.Values{}
@@ -852,3 +880,61 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, params url.Values,
return k.SendPayload("POST", k.APIUrl+path, headers, strings.NewReader(encoded), result, true, k.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (k *Kraken) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
currency := feeBuilder.FirstCurrency + feeBuilder.Delimiter + feeBuilder.SecondCurrency
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
feePair, err := k.GetTradeVolume(true, currency)
if err != nil {
return 0, err
}
if feeBuilder.IsMaker {
fee = calculateTradingFee(currency, feePair.FeesMaker, feeBuilder.PurchasePrice, feeBuilder.Amount)
} else {
fee = calculateTradingFee(currency, feePair.Fees, feeBuilder.PurchasePrice, feeBuilder.Amount)
}
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankDepositFee:
depositMethods, err := k.GetDepositMethods(feeBuilder.CurrencyItem)
if err != nil {
return 0, err
}
for _, i := range depositMethods {
switch feeBuilder.BankTransactionType {
case exchange.WireTransfer:
if i.Method == "SynapsePay (US Wire)" {
fee = i.Fee
return fee, nil
}
}
}
case exchange.CyptocurrencyDepositFee:
fee = getCryptocurrencyDepositFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.CurrencyItem)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func getCryptocurrencyDepositFee(currency string) float64 {
return DepositFees[currency]
}
func calculateTradingFee(currency string, feePair map[string]TradeVolumeFee, purchasePrice, amount float64) float64 {
return (feePair[currency].Fee / 100) * purchasePrice * amount
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var k Kraken
@@ -35,16 +37,6 @@ func TestSetup(t *testing.T) {
k.Setup(krakenConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if k.GetFee(true) != 0.1 {
t.Error("Test Failed - kraken GetFee() error")
}
if k.GetFee(false) != 0.35 {
t.Error("Test Failed - kraken GetFee() error")
}
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
_, err := k.GetServerTime()
@@ -219,3 +211,99 @@ func TestCancelOrder(t *testing.T) {
t.Error("Test Failed - CancelOrder() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.XXBT,
SecondCurrency: symbol.ZUSD,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
k.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if apiKey != "" && apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := k.GetFee(feeBuilder); resp != float64(0.0026) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0026), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := k.GetFee(feeBuilder); resp != float64(2600) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2600), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := k.GetFee(feeBuilder); resp != float64(0.0016) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0016), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := k.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := k.GetFee(feeBuilder); resp != float64(5) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(5), resp)
t.Error(err)
}
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
feeBuilder.FirstCurrency = symbol.XXBT
if resp, err := k.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(5), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := k.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0005), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := k.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := k.GetFee(feeBuilder); resp != float64(5) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(5), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package kraken
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// TimeResponse type
type TimeResponse struct {
Unixtime int64 `json:"unixtime"`
@@ -285,6 +287,21 @@ type AddOrderResponse struct {
TransactionIds []string `json:"txid"`
}
// WithdrawInformation Used to check withdrawal fees
type WithdrawInformation struct {
Method string `json:"method"`
Limit float64 `json:"limit,string"`
Fee float64 `json:"fee,string"`
}
// DepositMethods Used to check deposit fees
type DepositMethods struct {
Method string `json:"method"`
Limit float64 `json:"limit,string"`
Fee float64 `json:"fee,string"`
AddressSetupFee float64 `json:"address-setup-fee,string"`
}
// OrderDescription represents an orders description
type OrderDescription struct {
Close string `json:"close"`
@@ -308,3 +325,40 @@ type CancelOrderResponse struct {
Count int64 `json:"count"`
Pending interface{} `json:"pending"`
}
// DepositFees the large list of predefined deposit fees
// Prone to change
var DepositFees = map[string]float64{
symbol.XTZ: 0.05,
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.ZUSD: 5,
symbol.ZEUR: 5,
symbol.USD: 5,
symbol.EUR: 5,
symbol.REP: 0.01,
symbol.XXBT: 0.0005,
symbol.BTC: 0.0005,
symbol.XBT: 0.0005,
symbol.BCH: 0.0001,
symbol.ADA: 0.3,
symbol.DASH: 0.005,
symbol.XDG: 2,
symbol.EOS: 0.05,
symbol.ETH: 0.005,
symbol.ETC: 0.005,
symbol.GNO: 0.005,
symbol.ICN: 0.2,
symbol.LTC: 0.001,
symbol.MLN: 0.003,
symbol.XMR: 0.05,
symbol.QTUM: 0.01,
symbol.XRP: 0.02,
symbol.XLM: 0.00002,
symbol.USDT: 5,
symbol.XTZ: 0.05,
symbol.ZEC: 0.0001,
}

View File

@@ -255,3 +255,8 @@ func (k *Kraken) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curr
func (k *Kraken) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (k *Kraken) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return k.GetFee(feeBuilder)
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -117,14 +118,6 @@ func (l *LakeBTC) GetTradablePairs() ([]string, error) {
return currencies, nil
}
// GetFee returns maker or taker fee
func (l *LakeBTC) GetFee(maker bool) float64 {
if maker {
return l.MakerFee
}
return l.TakerFee
}
// GetTicker returns the current ticker from lakeBTC
func (l *LakeBTC) GetTicker() (map[string]Ticker, error) {
response := make(map[string]TickerResponse)
@@ -352,3 +345,38 @@ func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result int
return l.SendPayload("POST", l.APIUrl, headers, strings.NewReader(string(data)), result, true, l.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (l *LakeBTC) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CyptocurrencyDepositFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
if isMaker {
// TODO: Volume based fee calculation
fee = 0.0015
} else {
fee = 0.002
}
return fee * amount * purchasePrice
}
func getCryptocurrencyWithdrawalFee(currency string) (fee float64) {
if currency == symbol.BTC {
fee = 0.001
}
return fee
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var l LakeBTC
@@ -41,16 +43,6 @@ func TestGetTradablePairs(t *testing.T) {
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
if l.GetFee(false) != 0.2 {
t.Error("Test Failed - GetFee() error")
}
if l.GetFee(true) != 0.15 {
t.Error("Test Failed - GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := l.GetTicker()
@@ -151,3 +143,93 @@ func TestCreateWithdraw(t *testing.T) {
t.Error("Test Failed - CreateWithdraw() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := l.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := l.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := l.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0015), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -192,3 +192,8 @@ func (l *LakeBTC) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cur
func (l *LakeBTC) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *LakeBTC) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return l.GetFee(feeBuilder)
}

View File

@@ -1,7 +1,6 @@
package liqui
import (
"errors"
"fmt"
"log"
"net/url"
@@ -109,16 +108,6 @@ func (l *Liqui) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns a fee for a specific currency
func (l *Liqui) GetFee(currency string) (float64, error) {
val, ok := l.Info.Pairs[common.StringToLower(currency)]
if !ok {
return 0, errors.New("currency does not exist")
}
return val.Fee, nil
}
// GetAvailablePairs returns all available pairs
func (l *Liqui) GetAvailablePairs(nonHidden bool) []string {
var pairs []string
@@ -315,3 +304,33 @@ func (l *Liqui) SendAuthenticatedHTTPRequest(method string, values url.Values, r
true,
l.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (l *Liqui) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CryptocurrencyWithdrawalFee:
fee = getCryptocurrencyWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func getCryptocurrencyWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
if isMaker {
fee = 0.001
} else {
fee = 0.0025
}
return fee * purchasePrice * amount
}

View File

@@ -6,6 +6,8 @@ import (
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var l Liqui
@@ -34,14 +36,6 @@ func TestSetup(t *testing.T) {
l.Setup(liquiConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
_, err := l.GetFee("usd")
if err == nil {
t.Error("Test Failed - liqui GetFee() error", err)
}
}
func TestGetAvailablePairs(t *testing.T) {
t.Parallel()
v := l.GetAvailablePairs(false)
@@ -136,3 +130,92 @@ func TestUpdateOrderbook(t *testing.T) {
t.Error("Test Failed - liqui UpdateOrderbook() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
l.SetDefaults()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := l.GetFee(feeBuilder); resp != float64(0.0025) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0025), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := l.GetFee(feeBuilder); resp != float64(2500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := l.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0.01) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.01), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package liqui
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Info holds the current pair information as well as server time
type Info struct {
ServerTime int64 `json:"server_time"`
@@ -132,3 +134,92 @@ type WithdrawCoins struct {
Success int `json:"success"`
Error string `json:"error"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change
var WithdrawalFees = map[string]float64{
symbol.ZRX: 5,
symbol.ADX: 10,
symbol.AE: 2,
symbol.AION: 5,
symbol.AST: 25,
symbol.ANT: 2,
symbol.REP: 0.15,
symbol.BNT: 1.5,
symbol.BAT: 20,
symbol.BTC: 0.001,
symbol.BCH: 0.007,
symbol.BMC: 7,
symbol.BCAP: 2,
symbol.TIME: 0.5,
symbol.CVC: 15,
symbol.CFI: 100,
symbol.CLN: 100,
symbol.DASH: 0.003,
symbol.MANA: 40,
symbol.DGD: 0.05,
symbol.DNT: 100,
symbol.EDG: 15,
symbol.ENG: 3,
symbol.ENJ: 50,
symbol.EOS: 0.5,
symbol.ETH: 0.01,
symbol.FIRST: 5,
symbol.GNO: 0.1,
symbol.GNT: 15,
symbol.GOLOS: 0.01,
symbol.GBG: 0.01,
symbol.HMQ: 20,
symbol.ICN: 7,
symbol.RLC: 5,
symbol.INCNT: 1,
symbol.IND: 70,
symbol.INS: 7,
symbol.KNC: 4,
symbol.LDC: 1000,
symbol.LTC: 0.01,
symbol.LUN: 0.5,
symbol.GUP: 40,
symbol.MLN: 0.2,
symbol.MGO: 20,
symbol.MCO: 0.7,
symbol.MYST: 20,
symbol.NEU: 7,
symbol.NET: 10,
symbol.OAX: 10,
symbol.OMG: 0.5,
symbol.PTOY: 50,
symbol.PLU: 0.5,
symbol.PRO: 7,
symbol.QTUM: 0.2,
symbol.QRL: 10,
symbol.REN: 100,
symbol.REQ: 50,
symbol.ROUND: 100,
symbol.SALT: 4,
symbol.SAN: 4,
symbol.SNGLS: 80,
symbol.AGI: 50,
symbol.SRN: 30,
symbol.SNM: 25,
symbol.XID: 50,
symbol.SNT: 50,
symbol.STEEM: 0.01,
symbol.SBD: 0.01,
symbol.STORJ: 7,
symbol.STX: 20,
symbol.TAAS: 2,
symbol.PAY: 5,
symbol.USDT: 20,
symbol.TNT: 100,
symbol.TKN: 5,
symbol.TRX: 100,
symbol.VEN: 3,
symbol.VSL: 30,
symbol.WAVES: 0.01,
symbol.WPR: 100,
symbol.TRST: 100,
symbol.WINGS: 20,
symbol.XXX: 0.01,
symbol.XZC: 0.01,
}

View File

@@ -201,3 +201,8 @@ func (l *Liqui) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curre
func (l *Liqui) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *Liqui) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return l.GetFee(feeBuilder)
}

View File

@@ -166,14 +166,6 @@ func (l *LocalBitcoins) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the fee for maker or taker
func (l *LocalBitcoins) GetFee(maker bool) float64 {
if maker {
return l.MakerFee
}
return l.TakerFee
}
// GetAccountInfo lets you retrieve the public user information on a
// LocalBitcoins user. The response contains the same information that is found
// on an account's public profile page.
@@ -735,3 +727,9 @@ func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(method, path string, params
return l.SendPayload(method, l.APIUrl+path, headers, strings.NewReader(encoded), result, true, l.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (l *LocalBitcoins) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
// No fees will be used
return 0, nil
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var l LocalBitcoins
@@ -34,13 +36,6 @@ func TestSetup(t *testing.T) {
l.Setup(localbitcoinsConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if l.GetFee(false) != 0 || l.GetFee(true) != 0 {
t.Error("Test Failed - GetFee() error")
}
}
func TestGetAccountInfo(t *testing.T) {
t.Parallel()
if l.APIKey == "" || l.APISecret == "" {
@@ -82,3 +77,93 @@ func TestEditAd(t *testing.T) {
t.Error("Test Failed - EditAd() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
l.SetDefaults()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := l.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -173,3 +173,8 @@ func (l *LocalBitcoins) WithdrawFiatExchangeFundsToInternationalBank(currency pa
func (l *LocalBitcoins) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *LocalBitcoins) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return l.GetFee(feeBuilder)
}

View File

@@ -9,6 +9,8 @@ import (
"strings"
"time"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/gorilla/websocket"
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
@@ -180,18 +182,6 @@ func (o *OKCoin) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns current fees for the exchange
func (o *OKCoin) GetFee(maker bool) float64 {
if o.APIUrl == okcoinAPIURL {
if maker {
return o.MakerFee
}
return o.TakerFee
}
// Chinese exchange does not have any trading fees
return 0
}
// GetTicker returns the current ticker
func (o *OKCoin) GetTicker(symbol string) (Ticker, error) {
resp := TickerResponse{}
@@ -1027,3 +1017,46 @@ func (o *OKCoin) SetErrorDefaults() {
"20028": "No such contract",
}
}
// GetFee returns an estimate of fee based on type of transaction
func (o *OKCoin) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.InternationalBankWithdrawalFee:
fee = calculateInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
// TODO volume based fees
if isMaker {
fee = 0.0005
} else {
fee = 0.0015
}
return fee * amount * purchasePrice
}
func calculateInternationalBankWithdrawalFee(currency string, purchasePrice, amount float64) (fee float64) {
if currency == symbol.USD {
if purchasePrice*amount*0.001 < 15 {
fee = 15
} else {
fee = purchasePrice * amount * 0.001
}
}
return fee
}
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var o OKCoin
@@ -33,3 +35,93 @@ func TestSetup(t *testing.T) {
o.Setup(okcoinConfig)
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
o.SetDefaults()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := o.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0015), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := o.GetFee(feeBuilder); resp != float64(1500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(1500), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := o.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0005), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0.2) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.2), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := o.GetFee(feeBuilder); resp != float64(15) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(15), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package okcoin
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Ticker holds ticker data
type Ticker struct {
Buy float64 `json:",string"`
@@ -415,3 +417,13 @@ type WebsocketTradeOrderResponse struct {
OrderID int64 `json:"order_id,string"`
Result bool `json:"result,string"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change, using highest value
var WithdrawalFees = map[string]float64{
symbol.BTC: 0.005,
symbol.LTC: 0.2,
symbol.ETH: 0.01,
symbol.ETC: 0.2,
symbol.BCH: 0.002,
}

View File

@@ -239,3 +239,8 @@ func (o *OKCoin) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curr
func (o *OKCoin) GetWebsocket() (*exchange.Websocket, error) {
return o.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (o *OKCoin) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return o.GetFee(feeBuilder)
}

View File

@@ -1107,3 +1107,33 @@ func (o *OKEX) CheckType(typeInput string) error {
}
return nil
}
// GetFee returns an estimate of fee based on type of transaction
func (o *OKEX) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64, isMaker bool) (fee float64) {
// TODO volume based fees
if isMaker {
fee = 0.001
} else {
fee = 0.0015
}
return fee * amount * purchasePrice
}
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var o OKEX
@@ -282,3 +284,93 @@ func TestGetUserInfo(t *testing.T) {
t.Error("Test failed - okex GetUserInfo() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
o.SetDefaults()
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := o.GetFee(feeBuilder); resp != float64(0.0015) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0015), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := o.GetFee(feeBuilder); resp != float64(1500) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(1500), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := o.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := o.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,6 +1,7 @@
package okex
import "encoding/json"
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// ContractPrice holds date and ticker price price for contracts.
type ContractPrice struct {
@@ -261,3 +262,155 @@ var (
TimeIntervalThreeDays = TimeInterval("3day")
TimeIntervalWeek = TimeInterval("1week")
)
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change, using highest value
var WithdrawalFees = map[string]float64{
symbol.ZRX: 10,
symbol.ACE: 2.2,
symbol.ACT: 0.01,
symbol.AAC: 5,
symbol.AE: 1,
symbol.AIDOC: 17,
symbol.AST: 8,
symbol.SOC: 20,
symbol.ABT: 3,
symbol.ARK: 0.1,
symbol.ATL: 1.5,
symbol.AVT: 1,
symbol.BNT: 1,
symbol.BKX: 3,
symbol.BEC: 4,
symbol.BTC: 0.0005,
symbol.BCH: 0.0001,
symbol.BCD: 0.02,
symbol.BTG: 0.001,
symbol.VEE: 100,
symbol.BRD: 1.5,
symbol.CTR: 7,
symbol.LINK: 10,
symbol.CAG: 2,
symbol.CHAT: 10,
symbol.CVC: 10,
symbol.CIC: 150,
symbol.CBT: 10,
symbol.CAN: 3,
symbol.CMT: 10,
symbol.DADI: 10,
symbol.DASH: 0.002,
symbol.DAT: 2,
symbol.MANA: 20,
symbol.DCR: 0.03,
symbol.DPY: 0.8,
symbol.DENT: 100,
symbol.DGD: 0.2,
symbol.DNT: 20,
symbol.EDO: 2,
symbol.DNA: 3,
symbol.ENG: 5,
symbol.ENJ: 20,
symbol.ETH: 0.01,
symbol.ETC: 0.001,
symbol.LEND: 10,
symbol.EVX: 1.5,
symbol.XUC: 5.8,
symbol.FAIR: 15,
symbol.FIRST: 6,
symbol.FUN: 40,
symbol.GTC: 40,
symbol.GNX: 8,
symbol.GTO: 10,
symbol.GSC: 20,
symbol.GNT: 5,
symbol.HMC: 40,
symbol.HOT: 10,
symbol.ICN: 2,
symbol.INS: 2.5,
symbol.INT: 10,
symbol.IOST: 100,
symbol.ITC: 2,
symbol.IPC: 2.5,
symbol.KNC: 2,
symbol.LA: 3,
symbol.LEV: 20,
symbol.LIGHT: 100,
symbol.LSK: 0.4,
symbol.LTC: 0.001,
symbol.LRC: 7,
symbol.MAG: 34,
symbol.MKR: 0.002,
symbol.MTL: 0.5,
symbol.AMM: 5,
symbol.MITH: 20,
symbol.MDA: 2,
symbol.MOF: 5,
symbol.MCO: 0.2,
symbol.MTH: 35,
symbol.NGC: 1.5,
symbol.NANO: 0.2,
symbol.NULS: 2,
symbol.OAX: 6,
symbol.OF: 600,
symbol.OKB: 0,
symbol.MOT: 1.5,
symbol.OMG: 0.1,
symbol.RNT: 13,
symbol.POE: 30,
symbol.PPT: 0.2,
symbol.PST: 10,
symbol.PRA: 4,
symbol.QTUM: 0.01,
symbol.QUN: 20,
symbol.QVT: 10,
symbol.RDN: 0.3,
symbol.READ: 20,
symbol.RCT: 15,
symbol.RFR: 200,
symbol.REF: 0.2,
symbol.REN: 50,
symbol.REQ: 15,
symbol.R: 2,
symbol.RCN: 20,
symbol.XRP: 0.15,
symbol.SALT: 0.5,
symbol.SAN: 1,
symbol.KEY: 50,
symbol.SSC: 8,
symbol.SHOW: 150,
symbol.SC: 200,
symbol.OST: 3,
symbol.SNGLS: 20,
symbol.SMT: 8,
symbol.SNM: 20,
symbol.SPF: 5,
symbol.SNT: 50,
symbol.STORJ: 2,
symbol.SUB: 4,
symbol.SNC: 10,
symbol.SWFTC: 350,
symbol.PAY: 0.5,
symbol.USDT: 2,
symbol.TRA: 500,
symbol.THETA: 20,
symbol.TNB: 40,
symbol.TCT: 50,
symbol.TOPC: 20,
symbol.TIO: 2.5,
symbol.TRIO: 200,
symbol.TRUE: 4,
symbol.UCT: 10,
symbol.UGC: 12,
symbol.UKG: 2.5,
symbol.UTK: 3,
symbol.VIB: 6,
symbol.VIU: 40,
symbol.WTC: 0.4,
symbol.WFEE: 500,
symbol.WRC: 48,
symbol.YEE: 70,
symbol.YOYOW: 10,
symbol.ZEC: 0.001,
symbol.ZEN: 0.07,
symbol.ZIL: 20,
symbol.ZIP: 1000,
}

View File

@@ -205,3 +205,8 @@ func (o *OKEX) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Curren
func (o *OKEX) GetWebsocket() (*exchange.Websocket, error) {
return o.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (o *OKEX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return o.GetFee(feeBuilder)
}

View File

@@ -129,11 +129,6 @@ func (p *Poloniex) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the fee for poloniex
func (p *Poloniex) GetFee() float64 {
return p.Fee
}
// GetTicker returns current ticker information
func (p *Poloniex) GetTicker() (map[string]Ticker, error) {
type response struct {
@@ -891,3 +886,36 @@ func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values
return p.SendPayload(method, path, headers, bytes.NewBufferString(values.Encode()), result, true, p.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (p *Poloniex) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
feeInfo, err := p.GetFeeInfo()
if err != nil {
return 0, err
}
fee = calculateTradingFee(feeInfo, feeBuilder.PurchasePrice, feeBuilder.Amount, feeBuilder.IsMaker)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(feeInfo Fee, purchasePrice, amount float64, isMaker bool) (fee float64) {
if isMaker {
fee = feeInfo.MakerFee
} else {
fee = feeInfo.TakerFee
}
return fee * amount * purchasePrice
}
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var p Poloniex
@@ -34,12 +36,6 @@ func TestSetup(t *testing.T) {
p.Setup(poloniexConfig)
}
func TestGetFee(t *testing.T) {
if p.GetFee() != 0 {
t.Error("Test faild - Poloniex GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
_, err := p.GetTicker()
if err != nil {
@@ -88,3 +84,97 @@ func TestGetLoanOrders(t *testing.T) {
t.Error("Test faild - Poloniex GetLoanOrders() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
p.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
if apiKey != "" && apiSecret != "" {
// CryptocurrencyTradeFee Basic
if resp, err := p.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.0015), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := p.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := p.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := p.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := p.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := p.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := p.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := p.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := p.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package poloniex
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Ticker holds ticker data
type Ticker struct {
Last float64 `json:"last,string"`
@@ -225,7 +227,6 @@ type Fee struct {
MakerFee float64 `json:"makerFee,string"`
TakerFee float64 `json:"takerFee,string"`
ThirtyDayVolume float64 `json:"thirtyDayVolume,string"`
NextTier float64 `json:"nextTier,string"`
}
// Margin holds margin information
@@ -334,3 +335,68 @@ type WsTrade struct {
Price float64
Timestamp int64
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change, using highest value
var WithdrawalFees = map[string]float64{
symbol.ZRX: 5,
symbol.ARDR: 2,
symbol.REP: 0.1,
symbol.BTC: 0.0005,
symbol.BCH: 0.0001,
symbol.XBC: 0.0001,
symbol.BTCD: 0.01,
symbol.BTM: 0.01,
symbol.BTS: 5,
symbol.BURST: 1,
symbol.BCN: 1,
symbol.CVC: 1,
symbol.CLAM: 0.001,
symbol.XCP: 1,
symbol.DASH: 0.01,
symbol.DCR: 0.1,
symbol.DGB: 0.1,
symbol.DOGE: 5,
symbol.EMC2: 0.01,
symbol.EOS: 0,
symbol.ETH: 0.01,
symbol.ETC: 0.01,
symbol.EXP: 0.01,
symbol.FCT: 0.01,
symbol.GAME: 0.01,
symbol.GAS: 0,
symbol.GNO: 0.015,
symbol.GNT: 1,
symbol.GRC: 0.01,
symbol.HUC: 0.01,
symbol.LBC: 0.05,
symbol.LSK: 0.1,
symbol.LTC: 0.001,
symbol.MAID: 10,
symbol.XMR: 0.015,
symbol.NMC: 0.01,
symbol.NAV: 0.01,
symbol.XEM: 15,
symbol.NEOS: 0.0001,
symbol.NXT: 1,
symbol.OMG: 0.3,
symbol.OMNI: 0.1,
symbol.PASC: 0.01,
symbol.PPC: 0.01,
symbol.POT: 0.01,
symbol.XPM: 0.01,
symbol.XRP: 0.15,
symbol.SC: 10,
symbol.STEEM: 0.01,
symbol.SBD: 0.01,
symbol.XLM: 0.00001,
symbol.STORJ: 1,
symbol.STRAT: 0.01,
symbol.AMP: 5,
symbol.SYS: 0.01,
symbol.USDT: 10,
symbol.VRC: 0.01,
symbol.VTC: 0.001,
symbol.VIA: 0.01,
symbol.ZEC: 0.001,
}

View File

@@ -148,14 +148,14 @@ func (p *Poloniex) GetExchangeFundTransferHistory() ([]exchange.FundHistory, err
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (p *Poloniex) GetExchangeHistory(cP pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
func (p *Poloniex) GetExchangeHistory(currencyPair pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}
// SubmitExchangeOrder submits a new order
func (p *Poloniex) SubmitExchangeOrder(cP pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) {
func (p *Poloniex) SubmitExchangeOrder(currencyPair pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) {
return 0, errors.New("not yet implemented")
}
@@ -208,3 +208,8 @@ func (p *Poloniex) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cu
func (p *Poloniex) GetWebsocket() (*exchange.Websocket, error) {
return p.Websocket, nil
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (p *Poloniex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return p.GetFee(feeBuilder)
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -127,11 +128,6 @@ func (w *WEX) GetTradablePairs() ([]string, error) {
return currencies, nil
}
// GetFee returns the exchange fee
func (w *WEX) GetFee() float64 {
return w.Fee
}
// GetInfo returns the WEX info
func (w *WEX) GetInfo() (Info, error) {
resp := Info{}
@@ -399,3 +395,60 @@ func (w *WEX) SendAuthenticatedHTTPRequest(method string, values url.Values, res
true,
w.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (w *WEX) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
info, err := w.GetInfo()
if err != nil {
return 0, err
}
currency := feeBuilder.FirstCurrency + feeBuilder.Delimiter + feeBuilder.SecondCurrency
fee = calculateTradingFee(info, currency, feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.CurrencyItem, feeBuilder.Amount, feeBuilder.BankTransactionType)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(info Info, currency string, purchasePrice, amount float64) (fee float64) {
fee = info.Pairs[common.StringToLower(currency)].Fee
return (fee / 100) * amount * purchasePrice
}
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func getInternationalBankDepositFee(currency string, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {
var fee float64
switch bankTransactionType {
case exchange.WireTransfer:
fallthrough
case exchange.WesternUnion:
switch currency {
case symbol.USD:
fee = 0.065 * amount
}
case exchange.MoneyGram:
switch currency {
case symbol.USD:
fee = 0.065 * amount
}
case exchange.Contact:
switch currency {
case symbol.USD:
fee = 0.065 * amount
}
}
return fee
}

View File

@@ -4,6 +4,8 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
var w WEX
@@ -40,13 +42,6 @@ func TestGetTradablePairs(t *testing.T) {
}
}
func TestGetFee(t *testing.T) {
t.Parallel()
if w.GetFee() != 0.2 {
t.Error("Test Failed - GetFee() error")
}
}
func TestGetInfo(t *testing.T) {
t.Parallel()
_, err := w.GetInfo()
@@ -166,3 +161,96 @@ func TestRedeemCoupon(t *testing.T) {
t.Error("Test Failed - RedeemCoupon() error", err)
}
}
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
}
}
func TestGetFee(t *testing.T) {
w.SetDefaults()
TestSetup(t)
var feeBuilder = setFeeBuilder()
// CryptocurrencyTradeFee Basic
if resp, err := w.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Error(err)
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
}
// CryptocurrencyTradeFee High quantity
feeBuilder = setFeeBuilder()
feeBuilder.Amount = 1000
feeBuilder.PurchasePrice = 1000
if resp, err := w.GetFee(feeBuilder); resp != float64(2000) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(2000), resp)
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
if resp, err := w.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.002), resp)
t.Error(err)
}
// CryptocurrencyTradeFee Negative purchase price
feeBuilder = setFeeBuilder()
feeBuilder.PurchasePrice = -1000
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := w.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.001), resp)
t.Error(err)
}
// CryptocurrencyWithdrawalFee Invalid currency
feeBuilder = setFeeBuilder()
feeBuilder.FirstCurrency = "hello"
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// CyptocurrencyDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
// InternationalBankDepositFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankDepositFee
if resp, err := w.GetFee(feeBuilder); resp != float64(0.065) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0.065), resp)
t.Error(err)
}
// InternationalBankWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
feeBuilder.CurrencyItem = symbol.USD
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
t.Error(err)
}
}

View File

@@ -1,5 +1,7 @@
package wex
import "github.com/thrasher-/gocryptotrader/currency/symbol"
// Response is a generic struct used for exchange API request result
type Response struct {
Return interface{} `json:"return"`
@@ -152,3 +154,19 @@ type RedeemCoupon struct {
TransID int64 `json:"transID"`
Error string `json:"error"`
}
// WithdrawalFees the large list of predefined withdrawal fees
// Prone to change, using highest value
var WithdrawalFees = map[string]float64{
symbol.BTC: 0.0004,
symbol.LTC: 0.001,
symbol.NMC: 0.1,
symbol.NVC: 0.1,
symbol.PPC: 0.1,
symbol.DSH: 0.001,
symbol.ETH: 0.003,
symbol.BCH: 0.001,
symbol.ZEC: 0.001,
symbol.USDT: 10,
symbol.XMR: 0.01,
}

View File

@@ -211,3 +211,8 @@ func (w *WEX) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Currenc
func (w *WEX) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (w *WEX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return w.GetFee(feeBuilder)
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/config"
"github.com/thrasher-/gocryptotrader/currency/symbol"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/request"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
@@ -112,11 +113,6 @@ func (y *Yobit) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the exchange fee
func (y *Yobit) GetFee() float64 {
return y.Fee
}
// GetInfo returns the Yobit info
func (y *Yobit) GetInfo() (Info, error) {
resp := Info{}
@@ -358,3 +354,110 @@ func (y *Yobit) SendAuthenticatedHTTPRequest(path string, params url.Values, res
return y.SendPayload("POST", apiPrivateURL, headers, strings.NewReader(encoded), result, true, y.Verbose)
}
// GetFee returns an estimate of fee based on type of transaction
func (y *Yobit) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64
switch feeBuilder.FeeType {
case exchange.CryptocurrencyTradeFee:
fee = calculateTradingFee(feeBuilder.PurchasePrice, feeBuilder.Amount)
case exchange.CryptocurrencyWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
case exchange.InternationalBankDepositFee:
fee = getInternationalBankDepositFee(feeBuilder.CurrencyItem, feeBuilder.Amount, feeBuilder.BankTransactionType)
case exchange.InternationalBankWithdrawalFee:
fee = getInternationalBankWithdrawalFee(feeBuilder.CurrencyItem, feeBuilder.Amount, feeBuilder.BankTransactionType)
}
if fee < 0 {
fee = 0
}
return fee, nil
}
func calculateTradingFee(purchasePrice, amount float64) (fee float64) {
fee = 0.002
return fee * amount * purchasePrice
}
func getWithdrawalFee(currency string) float64 {
return WithdrawalFees[currency]
}
func getInternationalBankWithdrawalFee(currency string, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {
var fee float64
switch bankTransactionType {
case exchange.PerfectMoney:
switch currency {
case symbol.USD:
fee = 0.02 * amount
}
case exchange.Payeer:
switch currency {
case symbol.USD:
fee = 0.03 * amount
case symbol.RUR:
fee = 0.006 * amount
}
case exchange.AdvCash:
switch currency {
case symbol.USD:
fee = 0.04 * amount
case symbol.RUR:
fee = 0.03 * amount
}
case exchange.Qiwi:
switch currency {
case symbol.RUR:
fee = 0.04 * amount
}
case exchange.Capitalist:
switch currency {
case symbol.USD:
fee = 0.06 * amount
}
}
return fee
}
// No real fees for yobit deposits, but want to be explicit on what each payment type supports
func getInternationalBankDepositFee(currency string, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {
var fee float64
switch bankTransactionType {
case exchange.PerfectMoney:
switch currency {
case symbol.USD:
fee = 0
}
case exchange.Payeer:
switch currency {
case symbol.USD:
fee = 0
case symbol.RUR:
fee = 0
}
case exchange.AdvCash:
switch currency {
case symbol.USD:
fee = 0
case symbol.RUR:
fee = 0
}
case exchange.Qiwi:
switch currency {
case symbol.RUR:
fee = 0
}
case exchange.Capitalist:
switch currency {
case symbol.USD:
fee = 0
case symbol.RUR:
fee = 0
}
}
return fee
}

Some files were not shown because too many files have changed in this diff Show More