3016 lines
130 KiB
Go
3016 lines
130 KiB
Go
package ccxt
|
|
|
|
// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
|
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
|
|
|
type tokocrypto struct {
|
|
Exchange
|
|
|
|
}
|
|
|
|
func NewTokocryptoCore() tokocrypto {
|
|
p := tokocrypto{}
|
|
setDefaults(&p)
|
|
return p
|
|
}
|
|
|
|
func (this *tokocrypto) Describe() interface{} {
|
|
return this.DeepExtend(this.Exchange.Describe(), map[string]interface{} {
|
|
"id": "tokocrypto",
|
|
"name": "Tokocrypto",
|
|
"countries": []interface{}{"ID"},
|
|
"certified": false,
|
|
"pro": false,
|
|
"version": "v1",
|
|
"has": map[string]interface{} {
|
|
"CORS": nil,
|
|
"spot": true,
|
|
"margin": true,
|
|
"swap": false,
|
|
"future": false,
|
|
"option": false,
|
|
"addMargin": nil,
|
|
"borrowMargin": nil,
|
|
"cancelAllOrders": false,
|
|
"cancelOrder": true,
|
|
"cancelOrders": nil,
|
|
"createDepositAddress": false,
|
|
"createMarketBuyOrderWithCost": true,
|
|
"createMarketOrderWithCost": false,
|
|
"createMarketSellOrderWithCost": false,
|
|
"createOrder": true,
|
|
"createReduceOnlyOrder": nil,
|
|
"createStopLimitOrder": true,
|
|
"createStopMarketOrder": true,
|
|
"createStopOrder": true,
|
|
"fetchAccounts": false,
|
|
"fetchBalance": true,
|
|
"fetchBidsAsks": true,
|
|
"fetchBorrowInterest": nil,
|
|
"fetchBorrowRateHistories": nil,
|
|
"fetchBorrowRateHistory": nil,
|
|
"fetchCanceledOrders": false,
|
|
"fetchClosedOrder": false,
|
|
"fetchClosedOrders": "emulated",
|
|
"fetchCrossBorrowRate": false,
|
|
"fetchCrossBorrowRates": false,
|
|
"fetchCurrencies": false,
|
|
"fetchDeposit": false,
|
|
"fetchDepositAddress": true,
|
|
"fetchDepositAddresses": false,
|
|
"fetchDepositAddressesByNetwork": false,
|
|
"fetchDeposits": true,
|
|
"fetchDepositsWithdrawals": false,
|
|
"fetchFundingHistory": false,
|
|
"fetchFundingRate": false,
|
|
"fetchFundingRateHistory": false,
|
|
"fetchFundingRates": false,
|
|
"fetchIndexOHLCV": false,
|
|
"fetchIsolatedBorrowRate": false,
|
|
"fetchIsolatedBorrowRates": false,
|
|
"fetchL3OrderBook": false,
|
|
"fetchLedger": nil,
|
|
"fetchLeverage": false,
|
|
"fetchLeverageTiers": false,
|
|
"fetchMarketLeverageTiers": "emulated",
|
|
"fetchMarkets": true,
|
|
"fetchMarkOHLCV": false,
|
|
"fetchMyTrades": true,
|
|
"fetchOHLCV": true,
|
|
"fetchOpenInterestHistory": false,
|
|
"fetchOpenOrder": false,
|
|
"fetchOpenOrders": true,
|
|
"fetchOrder": true,
|
|
"fetchOrderBook": true,
|
|
"fetchOrderBooks": false,
|
|
"fetchOrders": true,
|
|
"fetchOrderTrades": false,
|
|
"fetchPosition": false,
|
|
"fetchPositions": false,
|
|
"fetchPositionsRisk": false,
|
|
"fetchPremiumIndexOHLCV": false,
|
|
"fetchStatus": false,
|
|
"fetchTicker": false,
|
|
"fetchTickers": false,
|
|
"fetchTime": true,
|
|
"fetchTrades": true,
|
|
"fetchTradingFee": false,
|
|
"fetchTradingFees": false,
|
|
"fetchTradingLimits": false,
|
|
"fetchTransactionFee": false,
|
|
"fetchTransactionFees": false,
|
|
"fetchTransactions": false,
|
|
"fetchTransfers": false,
|
|
"fetchWithdrawal": false,
|
|
"fetchWithdrawals": true,
|
|
"fetchWithdrawalWhitelist": false,
|
|
"reduceMargin": false,
|
|
"repayCrossMargin": false,
|
|
"repayIsolatedMargin": false,
|
|
"setLeverage": false,
|
|
"setMargin": false,
|
|
"setMarginMode": false,
|
|
"setPositionMode": false,
|
|
"signIn": false,
|
|
"transfer": false,
|
|
"withdraw": true,
|
|
},
|
|
"timeframes": map[string]interface{} {
|
|
"1m": "1m",
|
|
"3m": "3m",
|
|
"5m": "5m",
|
|
"15m": "15m",
|
|
"30m": "30m",
|
|
"1h": "1h",
|
|
"2h": "2h",
|
|
"4h": "4h",
|
|
"6h": "6h",
|
|
"8h": "8h",
|
|
"12h": "12h",
|
|
"1d": "1d",
|
|
"3d": "3d",
|
|
"1w": "1w",
|
|
"1M": "1M",
|
|
},
|
|
"urls": map[string]interface{} {
|
|
"logo": "https://user-images.githubusercontent.com/1294454/183870484-d3398d0c-f6a1-4cce-91b8-d58792308716.jpg",
|
|
"api": map[string]interface{} {
|
|
"rest": map[string]interface{} {
|
|
"public": "https://www.tokocrypto.com",
|
|
"binance": "https://api.binance.com/api/v3",
|
|
"private": "https://www.tokocrypto.com",
|
|
},
|
|
},
|
|
"www": "https://tokocrypto.com",
|
|
"doc": "https://www.tokocrypto.com/apidocs/",
|
|
"fees": "https://www.tokocrypto.com/fees/newschedule",
|
|
},
|
|
"api": map[string]interface{} {
|
|
"binance": map[string]interface{} {
|
|
"get": map[string]interface{} {
|
|
"ping": 1,
|
|
"time": 1,
|
|
"depth": map[string]interface{} {
|
|
"cost": 1,
|
|
"byLimit": []interface{}{[]interface{}{100, 1}, []interface{}{500, 5}, []interface{}{1000, 10}, []interface{}{5000, 50}},
|
|
},
|
|
"trades": 1,
|
|
"aggTrades": 1,
|
|
"historicalTrades": 5,
|
|
"klines": 1,
|
|
"ticker/24hr": map[string]interface{} {
|
|
"cost": 1,
|
|
"noSymbol": 40,
|
|
},
|
|
"ticker/price": map[string]interface{} {
|
|
"cost": 1,
|
|
"noSymbol": 2,
|
|
},
|
|
"ticker/bookTicker": map[string]interface{} {
|
|
"cost": 1,
|
|
"noSymbol": 2,
|
|
},
|
|
"exchangeInfo": 10,
|
|
},
|
|
"put": map[string]interface{} {
|
|
"userDataStream": 1,
|
|
},
|
|
"post": map[string]interface{} {
|
|
"userDataStream": 1,
|
|
},
|
|
"delete": map[string]interface{} {
|
|
"userDataStream": 1,
|
|
},
|
|
},
|
|
"public": map[string]interface{} {
|
|
"get": map[string]interface{} {
|
|
"open/v1/common/time": 1,
|
|
"open/v1/common/symbols": 1,
|
|
"open/v1/market/depth": 1,
|
|
"open/v1/market/trades": 1,
|
|
"open/v1/market/agg-trades": 1,
|
|
"open/v1/market/klines": 1,
|
|
},
|
|
},
|
|
"private": map[string]interface{} {
|
|
"get": map[string]interface{} {
|
|
"open/v1/orders/detail": 1,
|
|
"open/v1/orders": 1,
|
|
"open/v1/account/spot": 1,
|
|
"open/v1/account/spot/asset": 1,
|
|
"open/v1/orders/trades": 1,
|
|
"open/v1/withdraws": 1,
|
|
"open/v1/deposits": 1,
|
|
"open/v1/deposits/address": 1,
|
|
},
|
|
"post": map[string]interface{} {
|
|
"open/v1/orders": 1,
|
|
"open/v1/orders/cancel": 1,
|
|
"open/v1/orders/oco": 1,
|
|
"open/v1/withdraws": 1,
|
|
"open/v1/user-data-stream": 1,
|
|
},
|
|
},
|
|
},
|
|
"fees": map[string]interface{} {
|
|
"trading": map[string]interface{} {
|
|
"tierBased": true,
|
|
"percentage": true,
|
|
"taker": this.ParseNumber("0.0075"),
|
|
"maker": this.ParseNumber("0.0075"),
|
|
},
|
|
},
|
|
"precisionMode": TICK_SIZE,
|
|
"options": map[string]interface{} {
|
|
"createMarketBuyOrderRequiresPrice": true,
|
|
"defaultTimeInForce": "GTC",
|
|
"hasAlreadyAuthenticatedSuccessfully": false,
|
|
"warnOnFetchOpenOrdersWithoutSymbol": true,
|
|
"recvWindow": Multiply(5, 1000),
|
|
"timeDifference": 0,
|
|
"adjustForTimeDifference": false,
|
|
"newOrderRespType": map[string]interface{} {
|
|
"market": "FULL",
|
|
"limit": "FULL",
|
|
},
|
|
"quoteOrderQty": false,
|
|
"networks": map[string]interface{} {
|
|
"ERC20": "ETH",
|
|
"TRC20": "TRX",
|
|
"BEP2": "BNB",
|
|
"BEP20": "BSC",
|
|
"OMNI": "OMNI",
|
|
"EOS": "EOS",
|
|
"SPL": "SOL",
|
|
},
|
|
"reverseNetworks": map[string]interface{} {
|
|
"tronscan.org": "TRC20",
|
|
"etherscan.io": "ERC20",
|
|
"bscscan.com": "BSC",
|
|
"explorer.binance.org": "BEP2",
|
|
"bithomp.com": "XRP",
|
|
"bloks.io": "EOS",
|
|
"stellar.expert": "XLM",
|
|
"blockchair.com/bitcoin": "BTC",
|
|
"blockchair.com/bitcoin-cash": "BCH",
|
|
"blockchair.com/ecash": "XEC",
|
|
"explorer.litecoin.net": "LTC",
|
|
"explorer.avax.network": "AVAX",
|
|
"solscan.io": "SOL",
|
|
"polkadot.subscan.io": "DOT",
|
|
"dashboard.internetcomputer.org": "ICP",
|
|
"explorer.chiliz.com": "CHZ",
|
|
"cardanoscan.io": "ADA",
|
|
"mainnet.theoan.com": "AION",
|
|
"algoexplorer.io": "ALGO",
|
|
"explorer.ambrosus.com": "AMB",
|
|
"viewblock.io/zilliqa": "ZIL",
|
|
"viewblock.io/arweave": "AR",
|
|
"explorer.ark.io": "ARK",
|
|
"atomscan.com": "ATOM",
|
|
"www.mintscan.io": "CTK",
|
|
"explorer.bitcoindiamond.org": "BCD",
|
|
"btgexplorer.com": "BTG",
|
|
"bts.ai": "BTS",
|
|
"explorer.celo.org": "CELO",
|
|
"explorer.nervos.org": "CKB",
|
|
"cerebro.cortexlabs.ai": "CTXC",
|
|
"chainz.cryptoid.info": "VIA",
|
|
"explorer.dcrdata.org": "DCR",
|
|
"digiexplorer.info": "DGB",
|
|
"dock.subscan.io": "DOCK",
|
|
"dogechain.info": "DOGE",
|
|
"explorer.elrond.com": "EGLD",
|
|
"blockscout.com": "ETC",
|
|
"explore-fetchhub.fetch.ai": "FET",
|
|
"filfox.info": "FIL",
|
|
"fio.bloks.io": "FIO",
|
|
"explorer.firo.org": "FIRO",
|
|
"neoscan.io": "NEO",
|
|
"ftmscan.com": "FTM",
|
|
"explorer.gochain.io": "GO",
|
|
"block.gxb.io": "GXS",
|
|
"hash-hash.info": "HBAR",
|
|
"www.hiveblockexplorer.com": "HIVE",
|
|
"explorer.helium.com": "HNT",
|
|
"tracker.icon.foundation": "ICX",
|
|
"www.iostabc.com": "IOST",
|
|
"explorer.iota.org": "IOTA",
|
|
"iotexscan.io": "IOTX",
|
|
"irishub.iobscan.io": "IRIS",
|
|
"kava.mintscan.io": "KAVA",
|
|
"scope.klaytn.com": "KLAY",
|
|
"kmdexplorer.io": "KMD",
|
|
"kusama.subscan.io": "KSM",
|
|
"explorer.lto.network": "LTO",
|
|
"polygonscan.com": "POLYGON",
|
|
"explorer.ont.io": "ONT",
|
|
"minaexplorer.com": "MINA",
|
|
"nanolooker.com": "NANO",
|
|
"explorer.nebulas.io": "NAS",
|
|
"explorer.nbs.plus": "NBS",
|
|
"explorer.nebl.io": "NEBL",
|
|
"nulscan.io": "NULS",
|
|
"nxscan.com": "NXS",
|
|
"explorer.harmony.one": "ONE",
|
|
"explorer.poa.network": "POA",
|
|
"qtum.info": "QTUM",
|
|
"explorer.rsk.co": "RSK",
|
|
"www.oasisscan.com": "ROSE",
|
|
"ravencoin.network": "RVN",
|
|
"sc.tokenview.com": "SC",
|
|
"secretnodes.com": "SCRT",
|
|
"explorer.skycoin.com": "SKY",
|
|
"steemscan.com": "STEEM",
|
|
"explorer.stacks.co": "STX",
|
|
"www.thetascan.io": "THETA",
|
|
"scan.tomochain.com": "TOMO",
|
|
"explore.vechain.org": "VET",
|
|
"explorer.vite.net": "VITE",
|
|
"www.wanscan.org": "WAN",
|
|
"wavesexplorer.com": "WAVES",
|
|
"wax.eosx.io": "WAXP",
|
|
"waltonchain.pro": "WTC",
|
|
"chain.nem.ninja": "XEM",
|
|
"verge-blockchain.info": "XVG",
|
|
"explorer.yoyow.org": "YOYOW",
|
|
"explorer.zcha.in": "ZEC",
|
|
"explorer.zensystem.io": "ZEN",
|
|
},
|
|
"impliedNetworks": map[string]interface{} {
|
|
"ETH": map[string]interface{} {
|
|
"ERC20": "ETH",
|
|
},
|
|
"TRX": map[string]interface{} {
|
|
"TRC20": "TRX",
|
|
},
|
|
},
|
|
"legalMoney": map[string]interface{} {
|
|
"MXN": true,
|
|
"UGX": true,
|
|
"SEK": true,
|
|
"CHF": true,
|
|
"VND": true,
|
|
"AED": true,
|
|
"DKK": true,
|
|
"KZT": true,
|
|
"HUF": true,
|
|
"PEN": true,
|
|
"PHP": true,
|
|
"USD": true,
|
|
"TRY": true,
|
|
"EUR": true,
|
|
"NGN": true,
|
|
"PLN": true,
|
|
"BRL": true,
|
|
"ZAR": true,
|
|
"KES": true,
|
|
"ARS": true,
|
|
"RUB": true,
|
|
"AUD": true,
|
|
"NOK": true,
|
|
"CZK": true,
|
|
"GBP": true,
|
|
"UAH": true,
|
|
"GHS": true,
|
|
"HKD": true,
|
|
"CAD": true,
|
|
"INR": true,
|
|
"JPY": true,
|
|
"NZD": true,
|
|
},
|
|
},
|
|
"exceptions": map[string]interface{} {
|
|
"exact": map[string]interface{} {
|
|
"System is under maintenance.": OnMaintenance,
|
|
"System abnormality": ExchangeError,
|
|
"You are not authorized to execute this request.": PermissionDenied,
|
|
"API key does not exist": AuthenticationError,
|
|
"Order would trigger immediately.": OrderImmediatelyFillable,
|
|
"Stop price would trigger immediately.": OrderImmediatelyFillable,
|
|
"Order would immediately match and take.": OrderImmediatelyFillable,
|
|
"Account has insufficient balance for requested action.": InsufficientFunds,
|
|
"Rest API trading is not enabled.": ExchangeNotAvailable,
|
|
"You don\\'t have permission.": PermissionDenied,
|
|
"Market is closed.": ExchangeNotAvailable,
|
|
"Too many requests. Please try again later.": DDoSProtection,
|
|
"This action disabled is on this account.": AccountSuspended,
|
|
"-1000": ExchangeNotAvailable,
|
|
"-1001": ExchangeNotAvailable,
|
|
"-1002": AuthenticationError,
|
|
"-1003": RateLimitExceeded,
|
|
"-1004": DDoSProtection,
|
|
"-1005": PermissionDenied,
|
|
"-1006": BadResponse,
|
|
"-1007": RequestTimeout,
|
|
"-1010": BadResponse,
|
|
"-1011": PermissionDenied,
|
|
"-1013": InvalidOrder,
|
|
"-1014": InvalidOrder,
|
|
"-1015": RateLimitExceeded,
|
|
"-1016": ExchangeNotAvailable,
|
|
"-1020": BadRequest,
|
|
"-1021": InvalidNonce,
|
|
"-1022": AuthenticationError,
|
|
"-1023": BadRequest,
|
|
"-1099": AuthenticationError,
|
|
"-1100": BadRequest,
|
|
"-1101": BadRequest,
|
|
"-1102": BadRequest,
|
|
"-1103": BadRequest,
|
|
"-1104": BadRequest,
|
|
"-1105": BadRequest,
|
|
"-1106": BadRequest,
|
|
"-1108": BadRequest,
|
|
"-1109": AuthenticationError,
|
|
"-1110": BadRequest,
|
|
"-1111": BadRequest,
|
|
"-1112": InvalidOrder,
|
|
"-1113": BadRequest,
|
|
"-1114": BadRequest,
|
|
"-1115": BadRequest,
|
|
"-1116": BadRequest,
|
|
"-1117": BadRequest,
|
|
"-1118": BadRequest,
|
|
"-1119": BadRequest,
|
|
"-1120": BadRequest,
|
|
"-1121": BadSymbol,
|
|
"-1125": AuthenticationError,
|
|
"-1127": BadRequest,
|
|
"-1128": BadRequest,
|
|
"-1130": BadRequest,
|
|
"-1131": BadRequest,
|
|
"-1136": BadRequest,
|
|
"-2008": AuthenticationError,
|
|
"-2010": ExchangeError,
|
|
"-2011": OrderNotFound,
|
|
"-2013": OrderNotFound,
|
|
"-2014": AuthenticationError,
|
|
"-2015": AuthenticationError,
|
|
"-2016": BadRequest,
|
|
"-2018": InsufficientFunds,
|
|
"-2019": InsufficientFunds,
|
|
"-2020": OrderNotFillable,
|
|
"-2021": OrderImmediatelyFillable,
|
|
"-2022": InvalidOrder,
|
|
"-2023": InsufficientFunds,
|
|
"-2024": InsufficientFunds,
|
|
"-2025": InvalidOrder,
|
|
"-2026": InvalidOrder,
|
|
"-2027": InvalidOrder,
|
|
"-2028": InsufficientFunds,
|
|
"-3000": ExchangeError,
|
|
"-3001": AuthenticationError,
|
|
"-3002": BadSymbol,
|
|
"-3003": BadRequest,
|
|
"-3004": ExchangeError,
|
|
"-3005": InsufficientFunds,
|
|
"-3006": InsufficientFunds,
|
|
"-3007": ExchangeError,
|
|
"-3008": InsufficientFunds,
|
|
"-3009": BadRequest,
|
|
"-3010": ExchangeError,
|
|
"-3011": BadRequest,
|
|
"-3012": ExchangeError,
|
|
"-3013": BadRequest,
|
|
"-3014": AccountSuspended,
|
|
"-3015": ExchangeError,
|
|
"-3016": BadRequest,
|
|
"-3017": ExchangeError,
|
|
"-3018": AccountSuspended,
|
|
"-3019": AccountSuspended,
|
|
"-3020": InsufficientFunds,
|
|
"-3021": BadRequest,
|
|
"-3022": AccountSuspended,
|
|
"-3023": BadRequest,
|
|
"-3024": ExchangeError,
|
|
"-3025": BadRequest,
|
|
"-3026": BadRequest,
|
|
"-3027": BadSymbol,
|
|
"-3028": BadSymbol,
|
|
"-3029": ExchangeError,
|
|
"-3036": AccountSuspended,
|
|
"-3037": ExchangeError,
|
|
"-3038": BadRequest,
|
|
"-3041": InsufficientFunds,
|
|
"-3042": BadRequest,
|
|
"-3043": BadRequest,
|
|
"-3044": DDoSProtection,
|
|
"-3045": ExchangeError,
|
|
"-3999": ExchangeError,
|
|
"-4001": BadRequest,
|
|
"-4002": BadRequest,
|
|
"-4003": BadRequest,
|
|
"-4004": AuthenticationError,
|
|
"-4005": RateLimitExceeded,
|
|
"-4006": BadRequest,
|
|
"-4007": BadRequest,
|
|
"-4008": BadRequest,
|
|
"-4010": BadRequest,
|
|
"-4011": BadRequest,
|
|
"-4012": BadRequest,
|
|
"-4013": AuthenticationError,
|
|
"-4014": PermissionDenied,
|
|
"-4015": ExchangeError,
|
|
"-4016": PermissionDenied,
|
|
"-4017": PermissionDenied,
|
|
"-4018": BadSymbol,
|
|
"-4019": BadSymbol,
|
|
"-4021": BadRequest,
|
|
"-4022": BadRequest,
|
|
"-4023": ExchangeError,
|
|
"-4024": InsufficientFunds,
|
|
"-4025": InsufficientFunds,
|
|
"-4026": InsufficientFunds,
|
|
"-4027": ExchangeError,
|
|
"-4028": BadRequest,
|
|
"-4029": BadRequest,
|
|
"-4030": ExchangeError,
|
|
"-4031": ExchangeError,
|
|
"-4032": ExchangeError,
|
|
"-4033": BadRequest,
|
|
"-4034": ExchangeError,
|
|
"-4035": PermissionDenied,
|
|
"-4036": BadRequest,
|
|
"-4037": ExchangeError,
|
|
"-4038": ExchangeError,
|
|
"-4039": BadRequest,
|
|
"-4040": BadRequest,
|
|
"-4041": ExchangeError,
|
|
"-4042": ExchangeError,
|
|
"-4043": BadRequest,
|
|
"-4044": BadRequest,
|
|
"-4045": ExchangeError,
|
|
"-4046": AuthenticationError,
|
|
"-4047": BadRequest,
|
|
"-5001": BadRequest,
|
|
"-5002": InsufficientFunds,
|
|
"-5003": InsufficientFunds,
|
|
"-5004": BadRequest,
|
|
"-5005": InsufficientFunds,
|
|
"-5006": BadRequest,
|
|
"-5007": BadRequest,
|
|
"-5008": InsufficientFunds,
|
|
"-5009": BadRequest,
|
|
"-5010": ExchangeError,
|
|
"-5011": BadRequest,
|
|
"-5012": ExchangeError,
|
|
"-5013": InsufficientFunds,
|
|
"-5021": BadRequest,
|
|
"-6001": BadRequest,
|
|
"-6003": BadRequest,
|
|
"-6004": ExchangeError,
|
|
"-6005": InvalidOrder,
|
|
"-6006": BadRequest,
|
|
"-6007": BadRequest,
|
|
"-6008": BadRequest,
|
|
"-6009": RateLimitExceeded,
|
|
"-6011": BadRequest,
|
|
"-6012": InsufficientFunds,
|
|
"-6013": ExchangeError,
|
|
"-6014": BadRequest,
|
|
"-6015": BadRequest,
|
|
"-6016": BadRequest,
|
|
"-6017": BadRequest,
|
|
"-6018": BadRequest,
|
|
"-6019": AuthenticationError,
|
|
"-6020": BadRequest,
|
|
"-7001": BadRequest,
|
|
"-7002": BadRequest,
|
|
"-9000": InsufficientFunds,
|
|
"-10017": BadRequest,
|
|
"-11008": InsufficientFunds,
|
|
"-12014": RateLimitExceeded,
|
|
"-13000": BadRequest,
|
|
"-13001": BadRequest,
|
|
"-13002": BadRequest,
|
|
"-13003": BadRequest,
|
|
"-13004": BadRequest,
|
|
"-13005": BadRequest,
|
|
"-13006": InvalidOrder,
|
|
"-13007": AuthenticationError,
|
|
"-21001": BadRequest,
|
|
"-21002": BadRequest,
|
|
"-21003": BadRequest,
|
|
"100001003": BadRequest,
|
|
"2202": InsufficientFunds,
|
|
"3210": InvalidOrder,
|
|
"3203": InvalidOrder,
|
|
"3211": InvalidOrder,
|
|
"3207": InvalidOrder,
|
|
"3218": OrderNotFound,
|
|
},
|
|
"broad": map[string]interface{} {
|
|
"has no operation privilege": PermissionDenied,
|
|
"MAX_POSITION": InvalidOrder,
|
|
},
|
|
},
|
|
"features": map[string]interface{} {
|
|
"spot": map[string]interface{} {
|
|
"sandbox": false,
|
|
"createOrder": map[string]interface{} {
|
|
"marginMode": false,
|
|
"triggerPrice": true,
|
|
"triggerDirection": false,
|
|
"triggerPriceType": nil,
|
|
"stopLossPrice": false,
|
|
"takeProfitPrice": false,
|
|
"attachedStopLossTakeProfit": nil,
|
|
"timeInForce": map[string]interface{} {
|
|
"IOC": true,
|
|
"FOK": true,
|
|
"PO": true,
|
|
"GTD": false,
|
|
},
|
|
"hedged": false,
|
|
"trailing": false,
|
|
"leverage": false,
|
|
"marketBuyByCost": true,
|
|
"marketBuyRequiresPrice": true,
|
|
"selfTradePrevention": true,
|
|
"iceberg": true,
|
|
},
|
|
"createOrders": nil,
|
|
"fetchMyTrades": map[string]interface{} {
|
|
"marginMode": false,
|
|
"limit": 1000,
|
|
"daysBack": 100000,
|
|
"untilDays": 100000,
|
|
"symbolRequired": true,
|
|
},
|
|
"fetchOrder": map[string]interface{} {
|
|
"marginMode": false,
|
|
"trigger": false,
|
|
"trailing": false,
|
|
"symbolRequired": false,
|
|
},
|
|
"fetchOpenOrders": map[string]interface{} {
|
|
"marginMode": false,
|
|
"limit": 1000,
|
|
"trigger": false,
|
|
"trailing": false,
|
|
"symbolRequired": true,
|
|
},
|
|
"fetchOrders": map[string]interface{} {
|
|
"marginMode": false,
|
|
"limit": 1000,
|
|
"daysBack": 100000,
|
|
"untilDays": 100000,
|
|
"trigger": false,
|
|
"trailing": false,
|
|
"symbolRequired": true,
|
|
},
|
|
"fetchClosedOrders": map[string]interface{} {
|
|
"marginMode": false,
|
|
"limit": 1000,
|
|
"daysBack": 100000,
|
|
"daysBackCanceled": 1,
|
|
"untilDays": 100000,
|
|
"trigger": false,
|
|
"trailing": false,
|
|
"symbolRequired": true,
|
|
},
|
|
"fetchOHLCV": map[string]interface{} {
|
|
"limit": 1000,
|
|
},
|
|
},
|
|
"swap": map[string]interface{} {
|
|
"linear": nil,
|
|
"inverse": nil,
|
|
},
|
|
"future": map[string]interface{} {
|
|
"linear": nil,
|
|
"inverse": nil,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
func (this *tokocrypto) Nonce() interface{} {
|
|
return Subtract(this.Milliseconds(), GetValue(this.Options, "timeDifference"))
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchTime
|
|
* @see https://www.tokocrypto.com/apidocs/#check-server-time
|
|
* @description fetches the current integer timestamp in milliseconds from the exchange server
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {int} the current integer timestamp in milliseconds from the exchange server
|
|
*/
|
|
func (this *tokocrypto) FetchTime(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
params := GetArg(optionalArgs, 0, map[string]interface{} {})
|
|
_ = params
|
|
|
|
response:= (<-this.PublicGetOpenV1CommonTime(params))
|
|
PanicOnError(response)
|
|
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "Success",
|
|
// "data": null,
|
|
// "timestamp": 1737378074159
|
|
// }
|
|
//
|
|
ch <- this.SafeInteger(response, "timestamp")
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchMarkets
|
|
* @see https://www.tokocrypto.com/apidocs/#get-all-supported-trading-symbol
|
|
* @description retrieves data on all markets for tokocrypto
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object[]} an array of objects representing market data
|
|
*/
|
|
func (this *tokocrypto) FetchMarkets(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
params := GetArg(optionalArgs, 0, map[string]interface{} {})
|
|
_ = params
|
|
|
|
response:= (<-this.PublicGetOpenV1CommonSymbols(params))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code":0,
|
|
// "msg":"Success",
|
|
// "data":{
|
|
// "list":[
|
|
// {
|
|
// "type":1,
|
|
// "symbol":"1INCH_BTC",
|
|
// "baseAsset":"1INCH",
|
|
// "basePrecision":8,
|
|
// "quoteAsset":"BTC",
|
|
// "quotePrecision":8,
|
|
// "filters":[
|
|
// {"filterType":"PRICE_FILTER","minPrice":"0.00000001","maxPrice":"1000.00000000","tickSize":"0.00000001","applyToMarket":false},
|
|
// {"filterType":"PERCENT_PRICE","multiplierUp":5,"multiplierDown":0.2,"avgPriceMins":"5","applyToMarket":false},
|
|
// {"filterType":"LOT_SIZE","minQty":"0.10000000","maxQty":"90000000.00000000","stepSize":"0.10000000","applyToMarket":false},
|
|
// {"filterType":"MIN_NOTIONAL","avgPriceMins":"5","minNotional":"0.00010000","applyToMarket":true},
|
|
// {"filterType":"ICEBERG_PARTS","applyToMarket":false,"limit":"10"},
|
|
// {"filterType":"MARKET_LOT_SIZE","minQty":"0.00000000","maxQty":"79460.14117231","stepSize":"0.00000000","applyToMarket":false},
|
|
// {"filterType":"TRAILING_DELTA","applyToMarket":false},
|
|
// {"filterType":"MAX_NUM_ORDERS","applyToMarket":false},
|
|
// {"filterType":"MAX_NUM_ALGO_ORDERS","applyToMarket":false,"maxNumAlgoOrders":"5"}
|
|
// ],
|
|
// "orderTypes":["LIMIT","LIMIT_MAKER","MARKET","STOP_LOSS_LIMIT","TAKE_PROFIT_LIMIT"],
|
|
// "icebergEnable":1,
|
|
// "ocoEnable":1,
|
|
// "spotTradingEnable":1,
|
|
// "marginTradingEnable":1,
|
|
// "permissions":["SPOT","MARGIN"]
|
|
// },
|
|
// ]
|
|
// },
|
|
// "timestamp":1659492212507
|
|
// }
|
|
//
|
|
if IsTrue(GetValue(this.Options, "adjustForTimeDifference")) {
|
|
|
|
retRes75112 := (<-this.LoadTimeDifference())
|
|
PanicOnError(retRes75112)
|
|
}
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var list interface{} = this.SafeValue(data, "list", []interface{}{})
|
|
var result interface{} = []interface{}{}
|
|
for i := 0; IsLessThan(i, GetArrayLength(list)); i++ {
|
|
var market interface{} = GetValue(list, i)
|
|
var baseId interface{} = this.SafeString(market, "baseAsset")
|
|
var quoteId interface{} = this.SafeString(market, "quoteAsset")
|
|
var id interface{} = this.SafeString(market, "symbol")
|
|
var lowercaseId interface{} = this.SafeStringLower(market, "symbol")
|
|
var settleId interface{} = this.SafeString(market, "marginAsset")
|
|
var base interface{} = this.SafeCurrencyCode(baseId)
|
|
var quote interface{} = this.SafeCurrencyCode(quoteId)
|
|
var settle interface{} = this.SafeCurrencyCode(settleId)
|
|
var symbol interface{} = Add(Add(base, "/"), quote)
|
|
var filters interface{} = this.SafeValue(market, "filters", []interface{}{})
|
|
var filtersByType interface{} = this.IndexBy(filters, "filterType")
|
|
var status interface{} = this.SafeString(market, "spotTradingEnable")
|
|
var active interface{} = (IsEqual(status, "1"))
|
|
var permissions interface{} = this.SafeValue(market, "permissions", []interface{}{})
|
|
for j := 0; IsLessThan(j, GetArrayLength(permissions)); j++ {
|
|
if IsTrue(IsEqual(GetValue(permissions, j), "TRD_GRP_003")) {
|
|
active = false
|
|
break
|
|
}
|
|
}
|
|
var isMarginTradingAllowed interface{} = this.SafeBool(market, "isMarginTradingAllowed", false)
|
|
var entry interface{} = map[string]interface{} {
|
|
"id": id,
|
|
"lowercaseId": lowercaseId,
|
|
"symbol": symbol,
|
|
"base": base,
|
|
"quote": quote,
|
|
"settle": settle,
|
|
"baseId": baseId,
|
|
"quoteId": quoteId,
|
|
"settleId": settleId,
|
|
"type": "spot",
|
|
"spot": true,
|
|
"margin": isMarginTradingAllowed,
|
|
"swap": false,
|
|
"future": false,
|
|
"delivery": false,
|
|
"option": false,
|
|
"active": active,
|
|
"contract": false,
|
|
"linear": nil,
|
|
"inverse": nil,
|
|
"contractSize": nil,
|
|
"expiry": nil,
|
|
"expiryDatetime": nil,
|
|
"strike": nil,
|
|
"optionType": nil,
|
|
"precision": map[string]interface{} {
|
|
"amount": this.ParseNumber(this.ParsePrecision(this.SafeString(market, "quantityPrecision"))),
|
|
"price": this.ParseNumber(this.ParsePrecision(this.SafeString(market, "pricePrecision"))),
|
|
"base": this.ParseNumber(this.ParsePrecision(this.SafeString(market, "baseAssetPrecision"))),
|
|
"quote": this.ParseNumber(this.ParsePrecision(this.SafeString(market, "quotePrecision"))),
|
|
},
|
|
"limits": map[string]interface{} {
|
|
"leverage": map[string]interface{} {
|
|
"min": nil,
|
|
"max": nil,
|
|
},
|
|
"amount": map[string]interface{} {
|
|
"min": nil,
|
|
"max": nil,
|
|
},
|
|
"price": map[string]interface{} {
|
|
"min": nil,
|
|
"max": nil,
|
|
},
|
|
"cost": map[string]interface{} {
|
|
"min": nil,
|
|
"max": nil,
|
|
},
|
|
},
|
|
"created": nil,
|
|
"info": market,
|
|
}
|
|
if IsTrue(InOp(filtersByType, "PRICE_FILTER")) {
|
|
var filter interface{} = this.SafeValue(filtersByType, "PRICE_FILTER", map[string]interface{} {})
|
|
AddElementToObject(GetValue(entry, "precision"), "price", this.SafeNumber(filter, "tickSize"))
|
|
// PRICE_FILTER reports zero values for maxPrice
|
|
// since they updated filter types in November 2018
|
|
// https://github.com/ccxt/ccxt/issues/4286
|
|
// therefore limits['price']['max'] doesn't have any meaningful value except undefined
|
|
AddElementToObject(GetValue(entry, "limits"), "price", map[string]interface{} {
|
|
"min": this.SafeNumber(filter, "minPrice"),
|
|
"max": this.SafeNumber(filter, "maxPrice"),
|
|
})
|
|
AddElementToObject(GetValue(entry, "precision"), "price", GetValue(filter, "tickSize"))
|
|
}
|
|
if IsTrue(InOp(filtersByType, "LOT_SIZE")) {
|
|
var filter interface{} = this.SafeValue(filtersByType, "LOT_SIZE", map[string]interface{} {})
|
|
AddElementToObject(GetValue(entry, "precision"), "amount", this.SafeNumber(filter, "stepSize"))
|
|
AddElementToObject(GetValue(entry, "limits"), "amount", map[string]interface{} {
|
|
"min": this.SafeNumber(filter, "minQty"),
|
|
"max": this.SafeNumber(filter, "maxQty"),
|
|
})
|
|
}
|
|
if IsTrue(InOp(filtersByType, "MARKET_LOT_SIZE")) {
|
|
var filter interface{} = this.SafeValue(filtersByType, "MARKET_LOT_SIZE", map[string]interface{} {})
|
|
AddElementToObject(GetValue(entry, "limits"), "market", map[string]interface{} {
|
|
"min": this.SafeNumber(filter, "minQty"),
|
|
"max": this.SafeNumber(filter, "maxQty"),
|
|
})
|
|
}
|
|
if IsTrue(InOp(filtersByType, "MIN_NOTIONAL")) {
|
|
var filter interface{} = this.SafeValue(filtersByType, "MIN_NOTIONAL", map[string]interface{} {})
|
|
AddElementToObject(GetValue(GetValue(entry, "limits"), "cost"), "min", this.SafeNumber2(filter, "minNotional", "notional"))
|
|
}
|
|
AppendToArray(&result,entry)
|
|
}
|
|
|
|
ch <- result
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchOrderBook
|
|
* @see https://www.tokocrypto.com/apidocs/#order-book
|
|
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
* @param {int} [limit] the maximum amount of order book entries to return
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
*/
|
|
func (this *tokocrypto) FetchOrderBook(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
limit := GetArg(optionalArgs, 0, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes8808 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes8808)
|
|
var market interface{} = this.Market(symbol)
|
|
var request interface{} = map[string]interface{} {}
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit) // default 100, max 5000, see https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#order-book
|
|
}
|
|
var response interface{} = nil
|
|
if IsTrue(IsEqual(GetValue(market, "quote"), "USDT")) {
|
|
AddElementToObject(request, "symbol", Add(GetValue(market, "baseId"), GetValue(market, "quoteId")))
|
|
|
|
response = (<-this.BinanceGetDepth(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
} else {
|
|
AddElementToObject(request, "symbol", GetValue(market, "id"))
|
|
|
|
response = (<-this.PublicGetOpenV1MarketDepth(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
}
|
|
//
|
|
// future
|
|
//
|
|
// {
|
|
// "lastUpdateId":333598053905,
|
|
// "E":1618631511986,
|
|
// "T":1618631511964,
|
|
// "bids":[
|
|
// ["2493.56","20.189"],
|
|
// ["2493.54","1.000"],
|
|
// ["2493.51","0.005"]
|
|
// ],
|
|
// "asks":[
|
|
// ["2493.57","0.877"],
|
|
// ["2493.62","0.063"],
|
|
// ["2493.71","12.054"],
|
|
// ]
|
|
// }
|
|
// type not 1
|
|
// {
|
|
// "code":0,
|
|
// "msg":"Success",
|
|
// "data":{
|
|
// "lastUpdateId":3204783,
|
|
// "bids":[],
|
|
// "asks": []
|
|
// },
|
|
// "timestamp":1692262634599
|
|
// }
|
|
var data interface{} = this.SafeValue(response, "data", response)
|
|
var timestamp interface{} = this.SafeInteger2(response, "T", "timestamp")
|
|
var orderbook interface{} = this.ParseOrderBook(data, symbol, timestamp)
|
|
AddElementToObject(orderbook, "nonce", this.SafeInteger(data, "lastUpdateId"))
|
|
|
|
ch <- orderbook
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) ParseTrade(trade interface{}, optionalArgs ...interface{}) interface{} {
|
|
//
|
|
// aggregate trades
|
|
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
|
|
//
|
|
// {
|
|
// "a": 26129, // Aggregate tradeId
|
|
// "p": "0.01633102", // Price
|
|
// "q": "4.70443515", // Quantity
|
|
// "f": 27781, // First tradeId
|
|
// "l": 27781, // Last tradeId
|
|
// "T": 1498793709153, // Timestamp
|
|
// "m": true, // Was the buyer the maker?
|
|
// "M": true // Was the trade the best price match?
|
|
// }
|
|
//
|
|
// recent public trades and old public trades
|
|
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#recent-trades-list
|
|
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#old-trade-lookup-market_data
|
|
//
|
|
// {
|
|
// "id": 28457,
|
|
// "price": "4.00000100",
|
|
// "qty": "12.00000000",
|
|
// "time": 1499865549590,
|
|
// "isBuyerMaker": true,
|
|
// "isBestMatch": true
|
|
// }
|
|
//
|
|
// private trades
|
|
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#account-trade-list-user_data
|
|
//
|
|
// {
|
|
// "symbol": "BNBBTC",
|
|
// "id": 28457,
|
|
// "orderId": 100234,
|
|
// "price": "4.00000100",
|
|
// "qty": "12.00000000",
|
|
// "commission": "10.10000000",
|
|
// "commissionAsset": "BNB",
|
|
// "time": 1499865549590,
|
|
// "isBuyer": true,
|
|
// "isMaker": false,
|
|
// "isBestMatch": true
|
|
// }
|
|
//
|
|
// futures trades
|
|
// https://binance-docs.github.io/apidocs/futures/en/#account-trade-list-user_data
|
|
//
|
|
// {
|
|
// "accountId": 20,
|
|
// "buyer": False,
|
|
// "commission": "-0.07819010",
|
|
// "commissionAsset": "USDT",
|
|
// "counterPartyId": 653,
|
|
// "id": 698759,
|
|
// "maker": False,
|
|
// "orderId": 25851813,
|
|
// "price": "7819.01",
|
|
// "qty": "0.002",
|
|
// "quoteQty": "0.01563",
|
|
// "realizedPnl": "-0.91539999",
|
|
// "side": "SELL",
|
|
// "symbol": "BTCUSDT",
|
|
// "time": 1569514978020
|
|
// }
|
|
// {
|
|
// "symbol": "BTCUSDT",
|
|
// "id": 477128891,
|
|
// "orderId": 13809777875,
|
|
// "side": "SELL",
|
|
// "price": "38479.55",
|
|
// "qty": "0.001",
|
|
// "realizedPnl": "-0.00009534",
|
|
// "marginAsset": "USDT",
|
|
// "quoteQty": "38.47955",
|
|
// "commission": "-0.00076959",
|
|
// "commissionAsset": "USDT",
|
|
// "time": 1612733566708,
|
|
// "positionSide": "BOTH",
|
|
// "maker": true,
|
|
// "buyer": false
|
|
// }
|
|
//
|
|
// { respType: FULL }
|
|
//
|
|
// {
|
|
// "price": "4000.00000000",
|
|
// "qty": "1.00000000",
|
|
// "commission": "4.00000000",
|
|
// "commissionAsset": "USDT",
|
|
// "tradeId": "1234",
|
|
// }
|
|
//
|
|
market := GetArg(optionalArgs, 0, nil)
|
|
_ = market
|
|
var timestamp interface{} = this.SafeInteger2(trade, "T", "time")
|
|
var price interface{} = this.SafeString2(trade, "p", "price")
|
|
var amount interface{} = this.SafeString2(trade, "q", "qty")
|
|
var cost interface{} = this.SafeString2(trade, "quoteQty", "baseQty") // inverse futures
|
|
var marketId interface{} = this.SafeString(trade, "symbol")
|
|
var symbol interface{} = this.SafeSymbol(marketId, market)
|
|
var id interface{} = this.SafeString2(trade, "t", "a")
|
|
id = this.SafeString2(trade, "id", "tradeId", id)
|
|
var side interface{} = nil
|
|
var orderId interface{} = this.SafeString(trade, "orderId")
|
|
var buyerMaker interface{} = this.SafeValue2(trade, "m", "isBuyerMaker")
|
|
var takerOrMaker interface{} = nil
|
|
if IsTrue(!IsEqual(buyerMaker, nil)) {
|
|
side = Ternary(IsTrue(buyerMaker), "sell", "buy") // this is reversed intentionally
|
|
takerOrMaker = "taker"
|
|
} else if IsTrue(InOp(trade, "side")) {
|
|
side = this.SafeStringLower(trade, "side")
|
|
} else {
|
|
if IsTrue(InOp(trade, "isBuyer")) {
|
|
side = Ternary(IsTrue(GetValue(trade, "isBuyer")), "buy", "sell") // this is a true side
|
|
}
|
|
}
|
|
var fee interface{} = nil
|
|
if IsTrue(InOp(trade, "commission")) {
|
|
fee = map[string]interface{} {
|
|
"cost": this.SafeString(trade, "commission"),
|
|
"currency": this.SafeCurrencyCode(this.SafeString(trade, "commissionAsset")),
|
|
}
|
|
}
|
|
if IsTrue(InOp(trade, "isMaker")) {
|
|
takerOrMaker = Ternary(IsTrue(GetValue(trade, "isMaker")), "maker", "taker")
|
|
}
|
|
if IsTrue(InOp(trade, "maker")) {
|
|
takerOrMaker = Ternary(IsTrue(GetValue(trade, "maker")), "maker", "taker")
|
|
}
|
|
return this.SafeTrade(map[string]interface{} {
|
|
"info": trade,
|
|
"timestamp": timestamp,
|
|
"datetime": this.Iso8601(timestamp),
|
|
"symbol": symbol,
|
|
"id": id,
|
|
"order": orderId,
|
|
"type": nil,
|
|
"side": side,
|
|
"takerOrMaker": takerOrMaker,
|
|
"price": price,
|
|
"amount": amount,
|
|
"cost": cost,
|
|
"fee": fee,
|
|
}, market)
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchTrades
|
|
* @see https://www.tokocrypto.com/apidocs/#recent-trades-list
|
|
* @see https://www.tokocrypto.com/apidocs/#compressedaggregate-trades-list
|
|
* @description get the list of most recent trades for a particular symbol
|
|
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
* @param {int} [limit] the maximum amount of trades to fetch
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
*/
|
|
func (this *tokocrypto) FetchTrades(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
since := GetArg(optionalArgs, 0, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 1, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 2, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes10898 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes10898)
|
|
var market interface{} = this.Market(symbol)
|
|
var request interface{} = map[string]interface{} {
|
|
"symbol": this.GetMarketIdByType(market),
|
|
}
|
|
if IsTrue(!IsEqual(GetValue(market, "quote"), "USDT")) {
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit)
|
|
}
|
|
var responseInner interface{} = this.PublicGetOpenV1MarketTrades(this.Extend(request, params))
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "success",
|
|
// "data": {
|
|
// "list": [
|
|
// {
|
|
// "id": 28457,
|
|
// "price": "4.00000100",
|
|
// "qty": "12.00000000",
|
|
// "time": 1499865549590,
|
|
// "isBuyerMaker": true,
|
|
// "isBestMatch": true
|
|
// }
|
|
// ]
|
|
// },
|
|
// "timestamp": 1571921637091
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeDict(responseInner, "data", map[string]interface{} {})
|
|
var list interface{} = this.SafeList(data, "list", []interface{}{})
|
|
|
|
ch <- this.ParseTrades(list, market, since, limit)
|
|
return nil
|
|
}
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit) // default = 500, maximum = 1000
|
|
}
|
|
var defaultMethod interface{} = "binanceGetTrades"
|
|
var method interface{} = this.SafeString(this.Options, "fetchTradesMethod", defaultMethod)
|
|
var response interface{} = nil
|
|
if IsTrue(IsTrue((IsEqual(method, "binanceGetAggTrades"))) && IsTrue((!IsEqual(since, nil)))) {
|
|
AddElementToObject(request, "startTime", since)
|
|
// https://github.com/ccxt/ccxt/issues/6400
|
|
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
|
|
AddElementToObject(request, "endTime", this.Sum(since, 3600000))
|
|
|
|
response = (<-this.BinanceGetAggTrades(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
} else {
|
|
|
|
response = (<-this.BinanceGetTrades(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
}
|
|
|
|
//
|
|
// Caveats:
|
|
// - default limit (500) applies only if no other parameters set, trades up
|
|
// to the maximum limit may be returned to satisfy other parameters
|
|
// - if both limit and time window is set and time window contains more
|
|
// trades than the limit then the last trades from the window are returned
|
|
// - 'tradeId' accepted and returned by this method is "aggregate" trade id
|
|
// which is different from actual trade id
|
|
// - setting both fromId and time window results in error
|
|
//
|
|
// aggregate trades
|
|
//
|
|
// [
|
|
// {
|
|
// "a": 26129, // Aggregate tradeId
|
|
// "p": "0.01633102", // Price
|
|
// "q": "4.70443515", // Quantity
|
|
// "f": 27781, // First tradeId
|
|
// "l": 27781, // Last tradeId
|
|
// "T": 1498793709153, // Timestamp
|
|
// "m": true, // Was the buyer the maker?
|
|
// "M": true // Was the trade the best price match?
|
|
// }
|
|
// ]
|
|
//
|
|
// recent public trades and historical public trades
|
|
//
|
|
// [
|
|
// {
|
|
// "id": 28457,
|
|
// "price": "4.00000100",
|
|
// "qty": "12.00000000",
|
|
// "time": 1499865549590,
|
|
// "isBuyerMaker": true,
|
|
// "isBestMatch": true
|
|
// }
|
|
// ]
|
|
//
|
|
ch <- this.ParseTrades(response, market, since, limit)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) ParseTicker(ticker interface{}, optionalArgs ...interface{}) interface{} {
|
|
//
|
|
// {
|
|
// "symbol": "ETHBTC",
|
|
// "priceChange": "0.00068700",
|
|
// "priceChangePercent": "2.075",
|
|
// "weightedAvgPrice": "0.03342681",
|
|
// "prevClosePrice": "0.03310300",
|
|
// "lastPrice": "0.03378900",
|
|
// "lastQty": "0.07700000",
|
|
// "bidPrice": "0.03378900",
|
|
// "bidQty": "7.16800000",
|
|
// "askPrice": "0.03379000",
|
|
// "askQty": "24.00000000",
|
|
// "openPrice": "0.03310200",
|
|
// "highPrice": "0.03388900",
|
|
// "lowPrice": "0.03306900",
|
|
// "volume": "205478.41000000",
|
|
// "quoteVolume": "6868.48826294",
|
|
// "openTime": 1601469986932,
|
|
// "closeTime": 1601556386932,
|
|
// "firstId": 196098772,
|
|
// "lastId": 196186315,
|
|
// "count": 87544
|
|
// }
|
|
//
|
|
// coinm
|
|
// {
|
|
// "baseVolume": "214549.95171161",
|
|
// "closeTime": "1621965286847",
|
|
// "count": "1283779",
|
|
// "firstId": "152560106",
|
|
// "highPrice": "39938.3",
|
|
// "lastId": "153843955",
|
|
// "lastPrice": "37993.4",
|
|
// "lastQty": "1",
|
|
// "lowPrice": "36457.2",
|
|
// "openPrice": "37783.4",
|
|
// "openTime": "1621878840000",
|
|
// "pair": "BTCUSD",
|
|
// "priceChange": "210.0",
|
|
// "priceChangePercent": "0.556",
|
|
// "symbol": "BTCUSD_PERP",
|
|
// "volume": "81990451",
|
|
// "weightedAvgPrice": "38215.08713747"
|
|
// }
|
|
//
|
|
market := GetArg(optionalArgs, 0, nil)
|
|
_ = market
|
|
var timestamp interface{} = this.SafeInteger(ticker, "closeTime")
|
|
var marketId interface{} = this.SafeString(ticker, "symbol")
|
|
var symbol interface{} = this.SafeSymbol(marketId, market)
|
|
var last interface{} = this.SafeString(ticker, "lastPrice")
|
|
var isCoinm interface{} = (InOp(ticker, "baseVolume"))
|
|
var baseVolume interface{} = nil
|
|
var quoteVolume interface{} = nil
|
|
if IsTrue(isCoinm) {
|
|
baseVolume = this.SafeString(ticker, "baseVolume")
|
|
quoteVolume = this.SafeString(ticker, "volume")
|
|
} else {
|
|
baseVolume = this.SafeString(ticker, "volume")
|
|
quoteVolume = this.SafeString(ticker, "quoteVolume")
|
|
}
|
|
return this.SafeTicker(map[string]interface{} {
|
|
"symbol": symbol,
|
|
"timestamp": timestamp,
|
|
"datetime": this.Iso8601(timestamp),
|
|
"high": this.SafeString(ticker, "highPrice"),
|
|
"low": this.SafeString(ticker, "lowPrice"),
|
|
"bid": this.SafeString(ticker, "bidPrice"),
|
|
"bidVolume": this.SafeString(ticker, "bidQty"),
|
|
"ask": this.SafeString(ticker, "askPrice"),
|
|
"askVolume": this.SafeString(ticker, "askQty"),
|
|
"vwap": this.SafeString(ticker, "weightedAvgPrice"),
|
|
"open": this.SafeString(ticker, "openPrice"),
|
|
"close": last,
|
|
"last": last,
|
|
"previousClose": this.SafeString(ticker, "prevClosePrice"),
|
|
"change": this.SafeString(ticker, "priceChange"),
|
|
"percentage": this.SafeString(ticker, "priceChangePercent"),
|
|
"average": nil,
|
|
"baseVolume": baseVolume,
|
|
"quoteVolume": quoteVolume,
|
|
"info": ticker,
|
|
}, market)
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchTickers
|
|
* @see https://binance-docs.github.io/apidocs/spot/en/#24hr-ticker-price-change-statistics
|
|
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
|
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchTickers(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbols := GetArg(optionalArgs, 0, nil)
|
|
_ = symbols
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes12778 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes12778)
|
|
|
|
response:= (<-this.BinanceGetTicker24hr(params))
|
|
PanicOnError(response)
|
|
|
|
ch <- this.ParseTickers(response, symbols)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) GetMarketIdByType(market interface{}) interface{} {
|
|
if IsTrue(IsEqual(GetValue(market, "quote"), "USDT")) {
|
|
return Add(GetValue(market, "baseId"), GetValue(market, "quoteId"))
|
|
}
|
|
return GetValue(market, "id")
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchTicker
|
|
* @see https://binance-docs.github.io/apidocs/spot/en/#24hr-ticker-price-change-statistics
|
|
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchTicker(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
params := GetArg(optionalArgs, 0, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes12998 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes12998)
|
|
var market interface{} = this.Market(symbol)
|
|
var request interface{} = map[string]interface{} {
|
|
"symbol": Add(GetValue(market, "baseId"), GetValue(market, "quoteId")),
|
|
}
|
|
|
|
response:= (<-this.BinanceGetTicker24hr(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
if IsTrue(IsArray(response)) {
|
|
var firstTicker interface{} = this.SafeDict(response, 0, map[string]interface{} {})
|
|
|
|
ch <- this.ParseTicker(firstTicker, market)
|
|
return nil
|
|
}
|
|
|
|
ch <- this.ParseTicker(response, market)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchBidsAsks
|
|
* @see https://binance-docs.github.io/apidocs/spot/en/#symbol-order-book-ticker
|
|
* @description fetches the bid and ask price and volume for multiple markets
|
|
* @param {string[]|undefined} symbols unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchBidsAsks(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbols := GetArg(optionalArgs, 0, nil)
|
|
_ = symbols
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes13228 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes13228)
|
|
|
|
response:= (<-this.BinanceGetTickerBookTicker(params))
|
|
PanicOnError(response)
|
|
|
|
ch <- this.ParseTickers(response, symbols)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) ParseOHLCV(ohlcv interface{}, optionalArgs ...interface{}) interface{} {
|
|
// when api method = publicGetKlines || fapiPublicGetKlines || dapiPublicGetKlines
|
|
// [
|
|
// 1591478520000, // open time
|
|
// "0.02501300", // open
|
|
// "0.02501800", // high
|
|
// "0.02500000", // low
|
|
// "0.02500000", // close
|
|
// "22.19000000", // volume
|
|
// 1591478579999, // close time
|
|
// "0.55490906", // quote asset volume
|
|
// 40, // number of trades
|
|
// "10.92900000", // taker buy base asset volume
|
|
// "0.27336462", // taker buy quote asset volume
|
|
// "0" // ignore
|
|
// ]
|
|
//
|
|
// when api method = fapiPublicGetMarkPriceKlines || fapiPublicGetIndexPriceKlines
|
|
// [
|
|
// [
|
|
// 1591256460000, // Open time
|
|
// "9653.29201333", // Open
|
|
// "9654.56401333", // High
|
|
// "9653.07367333", // Low
|
|
// "9653.07367333", // Close (or latest price)
|
|
// "0", // Ignore
|
|
// 1591256519999, // Close time
|
|
// "0", // Ignore
|
|
// 60, // Number of bisic data
|
|
// "0", // Ignore
|
|
// "0", // Ignore
|
|
// "0" // Ignore
|
|
// ]
|
|
// ]
|
|
//
|
|
market := GetArg(optionalArgs, 0, nil)
|
|
_ = market
|
|
return []interface{}{this.SafeInteger(ohlcv, 0), this.SafeNumber(ohlcv, 1), this.SafeNumber(ohlcv, 2), this.SafeNumber(ohlcv, 3), this.SafeNumber(ohlcv, 4), this.SafeNumber(ohlcv, 5)}
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchOHLCV
|
|
* @see https://binance-docs.github.io/apidocs/spot/en/#kline-candlestick-data
|
|
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
* @param {string} timeframe the length of time each candle represents
|
|
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
* @param {int} [limit] the maximum amount of candles to fetch
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @param {string} [params.price] "mark" or "index" for mark price and index price candles
|
|
* @param {int} [params.until] timestamp in ms of the latest candle to fetch
|
|
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
*/
|
|
func (this *tokocrypto) FetchOHLCV(symbol interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
timeframe := GetArg(optionalArgs, 0, "1m")
|
|
_ = timeframe
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes13878 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes13878)
|
|
var market interface{} = this.Market(symbol)
|
|
// binance docs say that the default limit 500, max 1500 for futures, max 1000 for spot markets
|
|
// the reality is that the time range wider than 500 candles won't work right
|
|
var defaultLimit interface{} = 500
|
|
var maxLimit interface{} = 1500
|
|
var price interface{} = this.SafeString(params, "price")
|
|
var until interface{} = this.SafeInteger(params, "until")
|
|
params = this.Omit(params, []interface{}{"price", "until"})
|
|
limit = Ternary(IsTrue((IsEqual(limit, nil))), defaultLimit, mathMin(limit, maxLimit))
|
|
var request interface{} = map[string]interface{} {
|
|
"interval": this.SafeString(this.Timeframes, timeframe, timeframe),
|
|
"limit": limit,
|
|
}
|
|
if IsTrue(IsEqual(price, "index")) {
|
|
AddElementToObject(request, "pair", GetValue(market, "id")) // Index price takes this argument instead of symbol
|
|
} else {
|
|
AddElementToObject(request, "symbol", this.GetMarketIdByType(market))
|
|
}
|
|
// const duration = this.parseTimeframe (timeframe);
|
|
if IsTrue(!IsEqual(since, nil)) {
|
|
AddElementToObject(request, "startTime", since)
|
|
}
|
|
if IsTrue(!IsEqual(until, nil)) {
|
|
AddElementToObject(request, "endTime", until)
|
|
}
|
|
var response interface{} = nil
|
|
if IsTrue(IsEqual(GetValue(market, "quote"), "USDT")) {
|
|
|
|
response = (<-this.BinanceGetKlines(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
} else {
|
|
|
|
response = (<-this.PublicGetOpenV1MarketKlines(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
}
|
|
//
|
|
// [
|
|
// [1591478520000,"0.02501300","0.02501800","0.02500000","0.02500000","22.19000000",1591478579999,"0.55490906",40,"10.92900000","0.27336462","0"],
|
|
// [1591478580000,"0.02499600","0.02500900","0.02499400","0.02500300","21.34700000",1591478639999,"0.53370468",24,"7.53800000","0.18850725","0"],
|
|
// [1591478640000,"0.02500800","0.02501100","0.02500300","0.02500800","154.14200000",1591478699999,"3.85405839",97,"5.32300000","0.13312641","0"],
|
|
// ]
|
|
//
|
|
var data interface{} = this.SafeList(response, "data", response)
|
|
|
|
ch <- this.ParseOHLCVs(data, market, timeframe, since, limit)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchBalance
|
|
* @see https://www.tokocrypto.com/apidocs/#account-information-signed
|
|
* @description query for balance and get the amount of funds available for trading or funds locked in orders
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @param {string} [params.type] 'future', 'delivery', 'savings', 'funding', or 'spot'
|
|
* @param {string} [params.marginMode] 'cross' or 'isolated', for margin trading, uses this.options.defaultMarginMode if not passed, defaults to undefined/None/null
|
|
* @param {string[]|undefined} [params.symbols] unified market symbols, only used in isolated margin mode
|
|
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchBalance(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
params := GetArg(optionalArgs, 0, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes14428 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes14428)
|
|
var defaultType interface{} = this.SafeString2(this.Options, "fetchBalance", "defaultType", "spot")
|
|
var typeVar interface{} = this.SafeString(params, "type", defaultType)
|
|
var defaultMarginMode interface{} = this.SafeString2(this.Options, "marginMode", "defaultMarginMode")
|
|
var marginMode interface{} = this.SafeStringLower(params, "marginMode", defaultMarginMode)
|
|
var request interface{} = map[string]interface{} {}
|
|
|
|
response:= (<-this.PrivateGetOpenV1AccountSpot(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
|
|
//
|
|
// spot
|
|
//
|
|
// {
|
|
// "code":0,
|
|
// "msg":"Success",
|
|
// "data":{
|
|
// "makerCommission":"0.00100000",
|
|
// "takerCommission":"0.00100000",
|
|
// "buyerCommission":"0.00000000",
|
|
// "sellerCommission":"0.00000000",
|
|
// "canTrade":1,
|
|
// "canWithdraw":1,
|
|
// "canDeposit":1,
|
|
// "status":1,
|
|
// "accountAssets":[
|
|
// {"asset":"1INCH","free":"0","locked":"0"},
|
|
// {"asset":"AAVE","free":"0","locked":"0"},
|
|
// {"asset":"ACA","free":"0","locked":"0"}
|
|
// ],
|
|
// },
|
|
// "timestamp":1659666786943
|
|
// }
|
|
//
|
|
ch <- this.ParseBalanceCustom(response, typeVar, marginMode)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) ParseBalanceCustom(response interface{}, optionalArgs ...interface{}) interface{} {
|
|
typeVar := GetArg(optionalArgs, 0, nil)
|
|
_ = typeVar
|
|
marginMode := GetArg(optionalArgs, 1, nil)
|
|
_ = marginMode
|
|
var timestamp interface{} = this.SafeInteger(response, "updateTime")
|
|
var result interface{} = map[string]interface{} {
|
|
"info": response,
|
|
"timestamp": timestamp,
|
|
"datetime": this.Iso8601(timestamp),
|
|
}
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var balances interface{} = this.SafeValue(data, "accountAssets", []interface{}{})
|
|
for i := 0; IsLessThan(i, GetArrayLength(balances)); i++ {
|
|
var balance interface{} = GetValue(balances, i)
|
|
var currencyId interface{} = this.SafeString(balance, "asset")
|
|
var code interface{} = this.SafeCurrencyCode(currencyId)
|
|
var account interface{} = this.Account()
|
|
AddElementToObject(account, "free", this.SafeString(balance, "free"))
|
|
AddElementToObject(account, "used", this.SafeString(balance, "locked"))
|
|
AddElementToObject(result, code, account)
|
|
}
|
|
return this.SafeBalance(result)
|
|
}
|
|
func (this *tokocrypto) ParseOrderStatus(status interface{}) interface{} {
|
|
var statuses interface{} = map[string]interface{} {
|
|
"-2": "open",
|
|
"0": "open",
|
|
"1": "open",
|
|
"2": "closed",
|
|
"3": "canceled",
|
|
"4": "canceling",
|
|
"5": "rejected",
|
|
"6": "expired",
|
|
"NEW": "open",
|
|
"PARTIALLY_FILLED": "open",
|
|
"FILLED": "closed",
|
|
"CANCELED": "canceled",
|
|
"PENDING_CANCEL": "canceling",
|
|
"REJECTED": "rejected",
|
|
"EXPIRED": "expired",
|
|
}
|
|
return this.SafeString(statuses, status, status)
|
|
}
|
|
func (this *tokocrypto) ParseOrder(order interface{}, optionalArgs ...interface{}) interface{} {
|
|
//
|
|
// spot
|
|
//
|
|
// {
|
|
// "symbol": "LTCBTC",
|
|
// "orderId": 1,
|
|
// "clientOrderId": "myOrder1",
|
|
// "price": "0.1",
|
|
// "origQty": "1.0",
|
|
// "executedQty": "0.0",
|
|
// "cummulativeQuoteQty": "0.0",
|
|
// "status": "NEW",
|
|
// "timeInForce": "GTC",
|
|
// "type": "LIMIT",
|
|
// "side": "BUY",
|
|
// "stopPrice": "0.0",
|
|
// "icebergQty": "0.0",
|
|
// "time": 1499827319559,
|
|
// "updateTime": 1499827319559,
|
|
// "isWorking": true
|
|
// }
|
|
// createOrder
|
|
// {
|
|
// "orderId": "145265071",
|
|
// "bOrderListId": "0",
|
|
// "clientId": "49c09c3c2cd54419a59c05441f517b3c",
|
|
// "bOrderId": "35247529",
|
|
// "symbol": "USDT_BIDR",
|
|
// "symbolType": "1",
|
|
// "side": "0",
|
|
// "type": "1",
|
|
// "price": "11915",
|
|
// "origQty": "2",
|
|
// "origQuoteQty": "23830.00",
|
|
// "executedQty": "0.00000000",
|
|
// "executedPrice": "0",
|
|
// "executedQuoteQty": "0.00",
|
|
// "timeInForce": "1",
|
|
// "stopPrice": "0",
|
|
// "icebergQty": "0",
|
|
// "status": "0",
|
|
// "createTime": "1662711074372"
|
|
// }
|
|
//
|
|
// createOrder with { "newOrderRespType": "FULL" }
|
|
//
|
|
// {
|
|
// "symbol": "BTCUSDT",
|
|
// "orderId": 5403233939,
|
|
// "orderListId": -1,
|
|
// "clientOrderId": "x-R4BD3S825e669e75b6c14f69a2c43e",
|
|
// "transactTime": 1617151923742,
|
|
// "price": "0.00000000",
|
|
// "origQty": "0.00050000",
|
|
// "executedQty": "0.00050000",
|
|
// "cummulativeQuoteQty": "29.47081500",
|
|
// "status": "FILLED",
|
|
// "timeInForce": "GTC",
|
|
// "type": "MARKET",
|
|
// "side": "BUY",
|
|
// "fills": [
|
|
// {
|
|
// "price": "58941.63000000",
|
|
// "qty": "0.00050000",
|
|
// "commission": "0.00007050",
|
|
// "commissionAsset": "BNB",
|
|
// "tradeId": 737466631
|
|
// }
|
|
// ]
|
|
// }
|
|
//
|
|
// delivery
|
|
//
|
|
// {
|
|
// "orderId": "18742727411",
|
|
// "symbol": "ETHUSD_PERP",
|
|
// "pair": "ETHUSD",
|
|
// "status": "FILLED",
|
|
// "clientOrderId": "x-xcKtGhcu3e2d1503fdd543b3b02419",
|
|
// "price": "0",
|
|
// "avgPrice": "4522.14",
|
|
// "origQty": "1",
|
|
// "executedQty": "1",
|
|
// "cumBase": "0.00221134",
|
|
// "timeInForce": "GTC",
|
|
// "type": "MARKET",
|
|
// "reduceOnly": false,
|
|
// "closePosition": false,
|
|
// "side": "SELL",
|
|
// "positionSide": "BOTH",
|
|
// "stopPrice": "0",
|
|
// "workingType": "CONTRACT_PRICE",
|
|
// "priceProtect": false,
|
|
// "origType": "MARKET",
|
|
// "time": "1636061952660",
|
|
// "updateTime": "1636061952660"
|
|
// }
|
|
//
|
|
market := GetArg(optionalArgs, 0, nil)
|
|
_ = market
|
|
var status interface{} = this.ParseOrderStatus(this.SafeString(order, "status"))
|
|
var marketId interface{} = this.SafeString(order, "symbol")
|
|
var symbol interface{} = this.SafeSymbol(marketId, market)
|
|
var filled interface{} = this.SafeString(order, "executedQty", "0")
|
|
var timestamp interface{} = this.SafeInteger(order, "createTime")
|
|
var average interface{} = this.SafeString(order, "avgPrice")
|
|
var price interface{} = this.SafeString2(order, "price", "executedPrice")
|
|
var amount interface{} = this.SafeString(order, "origQty")
|
|
// - Spot/Margin market: cummulativeQuoteQty
|
|
// Note this is not the actual cost, since Binance futures uses leverage to calculate margins.
|
|
var cost interface{} = this.SafeStringN(order, []interface{}{"cummulativeQuoteQty", "cumQuote", "executedQuoteQty", "cumBase"})
|
|
var id interface{} = this.SafeString(order, "orderId")
|
|
var typeVar interface{} = this.ParseOrderType(this.SafeStringLower(order, "type"))
|
|
var side interface{} = this.SafeStringLower(order, "side")
|
|
if IsTrue(IsEqual(side, "0")) {
|
|
side = "buy"
|
|
} else if IsTrue(IsEqual(side, "1")) {
|
|
side = "sell"
|
|
}
|
|
var fills interface{} = this.SafeValue(order, "fills", []interface{}{})
|
|
var clientOrderId interface{} = this.SafeString2(order, "clientOrderId", "clientId")
|
|
var timeInForce interface{} = this.SafeString(order, "timeInForce")
|
|
if IsTrue(IsEqual(timeInForce, "GTX")) {
|
|
// GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
|
|
timeInForce = "PO"
|
|
}
|
|
var postOnly interface{} = IsTrue((IsEqual(typeVar, "limit_maker"))) || IsTrue((IsEqual(timeInForce, "PO")))
|
|
return this.SafeOrder(map[string]interface{} {
|
|
"info": order,
|
|
"id": id,
|
|
"clientOrderId": clientOrderId,
|
|
"timestamp": timestamp,
|
|
"datetime": this.Iso8601(timestamp),
|
|
"lastTradeTimestamp": nil,
|
|
"symbol": symbol,
|
|
"type": typeVar,
|
|
"timeInForce": timeInForce,
|
|
"postOnly": postOnly,
|
|
"reduceOnly": this.SafeValue(order, "reduceOnly"),
|
|
"side": side,
|
|
"price": price,
|
|
"triggerPrice": this.ParseNumber(this.OmitZero(this.SafeString(order, "stopPrice"))),
|
|
"amount": amount,
|
|
"cost": cost,
|
|
"average": average,
|
|
"filled": filled,
|
|
"remaining": nil,
|
|
"status": status,
|
|
"fee": nil,
|
|
"trades": fills,
|
|
}, market)
|
|
}
|
|
func (this *tokocrypto) ParseOrderType(status interface{}) interface{} {
|
|
var statuses interface{} = map[string]interface{} {
|
|
"2": "market",
|
|
"1": "limit",
|
|
"4": "limit",
|
|
"7": "limit",
|
|
}
|
|
return this.SafeString(statuses, status, status)
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#createOrder
|
|
* @description create a trade order
|
|
* @see https://www.tokocrypto.com/apidocs/#new-order--signed
|
|
* @param {string} symbol unified symbol of the market to create an order in
|
|
* @param {string} type 'market' or 'limit'
|
|
* @param {string} side 'buy' or 'sell'
|
|
* @param {float} amount how much of currency you want to trade in units of base currency
|
|
* @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @param {float} [params.triggerPrice] the price at which a trigger order would be triggered
|
|
* @param {float} [params.cost] for spot market buy orders, the quote quantity that can be used as an alternative for the amount
|
|
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
*/
|
|
func (this *tokocrypto) CreateOrder(symbol interface{}, typeVar interface{}, side interface{}, amount interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
price := GetArg(optionalArgs, 0, nil)
|
|
_ = price
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes16968 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes16968)
|
|
var market interface{} = this.Market(symbol)
|
|
var clientOrderId interface{} = this.SafeString2(params, "clientOrderId", "clientId")
|
|
var postOnly interface{} = this.SafeBool(params, "postOnly", false)
|
|
// only supported for spot/margin api
|
|
if IsTrue(postOnly) {
|
|
typeVar = "LIMIT_MAKER"
|
|
}
|
|
params = this.Omit(params, []interface{}{"clientId", "clientOrderId"})
|
|
var initialUppercaseType interface{} = ToUpper(typeVar)
|
|
var uppercaseType interface{} = initialUppercaseType
|
|
var triggerPrice interface{} = this.SafeValue2(params, "triggerPrice", "stopPrice")
|
|
if IsTrue(!IsEqual(triggerPrice, nil)) {
|
|
params = this.Omit(params, []interface{}{"triggerPrice", "stopPrice"})
|
|
if IsTrue(IsEqual(uppercaseType, "MARKET")) {
|
|
uppercaseType = "STOP_LOSS"
|
|
} else if IsTrue(IsEqual(uppercaseType, "LIMIT")) {
|
|
uppercaseType = "STOP_LOSS_LIMIT"
|
|
}
|
|
}
|
|
var validOrderTypes interface{} = this.SafeValue(GetValue(market, "info"), "orderTypes")
|
|
if !IsTrue(this.InArray(uppercaseType, validOrderTypes)) {
|
|
if IsTrue(!IsEqual(initialUppercaseType, uppercaseType)) {
|
|
panic(InvalidOrder(Add(Add(Add(Add(Add(this.Id, " triggerPrice parameter is not allowed for "), symbol), " "), typeVar), " orders")))
|
|
} else {
|
|
panic(InvalidOrder(Add(Add(Add(Add(Add(this.Id, " "), typeVar), " is not a valid order type for the "), symbol), " market")))
|
|
}
|
|
}
|
|
var reverseOrderTypeMapping interface{} = map[string]interface{} {
|
|
"LIMIT": 1,
|
|
"MARKET": 2,
|
|
"STOP_LOSS": 3,
|
|
"STOP_LOSS_LIMIT": 4,
|
|
"TAKE_PROFIT": 5,
|
|
"TAKE_PROFIT_LIMIT": 6,
|
|
"LIMIT_MAKER": 7,
|
|
}
|
|
var request interface{} = map[string]interface{} {
|
|
"symbol": Add(Add(GetValue(market, "baseId"), "_"), GetValue(market, "quoteId")),
|
|
"type": this.SafeString(reverseOrderTypeMapping, uppercaseType),
|
|
}
|
|
if IsTrue(IsEqual(side, "buy")) {
|
|
AddElementToObject(request, "side", 0)
|
|
} else if IsTrue(IsEqual(side, "sell")) {
|
|
AddElementToObject(request, "side", 1)
|
|
}
|
|
if IsTrue(IsEqual(clientOrderId, nil)) {
|
|
var broker interface{} = this.SafeValue(this.Options, "broker")
|
|
if IsTrue(!IsEqual(broker, nil)) {
|
|
var brokerId interface{} = this.SafeString(broker, "marketType")
|
|
if IsTrue(!IsEqual(brokerId, nil)) {
|
|
AddElementToObject(request, "clientId", Add(brokerId, this.Uuid22()))
|
|
}
|
|
}
|
|
} else {
|
|
AddElementToObject(request, "clientId", clientOrderId)
|
|
}
|
|
// additional required fields depending on the order type
|
|
var priceIsRequired interface{} = false
|
|
var triggerPriceIsRequired interface{} = false
|
|
var quantityIsRequired interface{} = false
|
|
//
|
|
// spot/margin
|
|
//
|
|
// LIMIT timeInForce, quantity, price
|
|
// MARKET quantity or quoteOrderQty
|
|
// STOP_LOSS quantity, stopPrice
|
|
// STOP_LOSS_LIMIT timeInForce, quantity, price, stopPrice
|
|
// TAKE_PROFIT quantity, stopPrice
|
|
// TAKE_PROFIT_LIMIT timeInForce, quantity, price, stopPrice
|
|
// LIMIT_MAKER quantity, price
|
|
//
|
|
if IsTrue(IsEqual(uppercaseType, "MARKET")) {
|
|
if IsTrue(IsEqual(side, "buy")) {
|
|
var precision interface{} = GetValue(GetValue(market, "precision"), "price")
|
|
var quoteAmount interface{} = nil
|
|
var createMarketBuyOrderRequiresPrice interface{} = true
|
|
createMarketBuyOrderRequiresPriceparamsVariable := this.HandleOptionAndParams(params, "createOrder", "createMarketBuyOrderRequiresPrice", true);
|
|
createMarketBuyOrderRequiresPrice = GetValue(createMarketBuyOrderRequiresPriceparamsVariable,0);
|
|
params = GetValue(createMarketBuyOrderRequiresPriceparamsVariable,1)
|
|
var cost interface{} = this.SafeNumber2(params, "cost", "quoteOrderQty")
|
|
params = this.Omit(params, []interface{}{"cost", "quoteOrderQty"})
|
|
if IsTrue(!IsEqual(cost, nil)) {
|
|
quoteAmount = cost
|
|
} else if IsTrue(createMarketBuyOrderRequiresPrice) {
|
|
if IsTrue(IsEqual(price, nil)) {
|
|
panic(InvalidOrder(Add(this.Id, " createOrder() requires the price argument for market buy orders to calculate the total cost to spend (amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to false and pass the cost to spend (quote quantity) in the amount argument")))
|
|
} else {
|
|
var amountString interface{} = this.NumberToString(amount)
|
|
var priceString interface{} = this.NumberToString(price)
|
|
quoteAmount = Precise.StringMul(amountString, priceString)
|
|
}
|
|
} else {
|
|
quoteAmount = amount
|
|
}
|
|
AddElementToObject(request, "quoteOrderQty", this.DecimalToPrecision(quoteAmount, TRUNCATE, precision, this.PrecisionMode))
|
|
} else {
|
|
quantityIsRequired = true
|
|
}
|
|
} else if IsTrue(IsEqual(uppercaseType, "LIMIT")) {
|
|
priceIsRequired = true
|
|
quantityIsRequired = true
|
|
} else if IsTrue(IsTrue((IsEqual(uppercaseType, "STOP_LOSS"))) || IsTrue((IsEqual(uppercaseType, "TAKE_PROFIT")))) {
|
|
triggerPriceIsRequired = true
|
|
quantityIsRequired = true
|
|
if IsTrue(IsTrue(GetValue(market, "linear")) || IsTrue(GetValue(market, "inverse"))) {
|
|
priceIsRequired = true
|
|
}
|
|
} else if IsTrue(IsTrue((IsEqual(uppercaseType, "STOP_LOSS_LIMIT"))) || IsTrue((IsEqual(uppercaseType, "TAKE_PROFIT_LIMIT")))) {
|
|
quantityIsRequired = true
|
|
triggerPriceIsRequired = true
|
|
priceIsRequired = true
|
|
} else if IsTrue(IsEqual(uppercaseType, "LIMIT_MAKER")) {
|
|
priceIsRequired = true
|
|
quantityIsRequired = true
|
|
}
|
|
if IsTrue(quantityIsRequired) {
|
|
AddElementToObject(request, "quantity", this.AmountToPrecision(symbol, amount))
|
|
}
|
|
if IsTrue(priceIsRequired) {
|
|
if IsTrue(IsEqual(price, nil)) {
|
|
panic(InvalidOrder(Add(Add(Add(this.Id, " createOrder() requires a price argument for a "), typeVar), " order")))
|
|
}
|
|
AddElementToObject(request, "price", this.PriceToPrecision(symbol, price))
|
|
}
|
|
if IsTrue(triggerPriceIsRequired) {
|
|
if IsTrue(IsEqual(triggerPrice, nil)) {
|
|
panic(InvalidOrder(Add(Add(Add(this.Id, " createOrder() requires a triggerPrice extra param for a "), typeVar), " order")))
|
|
} else {
|
|
AddElementToObject(request, "stopPrice", this.PriceToPrecision(symbol, triggerPrice))
|
|
}
|
|
}
|
|
|
|
response:= (<-this.PrivatePostOpenV1Orders(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "Success",
|
|
// "data": {
|
|
// "orderId": 145264846,
|
|
// "bOrderListId": 0,
|
|
// "clientId": "4ee2ab5e55e74b358eaf98079c670d17",
|
|
// "bOrderId": 35247499,
|
|
// "symbol": "USDT_BIDR",
|
|
// "symbolType": 1,
|
|
// "side": 0,
|
|
// "type": 1,
|
|
// "price": "11915",
|
|
// "origQty": "2",
|
|
// "origQuoteQty": "23830.00",
|
|
// "executedQty": "0.00000000",
|
|
// "executedPrice": "0",
|
|
// "executedQuoteQty": "0.00",
|
|
// "timeInForce": 1,
|
|
// "stopPrice": 0,
|
|
// "icebergQty": "0",
|
|
// "status": 0,
|
|
// "createTime": 1662710994848
|
|
// },
|
|
// "timestamp": 1662710994975
|
|
// }
|
|
//
|
|
var rawOrder interface{} = this.SafeDict(response, "data", map[string]interface{} {})
|
|
|
|
ch <- this.ParseOrder(rawOrder, market)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchOrder
|
|
* @see https://www.tokocrypto.com/apidocs/#query-order-signed
|
|
* @description fetches information on an order made by the user
|
|
* @param {string} id order id
|
|
* @param {string} symbol unified symbol of the market the order was made in
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbol := GetArg(optionalArgs, 0, nil)
|
|
_ = symbol
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
var request interface{} = map[string]interface{} {
|
|
"orderId": id,
|
|
}
|
|
|
|
response:= (<-this.PrivateGetOpenV1Orders(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "Success",
|
|
// "data": {
|
|
// "list": [{
|
|
// "orderId": "145221985",
|
|
// "clientId": "201515331fd64d03aedbe687a38152e3",
|
|
// "bOrderId": "35239632",
|
|
// "bOrderListId": "0",
|
|
// "symbol": "USDT_BIDR",
|
|
// "symbolType": 1,
|
|
// "side": 0,
|
|
// "type": 1,
|
|
// "price": "11907",
|
|
// "origQty": "2",
|
|
// "origQuoteQty": "23814",
|
|
// "executedQty": "0",
|
|
// "executedPrice": "0",
|
|
// "executedQuoteQty": "0",
|
|
// "timeInForce": 1,
|
|
// "stopPrice": "0",
|
|
// "icebergQty": "0",
|
|
// "status": 0,
|
|
// "createTime": 1662699360000
|
|
// }]
|
|
// },
|
|
// "timestamp": 1662710056523
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var list interface{} = this.SafeValue(data, "list", []interface{}{})
|
|
var rawOrder interface{} = this.SafeDict(list, 0, map[string]interface{} {})
|
|
|
|
ch <- this.ParseOrder(rawOrder)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchOrders
|
|
* @see https://www.tokocrypto.com/apidocs/#all-orders-signed
|
|
* @description fetches information on multiple orders made by the user
|
|
* @param {string} symbol unified market symbol of the market orders were made in
|
|
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchOrders(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbol := GetArg(optionalArgs, 0, nil)
|
|
_ = symbol
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
if IsTrue(IsEqual(symbol, nil)) {
|
|
panic(ArgumentsRequired(Add(this.Id, " fetchOrders() requires a symbol argument")))
|
|
}
|
|
|
|
retRes19258 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes19258)
|
|
var market interface{} = this.Market(symbol)
|
|
var request interface{} = map[string]interface{} {
|
|
"symbol": GetValue(market, "id"),
|
|
}
|
|
if IsTrue(!IsEqual(since, nil)) {
|
|
AddElementToObject(request, "startTime", since)
|
|
}
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit)
|
|
}
|
|
|
|
response:= (<-this.PrivateGetOpenV1Orders(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "success",
|
|
// "data": {
|
|
// "list": [
|
|
// {
|
|
// "orderId": "4", // order id
|
|
// "bOrderId": "100001", // binance order id
|
|
// "bOrderListId": -1, // Unless part of an OCO, the value will always be -1.
|
|
// "clientId": "1aa4f99ad7bc4fab903395afd25d0597", // client custom order id
|
|
// "symbol": "ADA_USDT",
|
|
// "symbolType": 1,
|
|
// "side": 1,
|
|
// "type": 1,
|
|
// "price": "0.1",
|
|
// "origQty": "10",
|
|
// "origQuoteQty": "1",
|
|
// "executedQty": "0",
|
|
// "executedPrice": "0",
|
|
// "executedQuoteQty": "0",
|
|
// "timeInForce": 1,
|
|
// "stopPrice": "0.0000000000000000",
|
|
// "icebergQty": "0.0000000000000000",
|
|
// "status": 0,
|
|
// "isWorking": 0,
|
|
// "createTime": 1572692016811
|
|
// }
|
|
// ]
|
|
// },
|
|
// "timestamp": 1572860756458
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var orders interface{} = this.SafeList(data, "list", []interface{}{})
|
|
|
|
ch <- this.ParseOrders(orders, market, since, limit)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchOpenOrders
|
|
* @see https://www.tokocrypto.com/apidocs/#all-orders-signed
|
|
* @description fetch all unfilled currently open orders
|
|
* @param {string} symbol unified market symbol
|
|
* @param {int} [since] the earliest time in ms to fetch open orders for
|
|
* @param {int} [limit] the maximum number of open orders structures to retrieve
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchOpenOrders(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbol := GetArg(optionalArgs, 0, nil)
|
|
_ = symbol
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
var request interface{} = map[string]interface{} {
|
|
"type": 1,
|
|
} // -1 = all, 1 = open, 2 = closed
|
|
|
|
retRes199515 := (<-this.FetchOrders(symbol, since, limit, this.Extend(request, params)))
|
|
PanicOnError(retRes199515)
|
|
ch <- retRes199515
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchClosedOrders
|
|
* @see https://www.tokocrypto.com/apidocs/#all-orders-signed
|
|
* @description fetches information on multiple closed orders made by the user
|
|
* @param {string} symbol unified market symbol of the market orders were made in
|
|
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchClosedOrders(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbol := GetArg(optionalArgs, 0, nil)
|
|
_ = symbol
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
var request interface{} = map[string]interface{} {
|
|
"type": 2,
|
|
} // -1 = all, 1 = open, 2 = closed
|
|
|
|
retRes201115 := (<-this.FetchOrders(symbol, since, limit, this.Extend(request, params)))
|
|
PanicOnError(retRes201115)
|
|
ch <- retRes201115
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#cancelOrder
|
|
* @see https://www.tokocrypto.com/apidocs/#cancel-order-signed
|
|
* @description cancels an open order
|
|
* @param {string} id order id
|
|
* @param {string} symbol unified symbol of the market the order was made in
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
*/
|
|
func (this *tokocrypto) CancelOrder(id interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbol := GetArg(optionalArgs, 0, nil)
|
|
_ = symbol
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
var request interface{} = map[string]interface{} {
|
|
"orderId": id,
|
|
}
|
|
|
|
response:= (<-this.PrivatePostOpenV1OrdersCancel(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "Success",
|
|
// "data": {
|
|
// "orderId": "145221985",
|
|
// "bOrderListId": "0",
|
|
// "clientId": "201515331fd64d03aedbe687a38152e3",
|
|
// "bOrderId": "35239632",
|
|
// "symbol": "USDT_BIDR",
|
|
// "symbolType": 1,
|
|
// "type": 1,
|
|
// "side": 0,
|
|
// "price": "11907.0000000000000000",
|
|
// "origQty": "2.0000000000000000",
|
|
// "origQuoteQty": "23814.0000000000000000",
|
|
// "executedPrice": "0.0000000000000000",
|
|
// "executedQty": "0.00000000",
|
|
// "executedQuoteQty": "0.00",
|
|
// "timeInForce": 1,
|
|
// "stopPrice": "0.0000000000000000",
|
|
// "icebergQty": "0.0000000000000000",
|
|
// "status": 3
|
|
// },
|
|
// "timestamp": 1662710683634
|
|
// }
|
|
//
|
|
var rawOrder interface{} = this.SafeDict(response, "data", map[string]interface{} {})
|
|
|
|
ch <- this.ParseOrder(rawOrder)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchMyTrades
|
|
* @see https://www.tokocrypto.com/apidocs/#account-trade-list-signed
|
|
* @description fetch all trades made by the user
|
|
* @param {string} symbol unified market symbol
|
|
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
* @param {int} [limit] the maximum number of trades structures to retrieve
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchMyTrades(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
symbol := GetArg(optionalArgs, 0, nil)
|
|
_ = symbol
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
if IsTrue(IsEqual(symbol, nil)) {
|
|
panic(ArgumentsRequired(Add(this.Id, " fetchMyTrades() requires a symbol argument")))
|
|
}
|
|
|
|
retRes20758 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes20758)
|
|
var market interface{} = this.Market(symbol)
|
|
var request interface{} = map[string]interface{} {
|
|
"symbol": GetValue(market, "id"),
|
|
}
|
|
var endTime interface{} = this.SafeInteger2(params, "until", "endTime")
|
|
if IsTrue(!IsEqual(since, nil)) {
|
|
AddElementToObject(request, "startTime", since)
|
|
}
|
|
if IsTrue(!IsEqual(endTime, nil)) {
|
|
AddElementToObject(request, "endTime", endTime)
|
|
params = this.Omit(params, []interface{}{"endTime", "until"})
|
|
}
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit)
|
|
}
|
|
|
|
response:= (<-this.PrivateGetOpenV1OrdersTrades(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "success",
|
|
// "data": {
|
|
// "list": [
|
|
// {
|
|
// "tradeId": "3",
|
|
// "orderId": "2",
|
|
// "symbol": "ADA_USDT",
|
|
// "price": "0.04398",
|
|
// "qty": "250",
|
|
// "quoteQty": "10.995",
|
|
// "commission": "0.25",
|
|
// "commissionAsset": "ADA",
|
|
// "isBuyer": 1,
|
|
// "isMaker": 0,
|
|
// "isBestMatch": 1,
|
|
// "time": "1572920872276"
|
|
// }
|
|
// ]
|
|
// },
|
|
// "timestamp": 1573723498893
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var trades interface{} = this.SafeList(data, "list", []interface{}{})
|
|
|
|
ch <- this.ParseTrades(trades, market, since, limit)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchDepositAddress
|
|
* @description fetch the deposit address for a currency associated with this account
|
|
* @see https://www.tokocrypto.com/apidocs/#deposit-address-signed
|
|
* @param {string} code unified currency code
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchDepositAddress(code interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
params := GetArg(optionalArgs, 0, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes21328 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes21328)
|
|
var currency interface{} = this.Currency(code)
|
|
var request interface{} = map[string]interface{} {
|
|
"asset": GetValue(currency, "id"),
|
|
}
|
|
var networks interface{} = this.SafeValue(this.Options, "networks", map[string]interface{} {})
|
|
var network interface{} = this.SafeStringUpper(params, "network") // this line allows the user to specify either ERC20 or ETH
|
|
network = this.SafeString(networks, network, network) // handle ERC20>ETH alias
|
|
if IsTrue(!IsEqual(network, nil)) {
|
|
AddElementToObject(request, "network", network)
|
|
params = this.Omit(params, "network")
|
|
}
|
|
// has support for the 'network' parameter
|
|
// https://binance-docs.github.io/apidocs/spot/en/#deposit-address-supporting-network-user_data
|
|
|
|
response:= (<-this.PrivateGetOpenV1DepositsAddress(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code":0,
|
|
// "msg":"Success",
|
|
// "data":{
|
|
// "uid":"182395",
|
|
// "asset":"USDT",
|
|
// "network":"ETH",
|
|
// "address":"0x101a925704f6ff13295ab8dd7a60988d116aaedf",
|
|
// "addressTag":"",
|
|
// "status":1
|
|
// },
|
|
// "timestamp":1660685915746
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var address interface{} = this.SafeString(data, "address")
|
|
var tag interface{} = this.SafeString(data, "addressTag", "")
|
|
if IsTrue(IsEqual(GetLength(tag), 0)) {
|
|
tag = nil
|
|
}
|
|
this.CheckAddress(address)
|
|
|
|
ch <- map[string]interface{} {
|
|
"info": response,
|
|
"currency": code,
|
|
"network": this.SafeString(data, "network"),
|
|
"address": address,
|
|
"tag": tag,
|
|
}
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchDeposits
|
|
* @see https://www.tokocrypto.com/apidocs/#deposit-history-signed
|
|
* @description fetch all deposits made to an account
|
|
* @param {string} code unified currency code
|
|
* @param {int} [since] the earliest time in ms to fetch deposits for
|
|
* @param {int} [limit] the maximum number of deposits structures to retrieve
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @param {int} [params.until] the latest time in ms to fetch deposits for
|
|
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchDeposits(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
code := GetArg(optionalArgs, 0, nil)
|
|
_ = code
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes21928 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes21928)
|
|
var currency interface{} = nil
|
|
var request interface{} = map[string]interface{} {}
|
|
var until interface{} = this.SafeInteger(params, "until")
|
|
if IsTrue(!IsEqual(code, nil)) {
|
|
currency = this.Currency(code)
|
|
AddElementToObject(request, "coin", GetValue(currency, "id"))
|
|
}
|
|
if IsTrue(!IsEqual(since, nil)) {
|
|
AddElementToObject(request, "startTime", since)
|
|
// max 3 months range https://github.com/ccxt/ccxt/issues/6495
|
|
var endTime interface{} = this.Sum(since, 7776000000)
|
|
if IsTrue(!IsEqual(until, nil)) {
|
|
endTime = mathMin(endTime, until)
|
|
}
|
|
AddElementToObject(request, "endTime", endTime)
|
|
}
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit)
|
|
}
|
|
|
|
response:= (<-this.PrivateGetOpenV1Deposits(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code":0,
|
|
// "msg":"Success",
|
|
// "data":{
|
|
// "list":[
|
|
// {
|
|
// "id":5167969,
|
|
// "asset":"BIDR",
|
|
// "network":"BSC",
|
|
// "address":"0x101a925704f6ff13295ab8dd7a60988d116aaedf",
|
|
// "addressTag":"",
|
|
// "txId":"113409337867",
|
|
// "amount":"15000",
|
|
// "transferType":1,
|
|
// "status":1,
|
|
// "insertTime":"1659429390000"
|
|
// },
|
|
// ]
|
|
// },
|
|
// "timestamp":1659758865998
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var deposits interface{} = this.SafeList(data, "list", []interface{}{})
|
|
|
|
ch <- this.ParseTransactions(deposits, currency, since, limit)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#fetchWithdrawals
|
|
* @see https://www.tokocrypto.com/apidocs/#withdraw-signed
|
|
* @description fetch all withdrawals made from an account
|
|
* @param {string} code unified currency code
|
|
* @param {int} [since] the earliest time in ms to fetch withdrawals for
|
|
* @param {int} [limit] the maximum number of withdrawals structures to retrieve
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
*/
|
|
func (this *tokocrypto) FetchWithdrawals(optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
code := GetArg(optionalArgs, 0, nil)
|
|
_ = code
|
|
since := GetArg(optionalArgs, 1, nil)
|
|
_ = since
|
|
limit := GetArg(optionalArgs, 2, nil)
|
|
_ = limit
|
|
params := GetArg(optionalArgs, 3, map[string]interface{} {})
|
|
_ = params
|
|
|
|
retRes22538 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes22538)
|
|
var request interface{} = map[string]interface{} {}
|
|
var currency interface{} = nil
|
|
if IsTrue(!IsEqual(code, nil)) {
|
|
currency = this.Currency(code)
|
|
AddElementToObject(request, "coin", GetValue(currency, "id"))
|
|
}
|
|
if IsTrue(!IsEqual(since, nil)) {
|
|
AddElementToObject(request, "startTime", since)
|
|
// max 3 months range https://github.com/ccxt/ccxt/issues/6495
|
|
AddElementToObject(request, "endTime", this.Sum(since, 7776000000))
|
|
}
|
|
if IsTrue(!IsEqual(limit, nil)) {
|
|
AddElementToObject(request, "limit", limit)
|
|
}
|
|
|
|
response:= (<-this.PrivateGetOpenV1Withdraws(this.Extend(request, params)))
|
|
PanicOnError(response)
|
|
//
|
|
// {
|
|
// "code":0,
|
|
// "msg":"Success",
|
|
// "data":{
|
|
// "list":[
|
|
// {
|
|
// "id":4245859,
|
|
// "clientId":"198",
|
|
// "asset":"BIDR",
|
|
// "network":"BSC",
|
|
// "address":"0xff1c75149cc492e7d5566145b859fcafc900b6e9",
|
|
// "addressTag":"",
|
|
// "amount":"10000",
|
|
// "fee":"0",
|
|
// "txId":"113501794501",
|
|
// "transferType":1,
|
|
// "status":10,
|
|
// "createTime":1659521314413
|
|
// }
|
|
// ]
|
|
// },
|
|
// "timestamp":1659759062187
|
|
// }
|
|
//
|
|
var data interface{} = this.SafeValue(response, "data", map[string]interface{} {})
|
|
var withdrawals interface{} = this.SafeList(data, "list", []interface{}{})
|
|
|
|
ch <- this.ParseTransactions(withdrawals, currency, since, limit)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) ParseTransactionStatusByType(status interface{}, optionalArgs ...interface{}) interface{} {
|
|
typeVar := GetArg(optionalArgs, 0, nil)
|
|
_ = typeVar
|
|
var statusesByType interface{} = map[string]interface{} {
|
|
"deposit": map[string]interface{} {
|
|
"0": "pending",
|
|
"1": "ok",
|
|
},
|
|
"withdrawal": map[string]interface{} {
|
|
"0": "pending",
|
|
"1": "canceled",
|
|
"2": "pending",
|
|
"3": "failed",
|
|
"4": "pending",
|
|
"5": "failed",
|
|
"10": "ok",
|
|
},
|
|
}
|
|
var statuses interface{} = this.SafeValue(statusesByType, typeVar, map[string]interface{} {})
|
|
return this.SafeString(statuses, status, status)
|
|
}
|
|
func (this *tokocrypto) ParseTransaction(transaction interface{}, optionalArgs ...interface{}) interface{} {
|
|
//
|
|
// fetchDeposits
|
|
//
|
|
// {
|
|
// "id": 5167969,
|
|
// "asset": "BIDR",
|
|
// "network": "BSC",
|
|
// "address": "0x101a925704f6ff13295ab8dd7a60988d116aaedf",
|
|
// "addressTag": "",
|
|
// "txId": "113409337867",
|
|
// "amount": "15000",
|
|
// "transferType": 1,
|
|
// "status": 1,
|
|
// "insertTime": "1659429390000"
|
|
// }
|
|
//
|
|
// fetchWithdrawals
|
|
//
|
|
// {
|
|
// "id": 4245859,
|
|
// "clientId": "198",
|
|
// "asset": "BIDR",
|
|
// "network": "BSC",
|
|
// "address": "0xff1c75149cc492e7d5566145b859fcafc900b6e9",
|
|
// "addressTag": "",
|
|
// "amount": "10000",
|
|
// "fee": "0",
|
|
// "txId": "113501794501",
|
|
// "transferType": 1,
|
|
// "status": 10,
|
|
// "createTime": 1659521314413
|
|
// }
|
|
//
|
|
// withdraw
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "成功",
|
|
// "data": {
|
|
// "withdrawId":"12"
|
|
// },
|
|
// "timestamp": 1571745049095
|
|
// }
|
|
//
|
|
currency := GetArg(optionalArgs, 0, nil)
|
|
_ = currency
|
|
var address interface{} = this.SafeString(transaction, "address")
|
|
var tag interface{} = this.SafeString(transaction, "addressTag") // set but unused
|
|
if IsTrue(!IsEqual(tag, nil)) {
|
|
if IsTrue(IsLessThan(GetLength(tag), 1)) {
|
|
tag = nil
|
|
}
|
|
}
|
|
var txid interface{} = this.SafeString(transaction, "txId")
|
|
if IsTrue(IsTrue((!IsEqual(txid, nil))) && IsTrue((IsGreaterThanOrEqual(GetIndexOf(txid, "Internal transfer "), 0)))) {
|
|
txid = Slice(txid, 18, nil)
|
|
}
|
|
var currencyId interface{} = this.SafeString2(transaction, "coin", "fiatCurrency")
|
|
var code interface{} = this.SafeCurrencyCode(currencyId, currency)
|
|
var timestamp interface{} = nil
|
|
var insertTime interface{} = this.SafeInteger(transaction, "insertTime")
|
|
var createTime interface{} = this.SafeInteger2(transaction, "createTime", "timestamp")
|
|
var typeVar interface{} = this.SafeString(transaction, "type")
|
|
if IsTrue(IsEqual(typeVar, nil)) {
|
|
if IsTrue(IsTrue((!IsEqual(insertTime, nil))) && IsTrue((IsEqual(createTime, nil)))) {
|
|
typeVar = "deposit"
|
|
timestamp = insertTime
|
|
} else if IsTrue(IsTrue((IsEqual(insertTime, nil))) && IsTrue((!IsEqual(createTime, nil)))) {
|
|
typeVar = "withdrawal"
|
|
timestamp = createTime
|
|
}
|
|
}
|
|
var feeCost interface{} = this.SafeNumber2(transaction, "transactionFee", "totalFee")
|
|
var fee interface{} = map[string]interface{} {
|
|
"currency": nil,
|
|
"cost": nil,
|
|
"rate": nil,
|
|
}
|
|
if IsTrue(!IsEqual(feeCost, nil)) {
|
|
AddElementToObject(fee, "currency", code)
|
|
AddElementToObject(fee, "cost", feeCost)
|
|
}
|
|
var internalRaw interface{} = this.SafeInteger(transaction, "transferType")
|
|
var internal interface{} = false
|
|
if IsTrue(!IsEqual(internalRaw, nil)) {
|
|
internal = true
|
|
}
|
|
var id interface{} = this.SafeString(transaction, "id")
|
|
if IsTrue(IsEqual(id, nil)) {
|
|
var data interface{} = this.SafeValue(transaction, "data", map[string]interface{} {})
|
|
id = this.SafeString(data, "withdrawId")
|
|
typeVar = "withdrawal"
|
|
}
|
|
return map[string]interface{} {
|
|
"info": transaction,
|
|
"id": id,
|
|
"txid": txid,
|
|
"type": typeVar,
|
|
"currency": code,
|
|
"network": this.SafeString(transaction, "network"),
|
|
"amount": this.SafeNumber(transaction, "amount"),
|
|
"status": this.ParseTransactionStatusByType(this.SafeString(transaction, "status"), typeVar),
|
|
"timestamp": timestamp,
|
|
"datetime": this.Iso8601(timestamp),
|
|
"address": address,
|
|
"addressFrom": nil,
|
|
"addressTo": address,
|
|
"tag": tag,
|
|
"tagFrom": nil,
|
|
"tagTo": tag,
|
|
"updated": this.SafeInteger2(transaction, "successTime", "updateTime"),
|
|
"comment": nil,
|
|
"internal": internal,
|
|
"fee": fee,
|
|
}
|
|
}
|
|
/**
|
|
* @method
|
|
* @name tokocrypto#withdraw
|
|
* @see https://www.tokocrypto.com/apidocs/#withdraw-signed
|
|
* @description make a withdrawal
|
|
* @param {string} code unified currency code
|
|
* @param {float} amount the amount to withdraw
|
|
* @param {string} address the address to withdraw to
|
|
* @param {string} tag
|
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
*/
|
|
func (this *tokocrypto) Withdraw(code interface{}, amount interface{}, address interface{}, optionalArgs ...interface{}) <- chan interface{} {
|
|
ch := make(chan interface{})
|
|
go func() interface{} {
|
|
defer close(ch)
|
|
defer ReturnPanicError(ch)
|
|
tag := GetArg(optionalArgs, 0, nil)
|
|
_ = tag
|
|
params := GetArg(optionalArgs, 1, map[string]interface{} {})
|
|
_ = params
|
|
tagparamsVariable := this.HandleWithdrawTagAndParams(tag, params);
|
|
tag = GetValue(tagparamsVariable,0);
|
|
params = GetValue(tagparamsVariable,1)
|
|
|
|
retRes24498 := (<-this.LoadMarkets())
|
|
PanicOnError(retRes24498)
|
|
this.CheckAddress(address)
|
|
var currency interface{} = this.Currency(code)
|
|
var request interface{} = map[string]interface{} {
|
|
"asset": GetValue(currency, "id"),
|
|
"address": address,
|
|
"amount": this.NumberToString(amount),
|
|
}
|
|
if IsTrue(!IsEqual(tag, nil)) {
|
|
AddElementToObject(request, "addressTag", tag)
|
|
}
|
|
networkCodequeryVariable := this.HandleNetworkCodeAndParams(params);
|
|
networkCode := GetValue(networkCodequeryVariable,0);
|
|
query := GetValue(networkCodequeryVariable,1)
|
|
var networkId interface{} = this.NetworkCodeToId(networkCode)
|
|
if IsTrue(!IsEqual(networkId, nil)) {
|
|
AddElementToObject(request, "network", ToUpper(networkId))
|
|
}
|
|
|
|
response:= (<-this.PrivatePostOpenV1Withdraws(this.Extend(request, query)))
|
|
PanicOnError(response)
|
|
|
|
//
|
|
// {
|
|
// "code": 0,
|
|
// "msg": "成功",
|
|
// "data": {
|
|
// "withdrawId":"12"
|
|
// },
|
|
// "timestamp": 1571745049095
|
|
// }
|
|
//
|
|
ch <- this.ParseTransaction(response, currency)
|
|
return nil
|
|
|
|
}()
|
|
return ch
|
|
}
|
|
func (this *tokocrypto) Sign(path interface{}, optionalArgs ...interface{}) interface{} {
|
|
api := GetArg(optionalArgs, 0, "public")
|
|
_ = api
|
|
method := GetArg(optionalArgs, 1, "GET")
|
|
_ = method
|
|
params := GetArg(optionalArgs, 2, map[string]interface{} {})
|
|
_ = params
|
|
headers := GetArg(optionalArgs, 3, nil)
|
|
_ = headers
|
|
body := GetArg(optionalArgs, 4, nil)
|
|
_ = body
|
|
if !IsTrue((InOp(GetValue(GetValue(this.Urls, "api"), "rest"), api))) {
|
|
panic(NotSupported(Add(Add(Add(this.Id, " does not have a testnet/sandbox URL for "), api), " endpoints")))
|
|
}
|
|
var url interface{} = GetValue(GetValue(GetValue(this.Urls, "api"), "rest"), api)
|
|
url = Add(url, Add("/", path))
|
|
if IsTrue(IsEqual(api, "wapi")) {
|
|
url = Add(url, ".html")
|
|
}
|
|
var userDataStream interface{} = IsTrue((IsEqual(path, "userDataStream"))) || IsTrue((IsEqual(path, "listenKey")))
|
|
if IsTrue(userDataStream) {
|
|
if IsTrue(this.ApiKey) {
|
|
// v1 special case for userDataStream
|
|
headers = map[string]interface{} {
|
|
"X-MBX-APIKEY": this.ApiKey,
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
}
|
|
if IsTrue(!IsEqual(method, "GET")) {
|
|
body = this.Urlencode(params)
|
|
}
|
|
} else {
|
|
panic(AuthenticationError(Add(this.Id, " userDataStream endpoint requires `apiKey` credential")))
|
|
}
|
|
} else if IsTrue(IsTrue(IsTrue(IsTrue(IsTrue(IsTrue(IsTrue(IsTrue((IsEqual(api, "private"))) || IsTrue((IsTrue(IsEqual(api, "sapi")) && IsTrue(!IsEqual(path, "system/status"))))) || IsTrue((IsEqual(api, "sapiV3")))) || IsTrue((IsTrue(IsEqual(api, "wapi")) && IsTrue(!IsEqual(path, "systemStatus"))))) || IsTrue((IsEqual(api, "dapiPrivate")))) || IsTrue((IsEqual(api, "dapiPrivateV2")))) || IsTrue((IsEqual(api, "fapiPrivate")))) || IsTrue((IsEqual(api, "fapiPrivateV2")))) {
|
|
this.CheckRequiredCredentials()
|
|
var query interface{} = nil
|
|
var defaultRecvWindow interface{} = this.SafeInteger(this.Options, "recvWindow")
|
|
var extendedParams interface{} = this.Extend(map[string]interface{} {
|
|
"timestamp": this.Nonce(),
|
|
}, params)
|
|
if IsTrue(!IsEqual(defaultRecvWindow, nil)) {
|
|
AddElementToObject(extendedParams, "recvWindow", defaultRecvWindow)
|
|
}
|
|
var recvWindow interface{} = this.SafeInteger(params, "recvWindow")
|
|
if IsTrue(!IsEqual(recvWindow, nil)) {
|
|
AddElementToObject(extendedParams, "recvWindow", recvWindow)
|
|
}
|
|
if IsTrue(IsTrue((IsEqual(api, "sapi"))) && IsTrue((IsEqual(path, "asset/dust")))) {
|
|
query = this.UrlencodeWithArrayRepeat(extendedParams)
|
|
} else if IsTrue(IsTrue(IsTrue(IsTrue((IsEqual(path, "batchOrders"))) || IsTrue((IsGreaterThanOrEqual(GetIndexOf(path, "sub-account"), 0)))) || IsTrue((IsEqual(path, "capital/withdraw/apply")))) || IsTrue((IsGreaterThanOrEqual(GetIndexOf(path, "staking"), 0)))) {
|
|
query = this.Rawencode(extendedParams)
|
|
} else {
|
|
query = this.Urlencode(extendedParams)
|
|
}
|
|
var signature interface{} = this.Hmac(this.Encode(query), this.Encode(this.Secret), sha256)
|
|
query = Add(query, Add(Add("&", "signature="), signature))
|
|
headers = map[string]interface{} {
|
|
"X-MBX-APIKEY": this.ApiKey,
|
|
}
|
|
if IsTrue(IsTrue(IsTrue((IsEqual(method, "GET"))) || IsTrue((IsEqual(method, "DELETE")))) || IsTrue((IsEqual(api, "wapi")))) {
|
|
url = Add(url, Add("?", query))
|
|
} else {
|
|
body = query
|
|
AddElementToObject(headers, "Content-Type", "application/x-www-form-urlencoded")
|
|
}
|
|
} else {
|
|
if IsTrue(GetArrayLength(ObjectKeys(params))) {
|
|
url = Add(url, Add("?", this.Urlencode(params)))
|
|
}
|
|
}
|
|
return map[string]interface{} {
|
|
"url": url,
|
|
"method": method,
|
|
"body": body,
|
|
"headers": headers,
|
|
}
|
|
}
|
|
func (this *tokocrypto) HandleErrors(code interface{}, reason interface{}, url interface{}, method interface{}, headers interface{}, body interface{}, response interface{}, requestHeaders interface{}, requestBody interface{}) interface{} {
|
|
if IsTrue(IsTrue((IsEqual(code, 418))) || IsTrue((IsEqual(code, 429)))) {
|
|
panic(DDoSProtection(Add(Add(Add(Add(Add(Add(this.Id, " "), ToString(code)), " "), reason), " "), body)))
|
|
}
|
|
// error response in a form: { "code": -1013, "msg": "Invalid quantity." }
|
|
// following block cointains legacy checks against message patterns in "msg" property
|
|
// will switch "code" checks eventually, when we know all of them
|
|
if IsTrue(IsGreaterThanOrEqual(code, 400)) {
|
|
if IsTrue(IsGreaterThanOrEqual(GetIndexOf(body, "Price * QTY is zero or less"), 0)) {
|
|
panic(InvalidOrder(Add(Add(this.Id, " order cost = amount * price is zero or less "), body)))
|
|
}
|
|
if IsTrue(IsGreaterThanOrEqual(GetIndexOf(body, "LOT_SIZE"), 0)) {
|
|
panic(InvalidOrder(Add(Add(this.Id, " order amount should be evenly divisible by lot size "), body)))
|
|
}
|
|
if IsTrue(IsGreaterThanOrEqual(GetIndexOf(body, "PRICE_FILTER"), 0)) {
|
|
panic(InvalidOrder(Add(Add(this.Id, " order price is invalid, i.e. exceeds allowed price precision, exceeds min price or max price limits or is invalid value in general, use this.priceToPrecision (symbol, amount) "), body)))
|
|
}
|
|
}
|
|
if IsTrue(IsEqual(response, nil)) {
|
|
return nil // fallback to default error handler
|
|
}
|
|
// check success value for wapi endpoints
|
|
// response in format {'msg': 'The coin does not exist.', 'success': true/false}
|
|
var success interface{} = this.SafeBool(response, "success", true)
|
|
if !IsTrue(success) {
|
|
var messageInner interface{} = this.SafeString(response, "msg")
|
|
var parsedMessage interface{} = nil
|
|
if IsTrue(!IsEqual(messageInner, nil)) {
|
|
|
|
{ ret__ := func(this *tokocrypto) (ret_ interface{}) {
|
|
defer func() {
|
|
if e := recover(); e != nil {
|
|
if e == "break" {
|
|
return
|
|
}
|
|
ret_ = func(this *tokocrypto) interface{} {
|
|
// catch block:
|
|
// do nothing
|
|
parsedMessage = nil
|
|
return nil
|
|
}(this)
|
|
}
|
|
}()
|
|
// try block:
|
|
parsedMessage = JsonParse(messageInner)
|
|
return nil
|
|
}(this)
|
|
if ret__ != nil {
|
|
return ret__
|
|
}
|
|
}
|
|
if IsTrue(!IsEqual(parsedMessage, nil)) {
|
|
response = parsedMessage
|
|
}
|
|
}
|
|
}
|
|
var message interface{} = this.SafeString(response, "msg")
|
|
if IsTrue(!IsEqual(message, nil)) {
|
|
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), message, Add(Add(this.Id, " "), message))
|
|
this.ThrowBroadlyMatchedException(GetValue(this.Exceptions, "broad"), message, Add(Add(this.Id, " "), message))
|
|
}
|
|
// checks against error codes
|
|
var error interface{} = this.SafeString(response, "code")
|
|
if IsTrue(!IsEqual(error, nil)) {
|
|
// https://github.com/ccxt/ccxt/issues/6501
|
|
// https://github.com/ccxt/ccxt/issues/7742
|
|
if IsTrue(IsTrue((IsEqual(error, "200"))) || IsTrue(Precise.StringEquals(error, "0"))) {
|
|
return nil
|
|
}
|
|
// a workaround for {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
|
|
// despite that their message is very confusing, it is raised by Binance
|
|
// on a temporary ban, the API key is valid, but disabled for a while
|
|
if IsTrue(IsTrue((IsEqual(error, "-2015"))) && IsTrue(GetValue(this.Options, "hasAlreadyAuthenticatedSuccessfully"))) {
|
|
panic(DDoSProtection(Add(Add(this.Id, " "), body)))
|
|
}
|
|
var feedback interface{} = Add(Add(this.Id, " "), body)
|
|
if IsTrue(IsEqual(message, "No need to change margin type.")) {
|
|
panic(MarginModeAlreadySet(feedback))
|
|
}
|
|
this.ThrowExactlyMatchedException(GetValue(this.Exceptions, "exact"), error, feedback)
|
|
panic(ExchangeError(feedback))
|
|
}
|
|
if !IsTrue(success) {
|
|
panic(ExchangeError(Add(Add(this.Id, " "), body)))
|
|
}
|
|
return nil
|
|
}
|
|
func (this *tokocrypto) CalculateRateLimiterCost(api interface{}, method interface{}, path interface{}, params interface{}, optionalArgs ...interface{}) interface{} {
|
|
config := GetArg(optionalArgs, 0, map[string]interface{} {})
|
|
_ = config
|
|
if IsTrue(IsTrue((InOp(config, "noCoin"))) && !IsTrue((InOp(params, "coin")))) {
|
|
return GetValue(config, "noCoin")
|
|
} else if IsTrue(IsTrue((InOp(config, "noSymbol"))) && !IsTrue((InOp(params, "symbol")))) {
|
|
return GetValue(config, "noSymbol")
|
|
} else if IsTrue(IsTrue((InOp(config, "noPoolId"))) && !IsTrue((InOp(params, "poolId")))) {
|
|
return GetValue(config, "noPoolId")
|
|
} else if IsTrue(IsTrue((InOp(config, "byLimit"))) && IsTrue((InOp(params, "limit")))) {
|
|
var limit interface{} = GetValue(params, "limit")
|
|
var byLimit interface{} = GetValue(config, "byLimit")
|
|
for i := 0; IsLessThan(i, GetArrayLength(byLimit)); i++ {
|
|
var entry interface{} = GetValue(byLimit, i)
|
|
if IsTrue(IsLessThanOrEqual(limit, GetValue(entry, 0))) {
|
|
return GetValue(entry, 1)
|
|
}
|
|
}
|
|
}
|
|
return this.SafeInteger(config, "cost", 1)
|
|
}
|
|
|
|
|
|
func (this *tokocrypto) Init(userConfig map[string]interface{}) {
|
|
this.Exchange = Exchange{}
|
|
this.Exchange.InitParent(userConfig, this.Describe().(map[string]interface{}), this)
|
|
this.Exchange.DerivedExchange = this
|
|
}
|