diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index c23774cd..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Launch", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "${fileDirname}", - "env": {}, - "args": [] - } - ] -} \ No newline at end of file diff --git a/Const.go b/Const.go index f4032eff..9d197b2a 100644 --- a/Const.go +++ b/Const.go @@ -155,3 +155,16 @@ const ( COINBENE = "coinbene.com" ATOP = "a.top" ) + +const ( + SUB_ACCOUNT = iota //子账户 + SPOT // 币币交易 + _ + FUTURE //交割合约 + C2C //法币 + SPOT_MARGIN //币币杠杆交易 + WALLET // 资金账户 + _ + TIPS //余币宝 + SWAP //永续合约 +) diff --git a/FutureRestAPI.go b/FutureRestAPI.go index 2f0ccc42..a80e538b 100644 --- a/FutureRestAPI.go +++ b/FutureRestAPI.go @@ -51,6 +51,8 @@ type FutureRestAPI interface { */ PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) + LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) + /** * 取消订单 * @param symbol btc_usd:比特币 ltc_usd :莱特币 diff --git a/Models.go b/Models.go index ae341fa1..87fad236 100644 --- a/Models.go +++ b/Models.go @@ -6,20 +6,21 @@ import ( ) type Order struct { - Price float64 - Amount float64 - AvgPrice float64 - DealAmount float64 - Fee float64 - Cid string //客户端自定义ID - OrderID2 string - OrderID int //deprecated - OrderTime int - Status TradeStatus - Currency CurrencyPair - Side TradeSide - Type string //limit / market - OrderType int //0:default,1:maker,2:fok,3:ioc + Price float64 + Amount float64 + AvgPrice float64 + DealAmount float64 + Fee float64 + Cid string //客户端自定义ID + OrderID2 string + OrderID int //deprecated + Status TradeStatus + Currency CurrencyPair + Side TradeSide + Type string //limit / market + OrderType int //0:default,1:maker,2:fok,3:ioc + OrderTime int // create timestamp + FinishedTime int64 //finished timestamp } type Trade struct { @@ -75,7 +76,7 @@ type Ticker struct { type FutureTicker struct { *Ticker ContractType string `json:"omitempty"` - ContractId int `json:"contractId"` + ContractId string `json:"contractId"` LimitHigh float64 `json:"limitHigh,string"` LimitLow float64 `json:"limitLow,string"` HoldAmount float64 `json:"hold_amount,string"` @@ -102,7 +103,8 @@ func (dr DepthRecords) Less(i, j int) bool { } type Depth struct { - ContractType string //for future + ContractType string `json:"contract_type,omitempty"` //for futures + ContractId string `json:"contract_id,omitempty"` // for futures Pair CurrencyPair UTime time.Time AskList DepthRecords // Descending order @@ -164,6 +166,7 @@ type FutureOrder struct { LeverRate int //倍数 Fee float64 //手续费 ContractName string + FinishedTime int64 // finished timestamp } type FuturePosition struct { @@ -202,8 +205,8 @@ type TickSize struct { type FuturesContractInfo struct { *TickSize ContractVal float64 //合约面值(美元) - Delivery string //交割日期 - ContractType string // 本周 this_week 次周 next_week 季度 quarter + Delivery string //交割日期 + ContractType string // 本周 this_week 次周 next_week 季度 quarter } //api parameter struct @@ -218,3 +221,37 @@ type RepaymentParameter struct { BorrowParameter BorrowId string } + + +type TransferParameter struct { + Currency string `json:"currency"` + From int `json:"from"` + To int `json:"to"` + Amount float64 `json:"amount"` + SubAccount string `json:"sub_account"` + InstrumentId string `json:"instrument_id"` + ToInstrumentId string `json:"to_instrument_id"` +} + +type WithdrawParameter struct { + Currency string `json:"currency"` + Amount float64 `json:"amount,string"` + Destination int `json:"destination"` //提币到(2:OKCoin国际 3:OKEx 4:数字货币地址) + ToAddress string `json:"to_address"` + TradePwd string `json:"trade_pwd"` + Fee string `json:"fee"` +} + + +type DepositWithdrawHistory struct { + WithdrawalId string `json:"withdrawal_id,omitempty"` + Currency string `json:"currency"` + Txid string `json:"txid"` + Amount float64 `json:"amount,string"` + From string `json:"from,omitempty"` + To string `json:"to"` + Memo string `json:"memo,omitempty"` + Fee string `json:"fee"` + Status int `json:"status,string"` + Timestamp time.Time `json:"timestamp"` +} diff --git a/README.md b/README.md index c0b9993d..e46be10d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@
goex -
- [![](logo.png)] (https://www.jetbrains.com/?from=goex)
### goex目标 @@ -15,111 +13,37 @@ goex项目是为了统一并标准化各个数字资产交易平台的接口而 | 交易所 | 行情接口 | 交易接口 | 版本号 | | --- | --- | --- | --- | -| hbg.com | Y | Y | 1 | -| hbdm.com | Y| Y | 1 | -| okex.com | Y | Y | 3 | +| huobi.pro | Y | Y | 1 | +| hbdm.com | Y (REST / WS)| Y | 1 | +| okex.com (spot/future)| Y (REST / WS) | Y | 1 | +| okex.com (swap future) | Y | Y | 2 | | binance.com | Y | Y | 1 | | kucoin.com | Y | Y | 1 | | bitstamp.net | Y | Y | 1 | | bitfinex.com | Y | Y | 1 | | zb.com | Y | Y | 1 | | kraken.com | Y | Y | * | -| poloniex.com | Y | Y | * | -| aacoin.com | Y | Y | 1 | -| allcoin.ca | Y | Y | * | +| poloniex.com | Y | Y | * | | big.one | Y | Y | 2\|3 | -| fcoin.com | Y | Y | 2 | | hitbtc.com | Y | Y | * | | coinex.com | Y | Y | 1 | | exx.com | Y | Y | 1 | | bithumb.com | Y | Y | * | | gate.io | Y | N | 1 | -| btcbox.co.jp | Y | N | * | -| coinbig.com | Y | Y | * | -|coinbene.com|Y|Y|*| +| bittrex.com | Y | N | 1.1 | ### 安装goex库 +> go get ``` go get github.com/nntaoli-project/goex ``` >建议go mod 管理依赖 ``` require ( - github.com/nntaoli-project/goex v1.0.4 + github.com/nntaoli-project/goex latest ) ``` -### 例子 - -```golang - - package main - - import ( - "github.com/nntaoli-project/goex" - "github.com/nntaoli-project/goex/builder" - "log" - "time" - ) - - func main() { - apiBuilder := builder.NewAPIBuilder().HttpTimeout(5 * time.Second) - //apiBuilder := builder.NewAPIBuilder().HttpTimeout(5 * time.Second).HttpProxy("socks5://127.0.0.1:1080") - - //build spot api - //api := apiBuilder.APIKey("").APISecretkey("").ClientID("123").Build(goex.BITSTAMP) - api := apiBuilder.APIKey("").APISecretkey("").Build(goex.HUOBI_PRO) - log.Println(api.GetExchangeName()) - log.Println(api.GetTicker(goex.BTC_USD)) - log.Println(api.GetDepth(2, goex.BTC_USD)) - //log.Println(api.GetAccount()) - //log.Println(api.GetUnfinishOrders(goex.BTC_USD)) - - //build future api - futureApi := apiBuilder.APIKey("").APISecretkey("").BuildFuture(goex.HBDM) - log.Println(futureApi.GetExchangeName()) - log.Println(futureApi.GetFutureTicker(goex.BTC_USD, goex.QUARTER_CONTRACT)) - log.Println(futureApi.GetFutureDepth(goex.BTC_USD, goex.QUARTER_CONTRACT, 5)) - //log.Println(futureApi.GetFutureUserinfo()) // account - //log.Println(futureApi.GetFuturePosition(goex.BTC_USD , goex.QUARTER_CONTRACT))//position info - } - -``` - -### websocket 使用例子 - -```golang -import ( - "github.com/nntaoli-project/goex" - "github.com/nntaoli-project/goex/huobi" - //"github.com/nntaoli-project/goex/okcoin" - "log" -) - -func main() { - - //ws := okcoin.NewOKExFutureWs() //ok期货 - ws := huobi.NewHbdmWs() //huobi期货 - //设置回调函数 - ws.SetCallbacks(func(ticker *goex.FutureTicker) { - log.Println(ticker) - }, func(depth *goex.Depth) { - log.Println(depth) - }, func(trade *goex.Trade, contract string) { - log.Println(contract, trade) - }) - //订阅行情 - ws.SubscribeTrade(goex.BTC_USDT, goex.NEXT_WEEK_CONTRACT) - ws.SubscribeDepth(goex.BTC_USDT, goex.QUARTER_CONTRACT, 5) - ws.SubscribeTicker(goex.BTC_USDT, goex.QUARTER_CONTRACT) -} - -``` - -### 更多文档 - -[goex.TOP](https://goex.top) - ### 注意事项 1. 推荐使用GoLand开发。 @@ -127,7 +51,6 @@ func main() { 3. 不建议对现已存在的文件进行重新格式化,这样会导致commit特别糟糕。 4. 请用OrderID2这个字段代替OrderID 5. 请不要使用deprecated关键字标注的方法和字段,后面版本可能随时删除的 -6. 交流QQ群:574829125 ----------------- donate diff --git a/README_en.md b/README_en.md index 921944d8..f4a70cec 100644 --- a/README_en.md +++ b/README_en.md @@ -11,7 +11,7 @@ goex project is designed to unify and standardize the interfaces of each digital ### Exchanges are supported by goex `23+` | Exchange | Market API | Order API | Version | | --- | --- | --- | --- | -| hbg.com | Y | Y | 1 | +| huobi.pro | Y | Y | 1 | | hbdm.com | Y (REST / WS)| Y | 1 | | okex.com (spot/future)| Y (REST / WS) | Y | 1 | | okex.com (swap future) | Y | Y | 2 | @@ -21,104 +21,38 @@ goex project is designed to unify and standardize the interfaces of each digital | bitfinex.com | Y | Y | 1 | | zb.com | Y | Y | 1 | | kraken.com | Y | Y | * | -| poloniex.com | Y | Y | * | -| aacoin.com | Y | Y | 1 | -| allcoin.ca | Y | Y | * | +| poloniex.com | Y | Y | * | | big.one | Y | Y | 2\|3 | -| fcoin.com | Y (REST / WS) | Y | 2 | | hitbtc.com | Y | Y | * | | coinex.com | Y | Y | 1 | | exx.com | Y | Y | 1 | | bithumb.com | Y | Y | * | | gate.io | Y | N | 1 | -| btcbox.co.jp | Y | N | * | | bittrex.com | Y | N | 1.1 | -| btcchina.com | Y | Y | 1 | -| coinbig.com | Y | Y | * | ### Install goex -``` go get github.com/nntaoli-project/goex ``` - -### Example -```golang - - package main - - import ( - "github.com/nntaoli-project/goex" - "github.com/nntaoli-project/goex/builder" - "log" - "time" - ) - - func main() { - apiBuilder := builder.NewAPIBuilder().HttpTimeout(5 * time.Second) - //apiBuilder := builder.NewAPIBuilder().HttpTimeout(5 * time.Second).HttpProxy("socks5://127.0.0.1:1080") - - //build spot api - //api := apiBuilder.APIKey("").APISecretkey("").ClientID("123").Build(goex.BITSTAMP) - api := apiBuilder.APIKey("").APISecretkey("").Build(goex.HUOBI_PRO) - log.Println(api.GetExchangeName()) - log.Println(api.GetTicker(goex.BTC_USD)) - log.Println(api.GetDepth(2, goex.BTC_USD)) - //log.Println(api.GetAccount()) - //log.Println(api.GetUnfinishOrders(goex.BTC_USD)) - - //build future api - futureApi := apiBuilder.APIKey("").APISecretkey("").BuildFuture(goex.HBDM) - log.Println(futureApi.GetExchangeName()) - log.Println(futureApi.GetFutureTicker(goex.BTC_USD, goex.QUARTER_CONTRACT)) - log.Println(futureApi.GetFutureDepth(goex.BTC_USD, goex.QUARTER_CONTRACT, 5)) - //log.Println(futureApi.GetFutureUserinfo()) // account - //log.Println(futureApi.GetFuturePosition(goex.BTC_USD , goex.QUARTER_CONTRACT))//position info - } +> go get -``` +``` go get github.com/nntaoli-project/goex ``` +> go mod -### websocket Example -```golang -import ( - "github.com/nntaoli-project/goex" - "github.com/nntaoli-project/goex/huobi" - //"github.com/nntaoli-project/goex/okcoin" - "log" +``` +require ( + github.com/nntaoli-project/goex latest ) - -func main() { - - //ws := okcoin.NewOKExFutureWs() //ok future - ws := huobi.NewHbdmWs() //huobi future - //setup callback - ws.SetCallbacks(func(ticker *goex.FutureTicker) { - log.Println(ticker) - }, func(depth *goex.Depth) { - log.Println(depth) - }, func(trade *goex.Trade, contract string) { - log.Println(contract, trade) - }) - //subscribe - ws.SubscribeTrade(goex.BTC_USDT, goex.NEXT_WEEK_CONTRACT) - ws.SubscribeDepth(goex.BTC_USDT, goex.QUARTER_CONTRACT, 5) - ws.SubscribeTicker(goex.BTC_USDT, goex.QUARTER_CONTRACT) -} - ``` -### More Detail - -[goex.TOP](https://goex.top) - -# Highly Recommended(IMPORTANCE) +#Recommended(IMPORTANCE) 1. use GoLand development. 2. turn off the auto format function. 3. DONOT reformat existing files, which will result in a particularly bad commit. 4. use the OrderID2 field instead of the OrderID +5. can't use the deprecated field or method -### How to find us -Join QQ group: [574829125](#) - +donate & Buy a cup of Coffee for author ----------------- +BTC:13cBHLk6B7t3Uj7caJbCwv1UaiuiA6Qx8z -### Buy me a Coffe - -Buy me a Coffe   Buy me a Coffe +LTC:LVxM7y1K2dnpuNBU42ei3dKzPySf4VAm1H + +ETH:0x98573ddb33cdddce480c3bc1f9279ccd88ca1e93 \ No newline at end of file diff --git a/Utils.go b/Utils.go index 0222988e..4d196637 100644 --- a/Utils.go +++ b/Utils.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/google/uuid" "io/ioutil" + "math" "net/url" "strconv" "strings" @@ -92,10 +93,13 @@ func ToInt64(v interface{}) int64 { } } -//n :保留的小数点位数,去除末尾多余的0(StripTrailingZeros) -func FloatToString(v float64, n int) string { - ret := strconv.FormatFloat(v, 'f', n, 64) - return strconv.FormatFloat(ToFloat64(ret), 'f', -1, 64) //StripTrailingZeros +func FloatToString(v float64, precision int) string { + return fmt.Sprint(FloatToFixed(v, precision)) +} + +func FloatToFixed(v float64, precision int) float64 { + p := math.Pow(10, float64(precision)) + return math.Round(v*p) / p } func ValuesToJson(v url.Values) ([]byte, error) { @@ -124,5 +128,5 @@ func FlateDecompress(data []byte) ([]byte, error) { func GenerateOrderClientId(size int) string { uuidStr := strings.Replace(uuid.New().String(), "-", "", 32) - return "goex-" + uuidStr[0:size-5] + return "goex" + uuidStr[0:size-5] } diff --git a/Utils_test.go b/Utils_test.go index 713b24d1..7e6a4bc9 100644 --- a/Utils_test.go +++ b/Utils_test.go @@ -8,8 +8,9 @@ import ( func TestFloatToString(t *testing.T) { assert.Equal(t, "1", FloatToString(1.10231000, 0)) assert.Equal(t, "0.102", FloatToString(0.10231000, 3)) - assert.Equal(t, "1.10231", FloatToString(1.10231000, 8)) + assert.Equal(t, "189.61", FloatToString(189.61020000, 2)) assert.NotEqual(t, "1.10231000", FloatToString(1.10231000, 8)) + assert.Equal(t, 0.13, FloatToFixed(0.1299999, 5)) } func TestGenerateOrderClientId(t *testing.T) { diff --git a/WalletApi.go b/WalletApi.go new file mode 100644 index 00000000..c88309e6 --- /dev/null +++ b/WalletApi.go @@ -0,0 +1,14 @@ +package goex + +type WalletApi interface { + //获取钱包资产 + GetAccount() (*Account, error) + //提币 + Withdrawal(param WithdrawParameter) (withdrawId string, err error) + //划转资产 + Transfer(param TransferParameter) error + //获取提币记录 + GetWithDrawHistory(currency *Currency) ([]DepositWithdrawHistory, error) + //获取充值记录 + GetDepositHistory(currency *Currency) ([]DepositWithdrawHistory, error) +} diff --git a/binance/BinanceSwap.go b/binance/BinanceSwap.go index f569a6d5..00014735 100644 --- a/binance/BinanceSwap.go +++ b/binance/BinanceSwap.go @@ -19,6 +19,10 @@ type BinanceSwap struct { Binance } +func (bs *BinanceSwap) LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) { + return bs.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, 0, 10) +} + func NewBinanceSwap(config *APIConfig) *BinanceSwap { if config.Endpoint == "" { config.Endpoint = baseUrl @@ -289,6 +293,11 @@ func (bs *BinanceSwap) Transfer(currency Currency, transferType int, amount floa return ToInt64(respmap["tranId"]), nil } +func (bs *BinanceSwap) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) { + fOrder, err := bs.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, matchPrice, leverRate) + return fOrder.OrderID2, err +} + /** * @deprecated * 期货下单 @@ -299,13 +308,23 @@ func (bs *BinanceSwap) Transfer(currency Currency, transferType int, amount floa * @param openType 1:开多 2:开空 3:平多 4:平空 * @param matchPrice 是否为对手价 0:不是 1:是 ,当取值为1时,price无效 */ -func (bs *BinanceSwap) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) { +func (bs *BinanceSwap) PlaceFutureOrder2(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (*FutureOrder, error) { + fOrder := &FutureOrder{ + Currency: currencyPair, + ClientOid: GenerateOrderClientId(32), + Price: ToFloat64(price), + Amount: ToFloat64(amount), + OrderType: openType, + LeverRate: leverRate, + ContractName: contractType, + } pair := bs.adaptCurrencyPair(currencyPair) path := bs.apiV1 + ORDER_URI params := url.Values{} params.Set("symbol", pair.ToSymbol("")) params.Set("quantity", amount) + params.Set("newClientOrderId", fOrder.ClientOid) switch openType { case OPEN_BUY, CLOSE_SELL: @@ -325,20 +344,22 @@ func (bs *BinanceSwap) PlaceFutureOrder(currencyPair CurrencyPair, contractType, resp, err := HttpPostForm2(bs.httpClient, path, params, map[string]string{"X-MBX-APIKEY": bs.accessKey}) if err != nil { - return "", err + return fOrder, err } respmap := make(map[string]interface{}) err = json.Unmarshal(resp, &respmap) if err != nil { - return "", err + return fOrder, err } orderId := ToInt(respmap["orderId"]) if orderId <= 0 { - return "", errors.New(string(resp)) + return fOrder, errors.New(string(resp)) } - return strconv.Itoa(orderId), nil + fOrder.OrderID2 = strconv.Itoa(orderId) + + return fOrder, nil } /** diff --git a/binance/BinanceWs.go b/binance/BinanceWs.go index 0bb2eb5d..4c3a5213 100644 --- a/binance/BinanceWs.go +++ b/binance/BinanceWs.go @@ -92,7 +92,7 @@ func (bnWs *BinanceWs) SetCallbacks( bnWs.klineCallback = klineCallback } -func (bnWs *BinanceWs) Subscribe(endpoint string, handle func(msg []byte) error) { +func (bnWs *BinanceWs) Subscribe(endpoint string, handle func(msg []byte) error) *WsConn { wsConn := NewWsBuilder(). WsUrl(endpoint). AutoReconnect(). @@ -102,6 +102,7 @@ func (bnWs *BinanceWs) Subscribe(endpoint string, handle func(msg []byte) error) Build() bnWs.wsConns = append(bnWs.wsConns, wsConn) go bnWs.exitHandler(wsConn) + return wsConn } func (bnWs *BinanceWs) Close() { @@ -121,11 +122,10 @@ func (bnWs *BinanceWs) SubscribeDepth(pair CurrencyPair, size int) error { handle := func(msg []byte) error { rawDepth := struct { - LastUpdateID int64 `json:"T"` - Bids [][]interface{} `json:"b"` - Asks [][]interface{} `json:"a"` + LastUpdateID int64 `json:"lastUpdateId"` + Bids [][]interface{} `json:"bids"` + Asks [][]interface{} `json:"asks"` }{} - err := json.Unmarshal(msg, &rawDepth) if err != nil { fmt.Println("json unmarshal error for ", string(msg)) diff --git a/bitmex/bitmex.go b/bitmex/bitmex.go index 7bee6db3..a10e80bb 100644 --- a/bitmex/bitmex.go +++ b/bitmex/bitmex.go @@ -120,6 +120,11 @@ type BitmexOrder struct { } func (bm *bitmex) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) { + fOrder, err := bm.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, matchPrice, leverRate) + return fOrder.OrderID2, err +} + +func (bm *bitmex) PlaceFutureOrder2(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (*FutureOrder, error) { var createOrderParameter BitmexOrder var resp struct { @@ -150,13 +155,29 @@ func (bm *bitmex) PlaceFutureOrder(currencyPair CurrencyPair, contractType, pric // createOrderParameter.OrderQty = -ToInt(amount) //} + fOrder := &FutureOrder{ + ClientOid: createOrderParameter.ClOrdID, + Currency: currencyPair, + Price: ToFloat64(price), + Amount: ToFloat64(amount), + OType: openType, + LeverRate: leverRate, + ContractName: contractType, + } + err := bm.doAuthRequest("POST", "/api/v1/order", bm.toJson(createOrderParameter), &resp) if err != nil { - return "", err + return fOrder, err } - return resp.OrderId, nil + fOrder.OrderID2 = resp.OrderId + + return fOrder, nil +} + +func (bm *bitmex) LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) { + return bm.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, 0, 10) } func (bm *bitmex) FutureCancelOrder(currencyPair CurrencyPair, contractType, orderId string) (bool, error) { diff --git a/builder/APIBuilder.go b/builder/APIBuilder.go index e2835fea..637c9004 100644 --- a/builder/APIBuilder.go +++ b/builder/APIBuilder.go @@ -335,3 +335,16 @@ func (builder *APIBuilder) BuildSpotWs(exName string) (SpotWsApi, error) { } return nil, errors.New("not support the exchange " + exName) } + +func (builder *APIBuilder) BuildWallet(exName string) (WalletApi, error) { + switch exName { + case OKEX_V3, OKEX: + return okex.NewOKEx(&APIConfig{ + HttpClient: builder.client, + ApiKey: builder.apiKey, + ApiSecretKey: builder.secretkey, + ApiPassphrase: builder.apiPassphrase, + }).OKExWallet, nil + } + return nil, errors.New("not support the wallet api for " + exName) +} diff --git a/coinbene/CoinbeneSwap.go b/coinbene/CoinbeneSwap.go index d55bb151..421582a2 100644 --- a/coinbene/CoinbeneSwap.go +++ b/coinbene/CoinbeneSwap.go @@ -192,6 +192,18 @@ func (swap *CoinbeneSwap) PlaceFutureOrder(currencyPair CurrencyPair, contractTy return data.orderId, nil } +func (swap *CoinbeneSwap) LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) { + orderId, err := swap.PlaceFutureOrder(currencyPair, contractType, price, amount, openType, 0, 10) + return &FutureOrder{ + Currency: currencyPair, + OrderID2: orderId, + Price: ToFloat64(price), + Amount: ToFloat64(amount), + OType: openType, + ContractName: contractType, + }, err +} + func (swap *CoinbeneSwap) FutureCancelOrder(currencyPair CurrencyPair, contractType, orderId string) (bool, error) { var param struct { OrderId string `json:"orderId"` diff --git a/huobi/Hbdm.go b/huobi/Hbdm.go index 9ad23327..31485d60 100644 --- a/huobi/Hbdm.go +++ b/huobi/Hbdm.go @@ -57,8 +57,11 @@ var ( FuturesContractInfos []FuturesContractInfo ) -func init() { +func hbdmInit() { go func() { + defer func() { + logger.Info("[hbdm] Get Futures Tick Size Finished.") + }() interval := time.Second intervalTimer := time.NewTimer(interval) @@ -104,9 +107,9 @@ func init() { ContractType: info.ContractType, }) } - interval = 10 * time.Minute + return reset: - intervalTimer.Reset(interval) + intervalTimer.Reset(10 * interval) } } @@ -118,6 +121,7 @@ func NewHbdm(conf *APIConfig) *Hbdm { if conf.Endpoint == "" { conf.Endpoint = defaultBaseUrl } + hbdmInit() return &Hbdm{conf} } @@ -194,10 +198,14 @@ func (dm *Hbdm) GetFuturePosition(currencyPair CurrencyPair, contractType string var positions []FuturePosition for _, d := range data { + if d.ContractType != contractType { + continue + } + switch d.Direction { case "buy": positions = append(positions, FuturePosition{ - ContractType: contractType, + ContractType: d.ContractType, ContractId: int64(ToInt(d.ContractCode[3:])), Symbol: currencyPair, BuyAmount: d.Volume, @@ -208,7 +216,7 @@ func (dm *Hbdm) GetFuturePosition(currencyPair CurrencyPair, contractType string LeverRate: d.LeverRate}) case "sell": positions = append(positions, FuturePosition{ - ContractType: contractType, + ContractType: d.ContractType, ContractId: int64(ToInt(d.ContractCode[3:])), Symbol: currencyPair, SellAmount: d.Volume, @@ -224,6 +232,11 @@ func (dm *Hbdm) GetFuturePosition(currencyPair CurrencyPair, contractType string } func (dm *Hbdm) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) { + fOrder, err := dm.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, matchPrice, leverRate) + return fOrder.OrderID2, err +} + +func (dm *Hbdm) PlaceFutureOrder2(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (*FutureOrder, error) { var data struct { OrderId int64 `json:"order_id"` COrderId int64 `json:"client_order_id"` @@ -232,6 +245,7 @@ func (dm *Hbdm) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, params := &url.Values{} path := "/api/v1/contract_order" + params.Add("client_order_id", fmt.Sprint(time.Now().UnixNano())) params.Add("contract_type", contractType) params.Add("symbol", currencyPair.CurrencyA.Symbol) params.Add("volume", amount) @@ -251,7 +265,26 @@ func (dm *Hbdm) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, err := dm.doRequest(path, params, &data) - return fmt.Sprint(data.OrderId), err + fOrd := &FutureOrder{ + ClientOid: params.Get("client_order_id"), + ContractName: contractType, + Currency: currencyPair, + Price: ToFloat64(price), + Amount: ToFloat64(amount), + OType: openType, + } + + if err != nil { + return fOrd, err + } + + fOrd.OrderID2 = fmt.Sprint(data.OrderId) + + return fOrd, err +} + +func (dm *Hbdm) LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) { + return dm.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, 0, 10) } func (dm *Hbdm) FutureCancelOrder(currencyPair CurrencyPair, contractType, orderId string) (bool, error) { @@ -598,9 +631,9 @@ func (dm *Hbdm) adaptOffsetDirectionToOpenType(offset, direction string) int { switch offset { case "close": if direction == "buy" { - return CLOSE_BUY - } else { return CLOSE_SELL + } else { + return CLOSE_BUY } default: @@ -670,15 +703,17 @@ func (dm *Hbdm) doRequest(path string, params *url.Values, data interface{}) err } func (dm *Hbdm) formatPriceSize(contract string, currency Currency, price string) string { - var tickSize = 0 + var tickSize = 2 //default set 2 for _, v := range FuturesContractInfos { if (v.ContractType == contract || v.InstrumentID == contract) && v.UnderlyingIndex == currency.Symbol { if v.PriceTickSize == 0 { break } - for v.PriceTickSize < 1 { + tickSize = 0 + priceSize := v.PriceTickSize + for priceSize < 1 { tickSize++ - v.PriceTickSize *= 10 + priceSize *= 10 } break } diff --git a/huobi/Hbdm_Ws.go b/huobi/Hbdm_Ws.go index 19a67d74..6b460768 100644 --- a/huobi/Hbdm_Ws.go +++ b/huobi/Hbdm_Ws.go @@ -76,6 +76,7 @@ func NewHbdmWs() *HbdmWs { //Heartbeat(func() []byte { return []byte("{\"op\":\"ping\"}") }(), 5*time.Second). DecompressFunc(GzipDecompress). ProtoHandleFunc(hbdmWs.handle) + go hbdmInit() return hbdmWs } @@ -144,7 +145,7 @@ func (hbdmWs *HbdmWs) handle(msg []byte) error { hbdmWs.wsConn.SendMessage(pong) return nil } - + var resp WsResponse err := json.Unmarshal(msg, &resp) if err != nil { @@ -171,6 +172,7 @@ func (hbdmWs *HbdmWs) handle(msg []byte) error { dep := ParseDepthFromResponse(depResp) dep.ContractType = contract + dep.ContractId = hbdmWs.getContractId(contract) dep.Pair = pair dep.UTime = time.Unix(0, resp.Ts*int64(time.Millisecond)) @@ -266,3 +268,12 @@ func (hbdmWs *HbdmWs) adaptTime(tm string) int64 { return t.UnixNano() / 1e6 } + +func (hbdmWs *HbdmWs) getContractId(alias string) string { + for _, info := range FuturesContractInfos { + if info.ContractType == alias { + return info.InstrumentID + } + } + return "" +} diff --git a/huobi/HuobiPro.go b/huobi/HuobiPro.go index 314f8766..2f2a49eb 100644 --- a/huobi/HuobiPro.go +++ b/huobi/HuobiPro.go @@ -55,6 +55,8 @@ type HuoBiProSymbol struct { QuoteCurrency string PricePrecision float64 AmountPrecision float64 + MinAmount float64 + MinValue float64 SymbolPartition string Symbol string } @@ -108,7 +110,7 @@ func NewHuoBiProSpot(client *http.Client, apikey, secretkey string) *HuoBiPro { accinfo, err := hb.GetAccountInfo(HB_SPOT_ACCOUNT) if err != nil { hb.accountId = "" - //panic(err) + panic(err) } else { hb.accountId = accinfo.Id Log.Info("account state :", accinfo.State) @@ -742,6 +744,8 @@ func (hbpro *HuoBiPro) GetCurrenciesPrecision() ([]HuoBiProSymbol, error) { sym.QuoteCurrency = _sym["quote-currency"].(string) sym.PricePrecision = _sym["price-precision"].(float64) sym.AmountPrecision = _sym["amount-precision"].(float64) + sym.MinAmount = _sym["min-order-amt"].(float64) + sym.MinValue = _sym["min-order-value"].(float64) sym.SymbolPartition = _sym["symbol-partition"].(string) sym.Symbol = _sym["symbol"].(string) Symbols = append(Symbols, sym) diff --git a/okex/OKExFuture.go b/okex/OKExFuture.go index b4303cff..6a02e1c1 100644 --- a/okex/OKExFuture.go +++ b/okex/OKExFuture.go @@ -4,11 +4,9 @@ import ( "errors" "fmt" "sort" - "strings" "sync" "time" - "github.com/google/uuid" . "github.com/nntaoli-project/goex" "github.com/nntaoli-project/goex/internal/logger" ) @@ -81,11 +79,27 @@ func (ok *OKExFuture) GetAllFutureContractInfo() ([]FutureContractInfo, error) { } func (ok *OKExFuture) GetContractInfo(contractId string) (*FutureContractInfo, error) { + now := time.Now() + if len(ok.allContractInfo.contractInfos) == 0 || + (ok.allContractInfo.uTime.Hour() < 16 && now.Hour() == 16 && now.Minute() <= 10) { + ok.Lock() + defer ok.Unlock() + + infos, err := ok.GetAllFutureContractInfo() + if err != nil { + logger.Errorf("Get All Futures Contract Infos Error=%s", err) + } else { + ok.allContractInfo.contractInfos = infos + ok.allContractInfo.uTime = now + } + } + for _, itm := range ok.allContractInfo.contractInfos { if itm.InstrumentID == contractId { return &itm, nil } } + return nil, errors.New("unknown contract id " + contractId) } @@ -101,7 +115,7 @@ func (ok *OKExFuture) GetFutureContractId(pair CurrencyPair, contractAlias strin hour := now.Hour() minute := now.Minute() - if ok.allContractInfo.uTime.IsZero() || (hour == 16 && minute <= 11) { + if ok.allContractInfo.uTime.IsZero() || (ok.allContractInfo.uTime.Hour() < 16 && hour == 16 && minute <= 11) { ok.Lock() defer ok.Unlock() @@ -357,7 +371,7 @@ func (ok *OKExFuture) PlaceFutureOrder2(matchPrice int, ord *FutureOrder) (*Futu return nil, errors.New("ord param is nil") } param.InstrumentId = ok.GetFutureContractId(ord.Currency, ord.ContractName) - param.ClientOid = strings.Replace(uuid.New().String(), "-", "", 32) + param.ClientOid = GenerateOrderClientId(32) param.Type = ord.OType param.OrderType = ord.OrderType param.Price = ok.normalizePrice(ord.Price, ord.Currency) @@ -386,42 +400,24 @@ func (ok *OKExFuture) PlaceFutureOrder2(matchPrice int, ord *FutureOrder) (*Futu } func (ok *OKExFuture) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) { - urlPath := "/api/futures/v3/order" - var param struct { - ClientOid string `json:"client_oid"` - InstrumentId string `json:"instrument_id"` - Type string `json:"type"` - OrderType string `json:"order_type"` - Price string `json:"price"` - Size string `json:"size"` - MatchPrice string `json:"match_price"` - Leverage string `json:"leverage"` - } - - var response struct { - Result bool `json:"result"` - ErrorMessage string `json:"error_message"` - ErrorCode string `json:"error_code"` - ClientOid string `json:"client_oid"` - OrderId string `json:"order_id"` - } - - param.InstrumentId = ok.GetFutureContractId(currencyPair, contractType) - param.ClientOid = strings.Replace(uuid.New().String(), "-", "", 32) - param.Type = fmt.Sprint(openType) - param.OrderType = "0" - param.Price = price - param.Size = amount - param.MatchPrice = fmt.Sprint(matchPrice) - param.Leverage = fmt.Sprint(leverRate) - - reqBody, _, _ := ok.BuildRequestBody(param) - err := ok.DoRequest("POST", urlPath, reqBody, &response) - if err != nil { - return "", err - } - - return response.OrderId, nil + fOrder, err := ok.PlaceFutureOrder2(matchPrice, &FutureOrder{ + Price: ToFloat64(price), + Amount: ToFloat64(amount), + OType: openType, + ContractName: contractType, + Currency: currencyPair, + }) + return fOrder.OrderID2, err +} + +func (ok *OKExFuture) LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) { + return ok.PlaceFutureOrder2(0, &FutureOrder{ + Currency: currencyPair, + Price: ToFloat64(price), + Amount: ToFloat64(amount), + OType: openType, + ContractName: contractType, + }) } func (ok *OKExFuture) FutureCancelOrder(currencyPair CurrencyPair, contractType, orderId string) (bool, error) { diff --git a/okex/OKExFuturesWs.go b/okex/OKExFuturesWs.go index 05423d00..2de0cb47 100644 --- a/okex/OKExFuturesWs.go +++ b/okex/OKExFuturesWs.go @@ -68,7 +68,11 @@ func (okV3Ws *OKExV3FuturesWs) getChannelName(currencyPair CurrencyPair, contrac } else { prefix = "futures" contractId = okV3Ws.base.OKExFuture.GetFutureContractId(currencyPair, contractType) - logger.Info("contractid=", contractId) + // logger.Info("contractid=", contractId) + } + + if contractId == "" { + return "" } channelName = prefix + "/%s:" + contractId @@ -82,6 +86,9 @@ func (okV3Ws *OKExV3FuturesWs) SubscribeDepth(currencyPair CurrencyPair, contrac } chName := okV3Ws.getChannelName(currencyPair, contractType) + if chName == "" { + return errors.New("subscribe error, get channel name fail") + } return okV3Ws.v3Ws.Subscribe(map[string]interface{}{ "op": "subscribe", @@ -92,7 +99,12 @@ func (okV3Ws *OKExV3FuturesWs) SubscribeTicker(currencyPair CurrencyPair, contra if okV3Ws.tickerCallback == nil { return errors.New("please set ticker callback func") } + chName := okV3Ws.getChannelName(currencyPair, contractType) + if chName == "" { + return errors.New("subscribe error, get channel name fail") + } + return okV3Ws.v3Ws.Subscribe(map[string]interface{}{ "op": "subscribe", "args": []string{fmt.Sprintf(chName, "ticker")}}) @@ -102,7 +114,12 @@ func (okV3Ws *OKExV3FuturesWs) SubscribeTrade(currencyPair CurrencyPair, contrac if okV3Ws.tradeCallback == nil { return errors.New("please set trade callback func") } + chName := okV3Ws.getChannelName(currencyPair, contractType) + if chName == "" { + return errors.New("subscribe error, get channel name fail") + } + return okV3Ws.v3Ws.Subscribe(map[string]interface{}{ "op": "subscribe", "args": []string{fmt.Sprintf(chName, "trade")}}) @@ -119,6 +136,10 @@ func (okV3Ws *OKExV3FuturesWs) SubscribeKline(currencyPair CurrencyPair, contrac } chName := okV3Ws.getChannelName(currencyPair, contractType) + if chName == "" { + return errors.New("subscribe error, get channel name fail") + } + return okV3Ws.v3Ws.Subscribe(map[string]interface{}{ "op": "subscribe", "args": []string{fmt.Sprintf(chName, fmt.Sprintf("candle%ds", seconds))}}) @@ -192,6 +213,7 @@ func (okV3Ws *OKExV3FuturesWs) handle(channel string, data json.RawMessage) erro Vol: t.Volume24h, Date: uint64(date.UnixNano() / int64(time.Millisecond)), }, + ContractId: t.InstrumentId, ContractType: alias, }) } @@ -232,6 +254,7 @@ func (okV3Ws *OKExV3FuturesWs) handle(channel string, data json.RawMessage) erro alias, pair := okV3Ws.getContractAliasAndCurrencyPairFromInstrumentId(depthResp[0].InstrumentId) dep.Pair = pair dep.ContractType = alias + dep.ContractId = depthResp[0].InstrumentId dep.UTime, _ = time.Parse(time.RFC3339, depthResp[0].Timestamp) for _, itm := range depthResp[0].Asks { dep.AskList = append(dep.AskList, DepthRecord{ diff --git a/okex/OKExSpot.go b/okex/OKExSpot.go index 8367fefc..2f111bb3 100644 --- a/okex/OKExSpot.go +++ b/okex/OKExSpot.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/go-openapi/errors" . "github.com/nntaoli-project/goex" + "github.com/nntaoli-project/goex/internal/logger" "sort" "strings" "time" @@ -110,7 +111,7 @@ func (ok *OKExSpot) BatchPlaceOrders(orders []Order) ([]PlaceOrderResponse, erro func (ok *OKExSpot) PlaceOrder(ty string, ord *Order) (*Order, error) { urlPath := "/api/spot/v3/orders" param := PlaceOrderParam{ - ClientOid: ok.UUID(), + ClientOid: GenerateOrderClientId(32), InstrumentId: ord.Currency.AdaptUsdToUsdt().ToLower().ToSymbol("-"), } @@ -205,9 +206,11 @@ func (ok *OKExSpot) CancelOrder(orderId string, currency CurrencyPair) (bool, er }{currency.AdaptUsdToUsdt().ToLower().ToSymbol("-")} reqBody, _, _ := ok.BuildRequestBody(param) var response struct { - ClientOid string `json:"client_oid"` - OrderId string `json:"order_id"` - Result bool `json:"result"` + ClientOid string `json:"client_oid"` + OrderId string `json:"order_id"` + Result bool `json:"result"` + ErrorCode string `json:"error_code"` + ErrorMessage string `json:"error_message"` } err := ok.OKEx.DoRequest("POST", urlPath, reqBody, &response) if err != nil { @@ -216,7 +219,7 @@ func (ok *OKExSpot) CancelOrder(orderId string, currency CurrencyPair) (bool, er if response.Result { return true, nil } - return false, errors.New(400, "cancel fail, unknown error") + return false, errors.New(400, fmt.Sprintf("cancel fail, %s", response.ErrorMessage)) } type OrderResponse struct { @@ -266,7 +269,7 @@ func (ok *OKExSpot) adaptOrder(response OrderResponse) *Order { date, err := time.Parse(time.RFC3339, response.Timestamp) //log.Println(date.Local().UnixNano()/int64(time.Millisecond)) if err != nil { - println(err) + logger.Error("parse timestamp err=", err, ",timestamp=", response.Timestamp) } else { ordInfo.OrderTime = int(date.UnixNano() / int64(time.Millisecond)) } @@ -312,7 +315,21 @@ func (ok *OKExSpot) GetUnfinishOrders(currency CurrencyPair) ([]Order, error) { } func (ok *OKExSpot) GetOrderHistorys(currency CurrencyPair, currentPage, pageSize int) ([]Order, error) { - panic("unsupported") + urlPath := fmt.Sprintf("/api/spot/v3/orders?instrument_id=%s&state=7", currency.AdaptUsdToUsdt().ToSymbol("-")) + var response []OrderResponse + err := ok.OKEx.DoRequest("GET", urlPath, "", &response) + if err != nil { + return nil, err + } + + var orders []Order + for _, itm := range response { + ord := ok.adaptOrder(itm) + ord.Currency = currency + orders = append(orders, *ord) + } + + return orders, nil } func (ok *OKExSpot) GetExchangeName() string { @@ -479,3 +496,55 @@ func (ok *OKExSpot) GetTrades(currencyPair CurrencyPair, since int64) ([]Trade, return trades, nil } + +type OKExSpotSymbol struct { + BaseCurrency string + QuoteCurrency string + PricePrecision float64 + AmountPrecision float64 + MinAmount float64 + MinValue float64 + SymbolPartition string + Symbol string +} + +func (ok *OKExSpot) GetCurrenciesPrecision() ([]OKExSpotSymbol, error) { + var response []struct { + InstrumentId string `json:"instrument_id"` + BaseCurrency string `json:"base_currency"` + QuoteCurrency string `json:"quote_currency"` + MinSize float64 `json:"min_size,string"` + SizeIncrement string `json:"size_increment"` + TickSize string `json:"tick_size"` + } + err := ok.DoRequest("GET", "/api/spot/v3/instruments", "", &response) + if err != nil { + return nil, err + } + + var Symbols []OKExSpotSymbol + for _, v := range response { + var sym OKExSpotSymbol + sym.BaseCurrency = v.BaseCurrency + sym.QuoteCurrency = v.QuoteCurrency + sym.Symbol = v.InstrumentId + sym.MinAmount = v.MinSize + + pres := strings.Split(v.TickSize, ".") + if len(pres) == 1 { + sym.PricePrecision = 0 + } else { + sym.PricePrecision = float64(len(pres[1])) + } + + pres = strings.Split(v.SizeIncrement, ".") + if len(pres) == 1 { + sym.AmountPrecision = 0 + } else { + sym.AmountPrecision = float64(len(pres[1])) + } + + Symbols = append(Symbols, sym) + } + return Symbols, nil +} diff --git a/okex/OKExSwap.go b/okex/OKExSwap.go index 5753d09f..0f8e9b18 100644 --- a/okex/OKExSwap.go +++ b/okex/OKExSwap.go @@ -6,10 +6,8 @@ import ( "fmt" "net/url" "strconv" - "strings" "time" - "github.com/google/uuid" . "github.com/nntaoli-project/goex" ) @@ -280,12 +278,31 @@ type PlaceOrdersInfo struct { } func (ok *OKExSwap) PlaceFutureOrder(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (string, error) { + fOrder, err := ok.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, matchPrice, leverRate) + return fOrder.OrderID2, err +} +func (ok *OKExSwap) PlaceFutureOrder2(currencyPair CurrencyPair, contractType, price, amount string, openType, matchPrice, leverRate int) (*FutureOrder, error) { + cid := GenerateOrderClientId(32) reqBody, _, _ := ok.OKEx.BuildRequestBody(PlaceOrderInfo{ - BasePlaceOrderInfo{ClientOid: strings.Replace(uuid.New().String(), "-", "", 32), Price: price, MatchPrice: fmt.Sprint(matchPrice), Type: fmt.Sprint(openType), Size: amount}, + BasePlaceOrderInfo{ + ClientOid: cid, + Price: price, + MatchPrice: fmt.Sprint(matchPrice), + Type: fmt.Sprint(openType), + Size: amount}, ok.adaptContractType(currencyPair), }) + fOrder := &FutureOrder{ + ClientOid: cid, + Currency: currencyPair, + ContractName: contractType, + OType: openType, + Price: ToFloat64(price), + Amount: ToFloat64(amount), + } + var resp struct { BaseResponse OrderID string `json:"order_id"` @@ -294,14 +311,20 @@ func (ok *OKExSwap) PlaceFutureOrder(currencyPair CurrencyPair, contractType, pr err := ok.DoRequest("POST", PLACE_ORDER, reqBody, &resp) if err != nil { - return "", err + return fOrder, err } if resp.ErrorMessage != "" { - return "", errors.New(fmt.Sprintf("%s:%s", resp.ErrorCode, resp.ErrorMessage)) + return fOrder, errors.New(fmt.Sprintf("%s:%s", resp.ErrorCode, resp.ErrorMessage)) } - return resp.OrderID, nil + fOrder.OrderID2 = resp.OrderID + + return fOrder, nil +} + +func (ok *OKExSwap) LimitFuturesOrder(currencyPair CurrencyPair, contractType, price, amount string, openType int) (*FutureOrder, error) { + return ok.PlaceFutureOrder2(currencyPair, contractType, price, amount, openType, 0, 10) } func (ok *OKExSwap) FutureCancelOrder(currencyPair CurrencyPair, contractType, orderId string) (bool, error) { diff --git a/okex/OKExWallet.go b/okex/OKExWallet.go index 32c1864e..d6d0c079 100644 --- a/okex/OKExWallet.go +++ b/okex/OKExWallet.go @@ -4,20 +4,6 @@ import ( "errors" "fmt" . "github.com/nntaoli-project/goex" - "time" -) - -const ( - SUB_ACCOUNT = iota //子账户 - SPOT // 币币交易 - _ - FUTURE //交割合约 - C2C //法币 - SPOT_MARGIN //币币杠杆交易 - WALLET // 资金账户 - _ - TIPS //余币宝 - SWAP //永续合约 ) const ( @@ -26,25 +12,6 @@ const ( WITHDRAWAL_COIN = 4 //提币到数字货币地址,跨平台提币或者提到自己钱包 ) -type TransferParameter struct { - Currency string `json:"currency"` - From int `json:"from"` - To int `json:"to"` - Amount float64 `json:"amount"` - SubAccount string `json:"sub_account"` - InstrumentId string `json:"instrument_id"` - ToInstrumentId string `json:"to_instrument_id"` -} - -type WithdrawParameter struct { - Currency string `json:"currency"` - Amount float64 `json:"amount,string"` - Destination int `json:"destination"` //提币到(2:OKCoin国际 3:OKEx 4:数字货币地址) - ToAddress string `json:"to_address"` - TradePwd string `json:"trade_pwd"` - Fee string `json:"fee"` -} - type OKExWallet struct { *OKEx } @@ -166,35 +133,22 @@ func (ok *OKExWallet) GetWithDrawalFee(currency *Currency) ([]WithdrawFee, error return response, nil } -type DepositWithDrawHistory struct { - WithdrawalId string `json:"withdrawal_id,omitempty"` - Currency string `json:"currency"` - Txid string `json:"txid"` - Amount float64 `json:"amount,string"` - From string `json:"from,omitempty"` - To string `json:"to"` - Memo string `json:"memo,omitempty"` - Fee string `json:"fee"` - Status int `json:"status,string"` - Timestamp time.Time `json:"timestamp"` -} - -func (ok *OKExWallet) GetWithDrawalHistory(currency *Currency) ([]DepositWithDrawHistory, error) { +func (ok *OKExWallet) GetWithDrawHistory(currency *Currency) ([]DepositWithdrawHistory, error) { urlPath := "/api/account/v3/withdrawal/history" if currency != nil && *currency != UNKNOWN { urlPath += "/" + currency.Symbol } - var response []DepositWithDrawHistory + var response []DepositWithdrawHistory err := ok.DoRequest("GET", urlPath, "", &response) return response, err } -func (ok *OKExWallet) GetDepositHistory(currency *Currency) ([]DepositWithDrawHistory, error) { +func (ok *OKExWallet) GetDepositHistory(currency *Currency) ([]DepositWithdrawHistory, error) { urlPath := "/api/account/v3/deposit/history" if currency != nil && *currency != UNKNOWN { urlPath += "/" + currency.Symbol } - var response []DepositWithDrawHistory + var response []DepositWithdrawHistory err := ok.DoRequest("GET", urlPath, "", &response) return response, err } diff --git a/okex/OKEx_test.go b/okex/OKEx_test.go index aa477773..e4502658 100644 --- a/okex/OKEx_test.go +++ b/okex/OKEx_test.go @@ -239,3 +239,11 @@ func TestOKExMargin_CancelOrder(t *testing.T) { func TestOKExMargin_GetOneOrder(t *testing.T) { t.Log(okex.OKExMargin.GetOneOrder("3174778420532224", goex.EOS_USDT)) } + +func TestOKExSpot_GetCurrenciesPrecision(t *testing.T) { + t.Log(okex.OKExSpot.GetCurrenciesPrecision()) +} + +func TestOKExSpot_GetOrderHistorys(t *testing.T) { + t.Log(okex.OKExSpot.GetOrderHistorys(goex.BTC_USDT, 1, 10)) +} diff --git a/okex/README.md b/okex/README.md index b0793fae..9fd39471 100644 --- a/okex/README.md +++ b/okex/README.md @@ -23,7 +23,7 @@ var okex = NewOKEx(&goex.APIConfig{ ) //接口调用,更多接口调用请看代码 - log.Prinitln(okexSpot.GetAccount()) //获取账户资产信息 + log.Println(okexSpot.GetAccount()) //获取账户资产信息 //okexSpot.BatchPlaceOrders([]goex.Order{...}) //批量下单,单个交易对同时最大只能下10笔 log.Println(okexSwap.GetFutureUserinfo()) //获取账户权益信息 log.Println(okexFuture.GetFutureUserinfo())//获取账户权益信息