exchanges: Add OKX support (#1005)

* public endpoints methods added

* Completing mapping REST endpoints

* Binanceus Wrapper methods -Partially

* Binanceus Wrapper methods -Partially

* BinaWra functions with test funs; Not Completed

* Finalizing wrapper methods & test

* Fix & Complete wrapper functions

* Finalizing wrapper methods & test

* Adding Stream Datas

* WS Test functions

* CI: Fix golangci-lint linter issues

* CI: Fix reverting unnessesary changes and type conversion issues

* CI: Fix reverting unnessesary changes and type conversion issues

* Adding Public endpoints and tests

* Adding Market and Public Endpoints

* Adding Public endoints

* Public Trading Endpoints & Authenticated Trade order methods

* Adding Authenticated Methods and Tests

* Adding algo and Funding Authenticated endpoints

* Adding funding trading endpoints and correspondint tests

* adding authenticated endpoints

* Completing Block Trading endpoints and added subaccount endpoints

* Completing sub account and grid Trading endpoints

* Adding Rate Limit and missing endpoints

* Wrapper and Websocket handlers

* Fixing Websocket Test and Push Data Handler Issues

* Fixing Websocket Test and Push Data Handler Issues

* Fixing linter issues, package dependency, and other slight tempos

* Fixing linter and slight tempos

* Update on test functions, and Rest and Websocket Endpoint handlers

* Remove okex, adding comments, and slight fixes on endpoints.

* Fixing linter issues and adding comments

* Slight code changes, updating documentation, and n and linter issues

* Fix context and configuration endpoint issues

* slight fixes on config and test files

* adding some missing test and fix linter issues

* fix linter issue

* Slight fixes on code structure, shorthand exp,and ot and other

* Fix slight linter issue

* Slight code fixes and fixing linter issues

* fixing linter iissues

* fixing linter iissues

* slight linter issue fix

* slight linter issue fix

* Fix on models, type convert funcs and endpoints

* Adding Error messages map and update of models

* Fix on error message string and linter issues

* Fix slight linter issue

* Fix slight linter issue

* Fixing type converts, models, and linter issues

* Adding Ws fixes

* Slight fix on websocket and other issues

* Adding slight websocket fixes

* Remove 'books5' channel default subscription

* Small changes on default subscription and checksum

* Fix slight websocket tempos

* Fix Wrapper function tempost and linter issues

* Resolving slight naming and other issues

* Resolve slight pointer issues

* resolve slight linter issues

* Resolve config files issue

* Update websocket and wrapper funcs with test and docs

* fixs on websocket multiplexer, types, and other slight issues

* fix slight linter issues

* slight update on web-socket orderbook and tickers

* fix slight issues and websocket runtime errors

* Slight unit test fix and assing simple semaphore

* FIx race issue

* Update on authenticated endpoints

* Fix wsSetupRun check in websocket 'setupWsAuth' func

* Update wsSetupRun check in websocket 'setupWsAuth' func

* Slight update on websocket handling

* Fix some race conditions

* fix slight tempos

* fix authenticated test issues

* Update on conditional statements

* slight update on unit test

* fix unit test tempos

* Fix slight tempos

* Change check map from struct valued to bool valued

* slight fix trial

* Slight unit test update

* Fix websocket timeout error

* Updating websocket subscription endpoints, and unit tests

* update unit tests

* Slight issue on wrapper method 'GetActiveOrders'

* Overall code update

* Addressing missing review comments

* Fix unit test tempo and linter issue

* Monor fix

* Slight update

* Slight unit test fix

* Slight fixes

* Slight fixes

* Fixing on missing review comments

* Adding WS Fixes

* slight fix

* Monor fix on unit test

* Minor convert issue

* Minor change on WS

* Monor logic fix

* Fix code structure and logic issues

* Fixing small typos

* fix slight data format issue

* Update on trade and order wrapper methods

* Adding slight update

* fix on order detail

* Slight update on FetchTradablePairs wrapper method

* Slight update on wrapper

* Update on deserialization and other slight issues

* Final update

* Resolve missing review comments

* Slight update on config and unit test

* minor fix on GetDepositAddress param

* Minor fix
This commit is contained in:
Samuael A
2022-12-09 03:44:29 +03:00
committed by GitHub
parent d7d4933f93
commit 2ac165a477
54 changed files with 16943 additions and 3977 deletions

154
exchanges/okx/README.md Normal file
View File

@@ -0,0 +1,154 @@
# GoCryptoTrader package Okx
<img src="/common/gctlogo.png?raw=true" width="350px" height="350px" hspace="70">
[![Build Status](https://github.com/thrasher-corp/gocryptotrader/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/thrasher-corp/gocryptotrader/actions/workflows/tests.yml)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/okx)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
This okx package is part of the GoCryptoTrader codebase.
## This is still in active development
You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk)
## Okx Exchange
### Current Features
+ REST Support
+ Websocket Support
### How to enable
[Enable via configuration](https://github.com/thrasher-corp/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
+ Individual package example below:
```go
// Exchanges will be abstracted out in further updates and examples will be
// supplied then
```
### How to do REST public/private calls
+ If enabled via "configuration".json file the exchange will be added to the
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
the wrapper interface functions for accessing exchange data. View routines.go
for an example of integration usage with GoCryptoTrader. Rudimentary example
below:
main.go
```go
var ok exchange.IBotExchange
for i := range bot.Exchanges {
if bot.Exchanges[i].GetName() == "Okx" {
y = bot.Exchanges[i]
}
}
// Public calls - wrapper functions
// Fetches current ticker information
tick, err := ok.FetchTicker()
if err != nil {
// Handle error
}
// Fetches current orderbook information
ob, err := ok.FetchOrderbook()
if err != nil {
// Handle error
}
// Private calls - wrapper functions - make sure your APIKEY, APISECRET, and API_CLIENT_ID are
// set and AuthenticatedAPISupport is set to true
// Fetches current account information
accountInfo, err := ok.GetAccountInfo()
if err != nil {
// Handle error
}
```
+ If enabled via individually importing package, rudimentary example below:
```go
// Public calls
// Fetches current ticker information
ticker, err := ok.GetTicker()
if err != nil {
// Handle error
}
// Fetches current orderbook information
ob, err := ok.GetOrderBook()
if err != nil {
// Handle error
}
// Fetches historic trade data within the timeframe provided
tradeDatas, err := ok.GetHistoricTrades(...)
if err != nil {
// Handle error
}
// Returns an estimate of fee based on the type of transaction
fee, err := ok.GetFeeByType(...)
if err != nil {
// Handle error
}
// Private calls - make sure your APIKEY and APISECRET are set and
// AuthenticatedAPISupport is set to true
// Submits an order and the exchange and returns its tradeID
orderID, err := ok.SubmitOrder(...)
if err != nil {
// Handle error
}
// ModifyOrder will allow of changing orderbook placement and limit to market conversion
updatedOrder, err := ok.ModifyOrder(...)
if err != nil {
// Handle error
}
```
### How to do Websocket public/private calls
```go
// Exchanges will be abstracted out in further updates and examples will be
// supplied then
```
### Please click GoDocs chevron above to view current GoDoc information for this package
## Contribution
Please feel free to submit any pull requests or suggest any desired features to be added.
When submitting a PR, please abide by our coding guidelines:
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
+ Pull requests need to be based on and opened against the `master` branch.
## Donations
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
***bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc***

4319
exchanges/okx/okx.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,524 @@
package okx
import "errors"
// ErrorCodes and their corresponding error messages
var (
ErrorCodes = map[string]error{
"60001": errors.New("\"OK_ACCESS_KEY\" can not be empty"),
"60002": errors.New("\"OK_ACCESS_SIGN\" can not be empty"),
"60003": errors.New("\"OK_ACCESS_PASSPHRASE\" can not be empty"),
"60004": errors.New("invalid OK_ACCESS_TIMESTAMP"),
"60005": errors.New("invalid OK_ACCESS_KEY"),
"60006": errors.New("timestamp request expired"),
"60007": errors.New("invalid sign"),
"60008": errors.New("public websocket services do not support subscribing to private channels"),
"60009": errors.New("login failed"),
"60011": errors.New("please log in"),
"60012": errors.New("illegal request"),
"60013": errors.New("invalid args"),
"60014": errors.New("requests too frequent"),
"60015": errors.New("connection closed as there was no data transmission in the last 30 seconds"),
"60016": errors.New("buffer is full, cannot write data"),
"60017": errors.New("invalid url path"),
"60018": errors.New("the {0} {1} {2} {3} {4} does not exist"),
"60019": errors.New("invalid op {op}"),
"60020": errors.New("apikey subscription amount exceeds the limit {0}"),
"60021": errors.New("this operation does not support multiple accounts login"),
"60022": errors.New("bulk login partially succeeded"),
"60023": errors.New("bulk login requests too frequent"),
"60024": errors.New("wrong passphrase"),
"60025": errors.New("token subscription amount exceeds the limit {0}"),
"60026": errors.New("batch login by apikey and token simultaneously is not supported"),
"60027": errors.New("parameter {0} can not be empty"),
"60028": errors.New("private websocket services do not support subscribing to public channels"),
"60029": errors.New("only users who're VIP5 and above can subscribe to books-l2-tbt order book channels"),
"60030": errors.New("only users who're VIP4 and above can subscribe to books50-l2-tbt order book channels"),
"63999": errors.New("internal system error"),
"70000": errors.New("rFQ does not exist"),
"70001": errors.New("quote does not exist"),
"70002": errors.New("block trade does not exist"),
"70003": errors.New("public block trade does not exist"),
"70004": errors.New("invalid instrument {0}"),
"70005": errors.New("the number of legs in RFQ cannot exceed maximum value"),
"70006": errors.New("does not meet the minimum asset requirement"),
"70007": errors.New("underlying index {0} does not exist under instType {1}"),
"70008": errors.New("operation failed under MMP status, the frozen window is {0} seconds"),
"70009": errors.New("data must have at least 1 valid element"),
"70011": errors.New("duplicate setting for instType {0}"),
"70100": errors.New("duplicate instruments in legs array"),
"70101": errors.New("duplicate clRfqId"),
"70102": errors.New("no counterparties specified"),
"70103": errors.New("invalid counterparty"),
"70105": errors.New("the total value should be greater than the min notional value {0}"),
"70106": errors.New("the trading amount does not meet the min tradable amount requirement"),
"70107": errors.New("the number of counterparties cannot exceed maximum value"),
"70109": errors.New("counterparties for selected instruments are currently unavailable"),
"70200": errors.New("the RFQ with {0} status cannot be canceled"),
"70203": errors.New("cancellation failed as rfq count exceeds the limit {0}"),
"70207": errors.New("cancellation failed as you do not have any active RFQs"),
"70208": errors.New("cancellation failed as service is unavailable now, please try again later"),
"70301": errors.New("duplicate clQuoteId"),
"70303": errors.New("the RFQ with {0} status cannot be quoted"),
"70304": errors.New("price should be an integer multiple of the tick size"),
"70305": errors.New("bid price cannot be higher than offer price"),
"70306": errors.New("the legs of quote do not match the legs of {0}"),
"70307": errors.New("size should be in integral multiples of the lot size"),
"70308": errors.New("quote to your own RFQ is not allowed"),
"70309": errors.New("quote to the same RFQ with the same side is not allowed"),
"70310": errors.New("quoted price of instId {0} cannot exceed your preset price limit"),
"70400": errors.New("the quote with {0} status cannot be canceled"),
"70408": errors.New("cancellation failed as quote count exceeds the limit {0}"),
"70409": errors.New("cancellation failed as you do not have any active quotes"),
"70501": errors.New("RFQ {0} is not quoted by {1}"),
"70502": errors.New("the legs do not match the legs of {0}"),
"70503": errors.New("the legs of execution do not match the legs of {0}"),
"70504": errors.New("execution failed as the RFQ status is {0}"),
"70505": errors.New("execution failed as the quote status is {0}"),
"70511": errors.New("execution is being processed"),
"56000": errors.New("block trade does not exist"),
"56001": errors.New("the number of multi-legs cannot exceed {0}"),
"56002": errors.New("the number of multi-legs does not match with the verified one"),
"56003": errors.New("duplicated clBlockTdId"),
"56004": errors.New("trade with yourself is not allowed"),
"56005": errors.New("\"clBlockTdId\" should be the same as the verified one"),
"56006": errors.New("the role should be different from the verified one"),
"56007": errors.New("leg no.{0} does not match with the verified one"),
"56008": errors.New("duplicate instruments in legs array"),
"59000": errors.New("your settings failed as you have positions or open orders"),
"59001": errors.New("switching unavailable as you have borrowings"),
"59004": errors.New("only IDs with the same instrument type are supported"),
"59005": errors.New("when users transfer the margin by themselves in isolated mode, the value of the asset allocated to the position for the first time must be greater than 10,000 USDT"),
"59100": errors.New("you have open positions. please cancel all open positions before changing the leverage"),
"59101": errors.New("you have pending orders with isolated positions. please cancel all the pending isolated margin orders and adjust the leverage"),
"59102": errors.New("leverage exceeds the maximum leverage. please adjust the leverage"),
"59103": errors.New("leverage is too low and no sufficient margin in your account. please adjust the leverage"),
"59104": errors.New("the leverage is too high. the borrowed position has exceeded the maximum position of this leverage. please adjust the leverage"),
"59105": errors.New("leverage can not be less than {0}. please adjust the leverage"),
"59106": errors.New("the max available margin corresponding to your order tier please adjust your margin and place a new order"),
"59107": errors.New("you have pending cross margin orders under the service, please modify the leverage after canceling all pending cross margin orders"),
"59108": errors.New("low leverage and insufficient margin, please adjust the leverage"),
"59109": errors.New("account equity less than the required margin amount after adjustment. please adjust the leverage "),
"59110": errors.New("the instrument type corresponding to this {0} does not support the tgtCcy parameter"),
"59111": errors.New("you cannot query the leverage of cross derivatives positions under a PM account"),
"59112": errors.New("you have isolated/cross pending orders. please cancel them before adjusting your leverage"),
"59200": errors.New("insufficient account balance"),
"59201": errors.New("negative account balance"),
"59300": errors.New("margin call failed. position does not exist"),
"59301": errors.New("margin adjustment failed for exceeding the max limit"),
"59302": errors.New("you have pending close orders, please modify the margin after canceling the orders"),
"59303": errors.New("insufficient available margin, add margin or reduce the borrowing amount"),
"59304": errors.New("insufficient equity for borrowing, keep enough funds to pay interest for at least one day"),
"59305": errors.New("use VIP loan first to set the VIP loan priority"),
"59306": errors.New("your borrowing amount exceeds the max limit"),
"59307": errors.New("you are not eligible for VIP loans"),
"59308": errors.New("unable to repay VIP loan due to insufficient borrow limit"),
"59309": errors.New("unable to repay an amount that exceeds the borrowed amount"),
"59310": errors.New("your account does not support VIP loan"),
"59311": errors.New("unable to set up as there is VIP loan"),
"59312": errors.New("{currency} does not support VIP loans"),
"59401": errors.New("holdings already reached the limit"),
"59402": errors.New("none of the passed instId is in live state, please check them separately"),
"59500": errors.New("only the APIKey of the main account has permission"),
"59501": errors.New("only 50 APIKeys can be created per account"),
"59502": errors.New("note name cannot be duplicate with the currently created APIKey note name"),
"59503": errors.New("each APIKey can bind up to 20 IP addresses"),
"59504": errors.New("the sub account does not support the withdrawal function"),
"59505": errors.New("the passphrase format is incorrect"),
"59506": errors.New("apikey does not exist"),
"59507": errors.New("the two accounts involved in a transfer must be two different sub accounts under the same parent account"),
"59508": errors.New("the sub account of {0} is suspended"),
"59509": errors.New("account does not have permission to reset MMP status"),
"59510": errors.New("sub-account does not exist"),
"59512": errors.New("unable to set up this permission for ND brokers sub accounts. by default, all ND sub accounts can transfer funds out"),
"59601": errors.New("this sub-account name already exists, try another name"),
"59602": errors.New("number of API keys exceeds the limit"),
"59603": errors.New("number of sub accounts exceeds the limit"),
"59604": errors.New("only the main account APIkey can access this API"),
"59605": errors.New("this API key does not exist in your sub-account, try another API key"),
"59606": errors.New("transfer funds to your main account before deleting your sub-account"),
"59608": errors.New("only the broker account has permission to operate this API"),
"59609": errors.New("broker already exists"),
"59610": errors.New("broker does not exist"),
"59611": errors.New("broker unverified"),
"59612": errors.New("cannot convert time format"),
"59613": errors.New("there is currently no escrow relationship established with the sub account"),
"59614": errors.New("managed sub account do not support this operation"),
"59615": errors.New("the time interval between the begin date and end date cannot exceed 180 days"),
"59616": errors.New("begin date cannot be greater than end date"),
"59617": errors.New("sub-account created. failed to set up account level"),
"59618": errors.New("failed to create sub-account"),
"58000": errors.New("account type {0} does not supported when getting the sub-account balance"),
"58001": errors.New("incorrect trade password"),
"58002": errors.New("please activate savings account first"),
"58003": errors.New("currency type is not supported by savings account"),
"58004": errors.New("account blocked (transfer & withdrawal endpoint: either end of the account does not authorize the transfer)"),
"58005": errors.New("the purchase/redeemed amount must be no greater than {0}"),
"58006": errors.New("service unavailable for token {0}"),
"58007": errors.New("abnormal assets interface. please try again later"),
"58008": errors.New("you do not have assets in this currency"),
"58009": errors.New("currency pair do not exist"),
"58010": errors.New("the chain {0} is not supported"),
"58011": errors.New("sorry, we are unable to provide services to unverified users in {Region} due to local laws and regulations. please verify your account in order to use the services"),
"58012": errors.New("sorry, you can't transfer assets to this recipient as OKX are unable to provide services to unverified users in {region} due to local laws and regulations"),
"58100": errors.New("the trading product triggers risk control, and the platform has suspended the fund transfer-out function with related users. please wait patiently"),
"58101": errors.New("transfer suspended (transfer endpoint: either end of the account does not authorize the transfer)"),
"58102": errors.New("too frequent transfer (transfer too frequently)"),
"58104": errors.New("since your P2P transaction is abnormal, you are restricted from making fund transfers. please contact customer support to remove the restriction"),
"58105": errors.New(`since your P2P transaction is abnormal, you are restricted from making fund transfers. please transfer funds on our website or app to complete identity verification`),
"58106": errors.New("please enable the account for spot contract"),
"58107": errors.New("please enable the account for futures contract"),
"58108": errors.New("please enable the account for option contract"),
"58109": errors.New("please enable the account for swap contract"),
"58110": errors.New("the contract triggers risk control, and the platform has suspended the fund transfer function of it. please wait patiently"),
"58111": errors.New("funds transfer unavailable as the perpetual contract is charging the funding fee. please try again later"),
"58112": errors.New("your fund transfer failed. please try again later"),
"58114": errors.New("transfer amount must be more than 0"),
"58115": errors.New("sub-account does not exist"),
"58116": errors.New("transfer amount exceeds the limit"),
"58117": errors.New("account assets are abnormal, please deal with negative assets before transferring"),
"58119": errors.New("{0} sub-account has no permission to transfer out, please set first"),
"58120": errors.New("the transfer service is temporarily unavailable, please try again later"),
"58121": errors.New("this transfer will result in a high-risk level of your position, which may lead to forced liquidation. You need to re-adjust the transfer amount to make sure the position is at a safe level before proceeding with the transfer"),
"58122": errors.New("a portion of your spot is being used for delta offset between positions. if the transfer amount exceeds the available amount, it may affect current spot-derivatives risk offset structure, which will result in an increased maintenance margin requirement (MMR) rate. please be aware of your risk level"),
"58123": errors.New("parameter from can not equal to parameter to"),
"58200": errors.New("withdrawal from {0} to {1} is unavailable for this currency"),
"58201": errors.New("withdrawal amount exceeds the daily limit"),
"58202": errors.New("the minimum withdrawal amount for NEO is 1, and the amount must be an integer"),
"58203": errors.New("please add a withdrawal address"),
"58204": errors.New("withdrawal suspended"),
"58205": errors.New("withdrawal amount exceeds the upper limit"),
"58206": errors.New("withdrawal amount is lower than the lower limit"),
"58207": errors.New("withdrawal address is not in the verification-free whitelist"),
"58208": errors.New("withdrawal failed. please link your email"),
"58209": errors.New("sub-accounts cannot be deposits or withdrawals"),
"58210": errors.New("withdrawal fee exceeds the upper limit"),
"58211": errors.New("withdrawal fee is lower than the lower limit (withdrawal endpoint: incorrect fee)"),
"58212": errors.New("withdrawal fee should be {0} of the withdrawal amount"),
"58214": errors.New("withdrawals suspended due to {chainName} maintenance"),
"58215": errors.New("withdrawal ID does not exist"),
"58216": errors.New("operation not allowed"),
"58217": errors.New("you cannot withdraw your asset at the moment due to a risk detected in your withdrawal address, contact customer support for details"),
"58218": errors.New("your saved withdrawal account has expired"),
"58220": errors.New("the withdrawal order is already canceled"),
"58221": errors.New("missing label of withdrawal address"),
"58222": errors.New("illegal withdrawal address"),
"58224": errors.New("this type of crypto does not support on-chain withdrawing to OKX addresses. please withdraw through internal transfers"),
"58225": errors.New("sorry, you can't transfer assets to this recipient as OKX are unable to provide services to unverified users in {region} due to local laws and regulations"),
"58300": errors.New("deposit-address count exceeds the limit"),
"58301": errors.New("deposit-address not exist"),
"58302": errors.New("deposit-address needs tag"),
"58303": errors.New("deposit for the chain {0} is closed now"),
"58304": errors.New("failed to create invoice"),
"58350": errors.New("insufficient balance"),
"58351": errors.New("invoice expired"),
"58352": errors.New("invalid invoice"),
"58353": errors.New("deposit amount must be within limits"),
"58354": errors.New("you have reached the limit of 10000 invoices per day"),
"58355": errors.New("permission denied. please contact your account manager"),
"58356": errors.New("the accounts of the same node do not support the lightning network deposit or withdrawal"),
"58357": errors.New("{0} is not allowed to create a deposit address"),
"58358": errors.New("fromCcy should not be the same as toCcy"),
"58370": errors.New("the daily usage of small assets convert exceeds the limit"),
"58371": errors.New("small assets exceed the maximum limit"),
"58372": errors.New("insufficient small assets"),
"55000": errors.New("cannot be transferred out within 30 minutes after delivery"),
"54000": errors.New("margin transactions unavailable"),
"54001": errors.New("only multi-currency margin account can be set to borrow coins automatically"),
"52900": errors.New("general Invalid request"),
"52901": errors.New("invalid base asset"),
"52902": errors.New("invalid quote asset"),
"52903": errors.New("invalid quote amount"),
"52904": errors.New("invalid quote side"),
"52905": errors.New("invalid quote price"),
"52907": errors.New("order not found"),
"52908": errors.New("invalid order ID"),
"52909": errors.New("duplicated client order Id"),
"52910": errors.New("service unavailable, please try again later"),
"52911": errors.New("RFQ service unavailable, please try again later"),
"52912": errors.New("server timeout"),
"52913": errors.New("trade rejected"),
"52915": errors.New("cannot quote due to large amounts of RFQ and insufficient liquidity, please try again later"),
"52916": errors.New("insufficient balance in funding account"),
"52917": errors.New("RFQ quantity cannot be less than the lower limit"),
"52918": errors.New("insufficient balance in funding account"),
"52919": errors.New("parameter {param} of convert trading is inconsistent with the quotation"),
"52920": errors.New("quantity of convert trading cannot exceed the quotation quantity"),
"52921": errors.New("quote traded, please ask for quote again"),
"52922": errors.New("quote expired, please ask for quote again"),
"52923": errors.New("service unavailable, please try again later"),
"51720": errors.New("redeem error"),
"51721": errors.New("cancel redeem error"),
"51722": errors.New("redeem already complete"),
"51723": errors.New("early redemption is not supported"),
"51724": errors.New("redemption is currently not supported"),
"51725": errors.New("cancellation is currently not supported"),
"51726": errors.New("cancellation of subscriptions/redemptions is not supported"),
"51727": errors.New("the subscription quantity is below the minimum requirement"),
"51728": errors.New("the subscription quantity is above the maximum limit"),
"51729": errors.New("this project has not reached the redemption date"),
"51730": errors.New("sold out"),
"52000": errors.New("no market data found"),
"51000": errors.New("parameter {0} error"),
"51001": errors.New("instrument ID does not exist"),
"51002": errors.New("instrument ID does not match underlying index"),
"51003": errors.New("either client order ID or order ID is required"),
"51004": errors.New("order amount exceeds current tier limit, please lower the leverage"),
"51005": errors.New("order amount exceeds the limit"),
"51006": errors.New("order price is not within the price limit (max buy price: {0} min sell price: {1})"),
"51007": errors.New("order placement failed. order amount should be at least 1 contract (showing up when placing an order with less than 1 contract)"),
"51008": errors.New("delegate failed. Insufficient {0} balance in account"),
"51009": errors.New("order placement function is blocked by the platform"),
"51010": errors.New("operation is not supported under the current account mode"),
"51011": errors.New("duplicated order ID"),
"51012": errors.New("token does not exist"),
"51014": errors.New("index does not exist"),
"51015": errors.New("instrument ID does not match instrument type"),
"51016": errors.New("duplicated client order ID"),
"51017": errors.New("borrow amount exceeds the limit"),
"51018": errors.New("user with option account can not hold net short positions"),
"51019": errors.New("no net long positions can be held under cross margin mode in options"),
"51020": errors.New("order amount should be greater than the min available amount"),
"51021": errors.New("contract to be listed"),
"51022": errors.New("contract suspended"),
"51023": errors.New("position does not exist"),
"51024": errors.New("trading account is blocked"),
"51025": errors.New("order count exceeds the limit"),
"51026": errors.New("instrument type does not match underlying index"),
"51027": errors.New("contract expired"),
"51028": errors.New("contract under delivery"),
"51029": errors.New("contract is being settled"),
"51030": errors.New("funding fee is being settled"),
"51031": errors.New("this order price is not within the closing price range"),
"51032": errors.New("closing all positions at market price"),
"51033": errors.New("the total amount per order for this pair has reached the upper limit"),
"51037": errors.New("the current account risk status only supports you to place IOC orders that can reduce the risk of your account"),
"51038": errors.New("there is already an IOC order under the current risk module that reduces the risk of the account"),
"51039": errors.New("leverage cannot be adjusted for the cross positions of futures and perpetual swap under the PM account"),
"51040": errors.New("cannot adjust margins for long isolated options positions"),
"51041": errors.New("portfolio margin account only supports net mode"),
"51044": errors.New("the order type {0}, {1} is not allowed to set stop loss and take profit"),
"51046": errors.New("the take profit trigger price should be higher than the order price"),
"51047": errors.New("the stop loss trigger price should be lower than the order price"),
"51048": errors.New("the take profit trigger price should be lower than the order price"),
"51049": errors.New("the stop loss trigger price should be higher than the order price"),
"51050": errors.New("the take profit trigger price should be higher than the best ask price"),
"51051": errors.New("the stop loss trigger price should be lower than the best ask price"),
"51052": errors.New("the take profit trigger price should be lower than the best bid price"),
"51053": errors.New("the stop loss trigger price should be higher than the best bid price"),
"51054": errors.New("getting information timed out, please try again later"),
"51055": errors.New("futures grid is not available in portfolio margin mode"),
"51056": errors.New("action not allowed"),
"51057": errors.New("futures grid is not available in simple trading mode"),
"51058": errors.New("no position"),
"51059": errors.New("strategy for the current state does not support this operation"),
"51101": errors.New("entered amount exceeds the max pending order amount per transaction"),
"51102": errors.New("entered amount exceeds the max pending count"),
"51103": errors.New("entered amount exceeds the max pending order count of the underlying asset"),
"51104": errors.New("entered amount exceeds the max pending order amount of the underlying asset"),
"51105": errors.New("entered amount exceeds the max order amount of the contract"),
"51106": errors.New("entered amount exceeds the max order amount of the underlying asset"),
"51107": errors.New("entered amount exceeds the max holding amount"),
"51108": errors.New("positions exceed the limit for closing out with the market price"),
"51109": errors.New("no available offer"),
"51110": errors.New("you can only place a limit order after call auction has started"),
"51111": errors.New("maximum {0} orders can be placed in bulk"),
"51112": errors.New("close order size exceeds your available size"),
"51113": errors.New("market-price liquidation requests too frequent"),
"51115": errors.New("cancel all pending close-orders before liquidation"),
"51116": errors.New("order price or trigger price exceeds {0}"),
"51117": errors.New("pending close-orders count exceeds limit"),
"51120": errors.New("order quantity is less than {0}, please try again"),
"51121": errors.New("order count should be the integer multiples of the lot size"),
"51122": errors.New("order price should be higher than the min price {0}"),
"51124": errors.New("you can only place limit orders during call auction"),
"51125": errors.New("currently there are reduce + reverse position pending orders in margin trading. please cancel all reduce + reverse position pending orders and continue"),
"51126": errors.New("currently there are reduce only pending orders in margin trading. please cancel all reduce only pending orders and continue"),
"51127": errors.New("available balance is 0"),
"51128": errors.New("multi-currency margin account can not do cross-margin trading"),
"51129": errors.New("the value of the position and buy order has reached the position limit, and no further buying is allowed"),
"51130": errors.New("fixed margin currency error"),
"51131": errors.New("insufficient balance"),
"51132": errors.New("your position amount is negative and less than the minimum trading amount"),
"51133": errors.New("reduce-only feature is unavailable for the spot transactions by multi-currency margin account"),
"51134": errors.New("closing failed. please check your holdings and pending orders"),
"51135": errors.New("your closing price has triggered the limit price, and the max buy price is {0}"),
"51136": errors.New("your closing price has triggered the limit price, and the min sell price is {0}"),
"51137": errors.New("your opening price has triggered the limit price, and the max buy price is {0}"),
"51138": errors.New("your opening price has triggered the limit price, and the min sell price is {0}"),
"51139": errors.New("reduce-only feature is unavailable for the spot transactions by simple account"),
"51145": errors.New("when users transfer the margin by themselves in isolated mode, its not supported to place orders in advance"),
"51147": errors.New("the total value of assets in your trading account needs to be greater than 50,000 USD to trade options"),
"51148": errors.New("reduceOnly cannot increase the position quantity"),
"51149": errors.New("order timed out, please try again later"),
"51150": errors.New("the precision of the number of trades or the price exceeds the limit"),
"51201": errors.New("value of per market order cannot exceed 1,000,000 USDT"),
"51202": errors.New("market - order amount exceeds the max amount"),
"51203": errors.New("order amount exceeds the limit {0}"),
"51204": errors.New("the price for the limit order can not be empty"),
"51205": errors.New("reduce-only is not available"),
"51206": errors.New("please cancel the reduce only order before placing the current {0} order to avoid opening a reverse position"),
"51250": errors.New("algo order price is out of the available range"),
"51251": errors.New("algo order type error (when user place an iceberg order)"),
"51252": errors.New("algo order price is out of the available range"),
"51253": errors.New("average amount exceeds the limit of per iceberg order"),
"51254": errors.New("iceberg average amount error (when user place an iceberg order)"),
"51255": errors.New("limit of per iceberg order: total amount/1000 < x <= total amount"),
"51256": errors.New("iceberg order price variance error"),
"51257": errors.New("trail order callback rate error"),
"51258": errors.New("trail - order placement failed. the trigger price of a sell order should be higher than the last transaction price"),
"51259": errors.New("trail - order placement failed. the trigger price of a buy order should be lower than the last transaction price"),
"51260": errors.New("maximum {0} pending trail - orders can be held at the same time"),
"51261": errors.New("each user can hold up to {0} pending stop - orders at the same time"),
"51262": errors.New("maximum {0} pending iceberg orders can be held at the same time"),
"51263": errors.New("maximum {0} pending time-weighted orders can be held at the same time"),
"51264": errors.New("average amount exceeds the limit of per time-weighted order"),
"51265": errors.New("time-weighted order limit error"),
"51267": errors.New("time-weighted order strategy initiative rate error"),
"51268": errors.New("time-weighted order strategy initiative range error"),
"51269": errors.New("time-weighted order interval error, the interval should be {0}<= x<={1}"),
"51270": errors.New("the limit of time-weighted order price variance is 0 < x <= 1%"),
"51271": errors.New("sweep ratio should be 0 < x <= 100%"),
"51272": errors.New("price variance should be 0 < x <= 1%"),
"51273": errors.New("total amount should be more than {0}"),
"51274": errors.New("total quantity of time-weighted order must be larger than single order limit"),
"51275": errors.New("the amount of single stop-market order can not exceed the upper limit"),
"51276": errors.New("stop - market orders cannot specify a price"),
"51277": errors.New("TP trigger price can not be higher than the last price"),
"51278": errors.New("SL trigger price can not be lower than the last price"),
"51279": errors.New("TP trigger price can not be lower than the last price"),
"51280": errors.New("SL trigger price can not be higher than the last price"),
"51281": errors.New("trigger not support the tgtCcy parameter"),
"51282": errors.New("the range of price variance is {0}~{1}"),
"51283": errors.New("the range of time interval is {0}~{1}"),
"51284": errors.New("the range of average amount is {0}~{1}"),
"51285": errors.New("the range of total amount is {0}~{1}"),
"51286": errors.New("the total amount should not be less than {0}"),
"51287": errors.New("contract not supported"),
"51288": errors.New("we are stopping the bot. please do not click it multiple times"),
"51289": errors.New("bot configuration does not exist. please try again later"),
"51290": errors.New("the bot engine is being upgraded. please try again later"),
"51291": errors.New("this bot does not exist or has been stopped"),
"51292": errors.New("this bot type does not exist"),
"51293": errors.New("this bot does not exist"),
"51294": errors.New("this bot cannot be created temporarily. please try again later"),
"51295": errors.New("portfolio margin account does not support ordType {0} in trading bot mode"),
"51298": errors.New("trigger orders are not available in the net mode of futures and perpetual swaps"),
"51299": errors.New("order did not go through. you can hold maximum {0} orders of this type"),
"51300": errors.New("TP trigger price can not be higher than the mark price"),
"51302": errors.New("SL trigger price can not be lower than the mark price"),
"51303": errors.New("TP trigger price can not be lower than the mark price"),
"51304": errors.New("SL trigger price can not be higher than the mark price"),
"51305": errors.New("TP trigger price can not be higher than the index price"),
"51306": errors.New("SL trigger price can not be lower than the index price"),
"51307": errors.New("TP trigger price can not be lower than the index price"),
"51308": errors.New("SL trigger price can not be higher than the index price"),
"51309": errors.New("cannot create trading bot during call auction"),
"51310": errors.New("when users transfer the margin by themselves in isolated mode, strategic orders with ordType iceberg and twap will not be supported"),
"51311": errors.New("failed to place trailing stop order. callback rate should be within {0}<x<={1}"),
"51312": errors.New("failed to place trailing stop order. order amount should be within {0}<x<={1}"),
"51313": errors.New("manual transfer in isolated mode does not support bot trading"),
"51317": errors.New("trigger orders are not available by margin"),
"51340": errors.New("used margin must be greater than {0}{1}"),
"51341": errors.New("position closing not allowed"),
"51342": errors.New("closing order already exists.please try again later"),
"51343": errors.New("TP price must be less than the lower price"),
"51344": errors.New("SL price must be greater than the upper price"),
"51345": errors.New("policy type is not grid policy"),
"51346": errors.New("the highest price cannot be lower than the lowest price"),
"51347": errors.New("no profit available"),
"51348": errors.New("stop price should be less than the lowest price in the range"),
"51349": errors.New("stop profit price should be greater than the highest price in the range"),
"51350": errors.New("no recommended parameters"),
"51351": errors.New("single income must be greater than 0"),
"51370": errors.New("the range of lever is {0}~{1}"),
"51400": errors.New("cancellation failed as the order does not exist"),
"51401": errors.New("cancellation failed as the order is already canceled"),
"51402": errors.New("cancellation failed as the order is already completed"),
"51403": errors.New("cancellation failed as the order type does not support cancellation"),
"51404": errors.New("order cancellation unavailable during the second phase of call auction"),
"51405": errors.New("cancellation failed as you do not have any pending orders"),
"51406": errors.New("canceled - order count exceeds the limit {0}"),
"51407": errors.New("either order ID or client order ID is required"),
"51408": errors.New("pair ID or name does not match the order info"),
"51409": errors.New("either pair ID or pair name ID is required"),
"51410": errors.New("cancellation failed as the order is already under cancelling status"),
"51411": errors.New("account does not have permission for mass cancellation"),
"51412": errors.New("the order has been triggered and cannot be cancelled"),
"51413": errors.New("cancellation failed as the order type is not supported by endpoint"),
"51415": errors.New("unable to place order. spot trading only supports using the last price as trigger price. please select \"Last\" and try again"),
"51500": errors.New("either order price or amount is required"),
"51501": errors.New("maximum {0} orders can be modified"),
"51502": errors.New("order modification failed for insufficient margin"),
"51503": errors.New("order modification failed as the order does not exist"),
"51506": errors.New("order modification unavailable for the order type"),
"51508": errors.New("orders are not allowed to be modified during the call auction"),
"51509": errors.New("modification failed as the order has been canceled"),
"51510": errors.New("modification failed as the order has been completed"),
"51511": errors.New("operation failed as the order price did not meet the requirement for post only"),
"51512": errors.New("failed to amend bulk orders. you cannot add duplicate batch orders in your portfolio margin account"),
"51513": errors.New("number of modification requests that are currently in progress for an order cannot exceed 3"),
"51600": errors.New("status not found"),
"51601": errors.New("order status and order ID cannot exist at the same time"),
"51602": errors.New("either order status or order ID is required"),
"51603": errors.New("order does not exist"),
"51607": errors.New("the file is generating"),
"50100": errors.New("API frozen, please contact customer service"),
"50101": errors.New("APIKey does not match current environment"),
"50102": errors.New("timestamp request expired"),
"50103": errors.New("request header \"OK_ACCESS_KEY\" can not be empty"),
"50104": errors.New("request header \"OK_ACCESS_PASSPHRASE\" can not be empty"),
"50105": errors.New("request header \"OK_ACCESS_PASSPHRASE\" incorrect"),
"50106": errors.New("request header \"OK_ACCESS_SIGN\" can not be empty"),
"50107": errors.New("request header \"OK_ACCESS_TIMESTAMP\" can not be empty"),
"50108": errors.New("exchange ID does not exist"),
"50109": errors.New("exchange domain does not exist"),
"50110": errors.New("your IP {0} is not in linking trusted IP addresses.(You can add your IP in linking trusted IP addresses)"),
"50111": errors.New("invalid OK_ACCESS_KEY"),
"50112": errors.New("invalid OK_ACCESS_TIMESTAMP"),
"50113": errors.New("invalid signature"),
"50114": errors.New("invalid authorization"),
"50115": errors.New("invalid request method"),
"1": errors.New("operation failed"),
"2": errors.New("bulk operation partially succeeded"),
"50000": errors.New("body can not be empty"),
"50001": errors.New("service temporarily unavailable, please try again later"),
"50002": errors.New("json data format error"),
"50004": errors.New("endpoint request timeout (does not mean that the request was successful or failed, please check the request result)"),
"50005": errors.New("API is offline or unavailable"),
"50006": errors.New("invalid Content_Type, please use \"application/json\" format"),
"50007": errors.New("account blocked"),
"50008": errors.New("user does not exist"),
"50009": errors.New("account is suspended due to ongoing liquidation"),
"50010": errors.New("user ID can not be empty"),
"50011": errors.New("requests too frequent"),
"50012": errors.New("account status invalid"),
"50013": errors.New("system is busy, please try again later"),
"50014": errors.New("parameter {0} can not be empty"),
"50015": errors.New("either parameter {0} or {1} is required"),
"50016": errors.New("parameter {0} does not match parameter {1}"),
"50017": errors.New("the position is frozen due to ADL. operation restricted"),
"50018": errors.New("currency {0} is frozen due to ADL. operation restricted"),
"50019": errors.New("the account is frozen due to ADL. operation restricted"),
"50020": errors.New("the position is frozen due to liquidation. operation restricted"),
"50021": errors.New("currency {0} is frozen due to liquidation. operation restricted"),
"50022": errors.New("the account is frozen due to liquidation. operation restricted"),
"50023": errors.New("funding fee frozen. operation restricted"),
"50024": errors.New("parameter {0} and {1} can not exist at the same time"),
"50025": errors.New("parameter {0} count exceeds the limit {1}"),
"50026": errors.New("system error, please try again later"),
"50027": errors.New("the account is restricted from trading"),
"50028": errors.New("unable to take the order, please reach out to support center for details"),
"50029": errors.New(`this instrument ({0}) is unavailable at present due to risk management. please contact customer service for help`),
"50030": errors.New("no permission to use this API"),
"50031": errors.New("amount cannot exceed 100"),
"50032": errors.New("this asset is blocked, allow its trading and try again"),
"50033": errors.New("this instrument is blocked, allow its trading and try again"),
"50034": errors.New("you are not currently on the whitelist, please contact customer service"),
"50035": errors.New("this endpoint requires that APIKey must be bound to IP"),
"50036": errors.New("invalid expTime"),
"50037": errors.New("order expired"),
"50038": errors.New("this feature is temporarily unavailable in demo trading"),
"50039": errors.New("the before parameter is not available for implementing timestamp pagination"),
}
)

3176
exchanges/okx/okx_test.go Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,742 @@
package okx
import (
"encoding/json"
"regexp"
"strconv"
"strings"
"time"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
type okxNumericalValue float64
// UnmarshalJSON is custom type json unmarshaller for okxNumericalValue
func (a *okxNumericalValue) UnmarshalJSON(data []byte) error {
var num string
err := json.Unmarshal(data, &num)
if err != nil {
return err
}
if num == "" {
return nil
}
v, err := strconv.ParseFloat(num, 64)
if err != nil {
return err
}
*a = okxNumericalValue(v)
return nil
}
// Float64 returns a float64 value for okxNumericalValue
func (a *okxNumericalValue) Float64() float64 { return float64(*a) }
type okxUnixMilliTime int64
// UnmarshalJSON deserializes byte data to okxunixMilliTime instance.
func (a *okxUnixMilliTime) UnmarshalJSON(data []byte) error {
var num string
err := json.Unmarshal(data, &num)
if err != nil {
return err
}
if num == "" {
return nil
}
value, err := strconv.ParseInt(num, 10, 64)
if err != nil {
return err
}
*a = okxUnixMilliTime(value)
return nil
}
// Time returns the time instance from unix value of integer.
func (a *okxUnixMilliTime) Time() time.Time {
return time.UnixMilli(int64(*a))
}
// numbersOnlyRegexp for checking the value is numerics only
var numbersOnlyRegexp = regexp.MustCompile(`^\d*$`)
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *Instrument) UnmarshalJSON(data []byte) error {
type Alias Instrument
chil := &struct {
*Alias
ListTime string `json:"listTime"`
ExpTime string `json:"expTime"`
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
if numbersOnlyRegexp.MatchString(chil.ListTime) {
var val int
if val, err = strconv.Atoi(chil.ListTime); err == nil {
a.ListTime = time.UnixMilli(int64(val))
}
}
if numbersOnlyRegexp.MatchString(chil.ExpTime) {
var val int
if val, err = strconv.Atoi(chil.ExpTime); err == nil {
a.ExpTime = time.UnixMilli(int64(val))
}
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON decoder for OpenInterestResponse instance.
func (a *OpenInterest) UnmarshalJSON(data []byte) error {
type Alias OpenInterest
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{Alias: (*Alias)(a)}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *FundingRateResponse) UnmarshalJSON(data []byte) error {
type Alias FundingRateResponse
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
FundingRate string `json:"fundingRate"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *LimitPriceResponse) UnmarshalJSON(data []byte) error {
type Alias LimitPriceResponse
chil := &struct {
*Alias
Timestamp int64 `json:"ts,string"`
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes the account and position response.
func (a *TickerResponse) UnmarshalJSON(data []byte) error {
type Alias TickerResponse
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
var err error
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *OptionMarketDataResponse) UnmarshalJSON(data []byte) error {
type Alias OptionMarketDataResponse
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, asset item, and timestamp information.
func (a *DeliveryEstimatedPrice) UnmarshalJSON(data []byte) error {
type Alias DeliveryEstimatedPrice
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON custom Unmarshaler to convert the Instrument type string to an asset.Item instance.
func (a *LiquidationOrder) UnmarshalJSON(data []byte) error {
type Alias LiquidationOrder
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON unmarshals the timestamp for mark price data
func (a *MarkPrice) UnmarshalJSON(data []byte) error {
type Alias MarkPrice
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if chil.InstrumentType == "" {
a.InstrumentType = asset.Empty
} else if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *OrderDetail) UnmarshalJSON(data []byte) error {
type Alias OrderDetail
chil := &struct {
*Alias
Side string `json:"side"`
UpdateTime int64 `json:"uTime,string"`
CreationTime int64 `json:"cTime,string"`
InstrumentType string `json:"instType"`
FillTime string `json:"fillTime"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
var err error
a.UpdateTime = time.UnixMilli(chil.UpdateTime)
a.CreationTime = time.UnixMilli(chil.CreationTime)
a.Side, err = order.StringToOrderSide(chil.Side)
if chil.FillTime == "" {
a.FillTime = time.Time{}
} else {
var value int64
value, err = strconv.ParseInt(chil.FillTime, 10, 64)
if err != nil {
return err
}
a.FillTime = time.UnixMilli(value)
}
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *PendingOrderItem) UnmarshalJSON(data []byte) error {
type Alias PendingOrderItem
chil := &struct {
*Alias
Side string `json:"side"`
UpdateTime string `json:"uTime"`
CreationTime string `json:"cTime"`
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
uTime, err := strconv.ParseInt(chil.UpdateTime, 10, 64)
if err != nil {
return err
}
cTime, err := strconv.ParseInt(chil.CreationTime, 10, 64)
if err != nil {
return err
}
a.Side, err = order.StringToOrderSide(chil.Side)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
a.CreationTime = time.UnixMilli(cTime)
a.UpdateTime = time.UnixMilli(uTime)
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *TransactionDetail) UnmarshalJSON(data []byte) error {
type Alias TransactionDetail
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *AlgoOrderResponse) UnmarshalJSON(data []byte) error {
type Alias AlgoOrderResponse
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *PositionData) UnmarshalJSON(data []byte) error {
type Alias PositionData
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *AccountPosition) UnmarshalJSON(data []byte) error {
type Alias AccountPosition
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserialises the JSON info, asset item instance, and including the timestamp
func (a *AccountPositionHistory) UnmarshalJSON(data []byte) error {
type Alias AccountPositionHistory
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *BillsDetailResponse) UnmarshalJSON(data []byte) error {
type Alias BillsDetailResponse
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *TradeFeeRate) UnmarshalJSON(data []byte) error {
type Alias TradeFeeRate
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *PositionBuilderData) UnmarshalJSON(data []byte) error {
type Alias PositionBuilderData
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *RfqTradeResponse) UnmarshalJSON(data []byte) error {
type Alias RfqTradeResponse
chil := &struct {
*Alias
CreationTime int64 `json:"cTime,string"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
a.CreationTime = time.UnixMilli(chil.CreationTime)
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *BlockTicker) UnmarshalJSON(data []byte) error {
type Alias BlockTicker
chil := &struct {
*Alias
Timestamp int64 `json:"ts,string"`
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *BlockTrade) UnmarshalJSON(data []byte) error {
type Alias BlockTrade
chil := &struct {
*Alias
Side string `json:"side"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
switch {
case strings.EqualFold(chil.Side, "buy"):
a.Side = order.Buy
case strings.EqualFold(chil.Side, "sell"):
a.Side = order.Sell
default:
a.Side = order.UnknownSide
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *UnitConvertResponse) UnmarshalJSON(data []byte) error {
type Alias UnitConvertResponse
chil := &struct {
*Alias
ConvertType int `json:"type,string"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
switch chil.ConvertType {
case 1:
a.ConvertType = 1
case 2:
a.ConvertType = 2
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *GridAlgoSuborder) UnmarshalJSON(data []byte) error {
type Alias GridAlgoSuborder
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *GridAlgoOrderResponse) UnmarshalJSON(data []byte) error {
type Alias GridAlgoOrderResponse
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *AlgoOrderPosition) UnmarshalJSON(data []byte) error {
type Alias AlgoOrderPosition
chil := &struct {
*Alias
InstrumentType string `json:"instType"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
chil.InstrumentType = strings.ToUpper(chil.InstrumentType)
if a.InstrumentType, err = GetAssetTypeFromInstrumentType(chil.InstrumentType); err != nil {
return err
}
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *QuoteLeg) UnmarshalJSON(data []byte) error {
type Alias QuoteLeg
chil := &struct {
*Alias
Side string `json:"side"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
chil.Side = strings.ToLower(chil.Side)
if chil.Side == "buy" {
a.Side = order.Buy
} else {
a.Side = order.Sell
}
return nil
}
// MarshalJSON serialized QuoteLeg instance into bytes
func (a *QuoteLeg) MarshalJSON() ([]byte, error) {
type Alias QuoteLeg
chil := &struct {
*Alias
Side string `json:"side"`
}{
Alias: (*Alias)(a),
}
if a.Side == order.Buy {
chil.Side = "buy"
} else {
chil.Side = "sell"
}
return json.Marshal(chil)
}
// MarshalJSON serialized CreateQuoteParams instance into bytes
func (a *CreateQuoteParams) MarshalJSON() ([]byte, error) {
type Alias CreateQuoteParams
chil := &struct {
*Alias
QuoteSide string `json:"quoteSide"`
}{
Alias: (*Alias)(a),
}
if a.QuoteSide == order.Buy {
chil.QuoteSide = "buy"
} else {
chil.QuoteSide = "sell"
}
return json.Marshal(chil)
}
// MarshalJSON serializes the WebsocketLoginData object
func (a *WebsocketLoginData) MarshalJSON() ([]byte, error) {
type Alias WebsocketLoginData
return json.Marshal(struct {
Timestamp int64 `json:"timestamp"`
*Alias
}{
Timestamp: a.Timestamp.UTC().Unix(),
Alias: (*Alias)(a),
})
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *WebsocketLoginData) UnmarshalJSON(data []byte) error {
type Alias WebsocketLoginData
chil := &struct {
*Alias
Timestamp int64 `json:"timestamp"`
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, chil); err != nil {
return err
}
a.Timestamp = time.UnixMilli(chil.Timestamp)
return nil
}
// UnmarshalJSON deserializes JSON, and timestamp information.
func (a *CurrencyOneClickRepay) UnmarshalJSON(data []byte) error {
type Alias CurrencyOneClickRepay
chil := &struct {
*Alias
UpdateTime int64 `json:"uTime,string"`
FillToSize string `json:"fillToSz"`
FillFromSize string `json:"fillFromSz"`
}{
Alias: (*Alias)(a),
}
err := json.Unmarshal(data, chil)
if err != nil {
return err
}
a.UpdateTime = time.Unix(chil.UpdateTime, 0)
return nil
}

3169
exchanges/okx/okx_types.go Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1471
exchanges/okx/okx_wrapper.go Normal file

File diff suppressed because it is too large Load Diff

1034
exchanges/okx/ratelimit.go Normal file

File diff suppressed because it is too large Load Diff