/// <summary>Gets the deposit history for a symbol</summary>
        /// <param name="currency">The symbol to check. May be null.</param>
        /// <returns>Collection of ExchangeTransactions</returns>
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string currencyNotNeeded = null)
        {
            var    transactions = new List <ExchangeTransaction>();
            string url          = "/deposits/closed";
            JToken result       = await MakeJsonRequestAsync <JToken>(url, null, await GetNoncePayloadAsync());

            foreach (JToken token in result)
            {
                var deposit = new ExchangeTransaction
                {
                    Amount         = token["quantity"].ConvertInvariant <decimal>(),
                    Address        = token["cryptoAddress"].ToStringInvariant(),
                    Currency       = token["currencySymbol"].ToStringInvariant(),
                    PaymentId      = token["id"].ToStringInvariant(),
                    BlockchainTxId = token["txId"].ToStringInvariant(),
                    Status         = TransactionStatus.Complete,            // As soon as it shows up in this list it is complete (verified manually)
                };

                DateTime.TryParse(token["updatedAt"].ToStringInvariant(), out DateTime timestamp);
                deposit.Timestamp = timestamp;

                transactions.Add(deposit);
            }

            return(transactions);
        }
        /// <summary>
        /// This returns both Deposit and Withdawl history for the Bank and Trading Accounts. Currently returning everything and not filtering.
        /// There is no support for retrieving by Symbol, so we'll filter that after reteiving all symbols
        /// </summary>
        /// <param name="currency"></param>
        /// <returns></returns>
        protected override async Task<IEnumerable<ExchangeTransaction>> OnGetDepositHistoryAsync(string? currency)
        {
            List<ExchangeTransaction> transactions = new List<ExchangeTransaction>();
            // [ {"id": "6a2fb54d-7466-490c-b3a6-95d8c882f7f7","index": 20400458,"currency": "ETH","amount": "38.616700000000000000000000","fee": "0.000880000000000000000000", "address": "0xfaEF4bE10dDF50B68c220c9ab19381e20B8EEB2B", "hash": "eece4c17994798939cea9f6a72ee12faa55a7ce44860cfb95c7ed71c89522fe8","status": "pending","type": "payout", "createdAt": "2017-05-18T18:05:36.957Z", "updatedAt": "2017-05-18T19:21:05.370Z" }, ... ]
            JToken result = await MakeJsonRequestAsync<JToken>("/account/transactions", null, await GetNoncePayloadAsync());
            if (result != null && result.HasValues)
            {
                foreach (JToken token in result)
                {
                    if (string.IsNullOrWhiteSpace(currency) || token["currency"].ToStringInvariant().Equals(currency))
                    {
                        ExchangeTransaction transaction = new ExchangeTransaction
                        {
                            PaymentId = token["id"].ToStringInvariant(),
                            Currency = token["currency"].ToStringInvariant(),
                            Address = token["address"].ToStringInvariant(),               // Address Tag isn't returned
                            BlockchainTxId = token["hash"].ToStringInvariant(),           // not sure about this
                            Amount = token["amount"].ConvertInvariant<decimal>(),
                            Notes = token["type"].ToStringInvariant(),                    // since no notes are returned, we'll use this to show the transaction type
                            TxFee = token["fee"].ConvertInvariant<decimal>(),
                            Timestamp = token["createdAt"].ToDateTimeInvariant()
                        };

                        string status = token["status"].ToStringInvariant();
                        if (status.Equals("pending")) transaction.Status = TransactionStatus.Processing;
                        else if (status.Equals("success")) transaction.Status = TransactionStatus.Complete;
                        else if (status.Equals("failed")) transaction.Status = TransactionStatus.Failure;
                        else transaction.Status = TransactionStatus.Unknown;

                        transactions.Add(transaction);
                    }
                }
            }
            return transactions;
        }
        /// <summary>Gets the deposit history for a symbol</summary>
        /// <param name="symbol">The symbol to check. Null for all symbols.</param>
        /// <returns>Collection of ExchangeCoinTransfers</returns>
        public override IEnumerable <ExchangeTransaction> GetDepositHistory(string symbol)
        {
            // TODO: API supports searching on status, startTime, endTime
            Dictionary <string, object> payload = GetNoncePayload();

            if (!string.IsNullOrWhiteSpace(symbol))
            {
                payload["asset"] = NormalizeSymbol(symbol);
            }

            JToken response = MakeJsonRequest <JToken>("/depositHistory.html", WithdrawalUrlPrivate, payload);

            CheckError(response);

            var transactions = new List <ExchangeTransaction>();

            foreach (JToken token in response["depositList"])
            {
                var transaction = new ExchangeTransaction
                {
                    TimestampUTC   = token["insertTime"].ConvertInvariant <double>().UnixTimeStampToDateTimeMilliseconds(),
                    Amount         = token["amount"].ConvertInvariant <decimal>(),
                    Symbol         = token["asset"].ToStringUpperInvariant(),
                    Address        = token["address"].ToStringInvariant(),
                    AddressTag     = token["addressTag"].ToStringInvariant(),
                    BlockchainTxId = token["txId"].ToStringInvariant()
                };
                int status = token["status"].ConvertInvariant <int>();
                switch (status)
                {
                case 0:
                    transaction.Status = TransactionStatus.Processing;
                    break;

                case 1:
                    transaction.Status = TransactionStatus.Complete;
                    break;

                default:
                    // If new states are added, see https://github.com/binance-exchange/binance-official-api-docs/blob/master/wapi-api.md
                    transaction.Status = TransactionStatus.Unknown;
                    transaction.Notes  = "Unknown transaction status: " + status;
                    break;
                }

                transactions.Add(transaction);
            }

            return(transactions);
        }
        /// <summary>Gets the deposit history for a symbol</summary>
        /// <param name="currency">The currency to check. Null for all symbols.</param>
        /// <returns>Collection of ExchangeCoinTransfers</returns>
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string currency)
        {
            // TODO: API supports searching on status, startTime, endTime
            Dictionary <string, object> payload = await GetNoncePayloadAsync();

            if (currency.Length != 0)
            {
                payload["asset"] = currency;
            }

            JToken response = await MakeJsonRequestAsync <JToken>("/depositHistory.html", WithdrawalUrlPrivate, payload);

            var transactions = new List <ExchangeTransaction>();

            foreach (JToken token in response["depositList"])
            {
                var transaction = new ExchangeTransaction
                {
                    Timestamp      = token["insertTime"].ConvertInvariant <double>().UnixTimeStampToDateTimeMilliseconds(),
                    Amount         = token["amount"].ConvertInvariant <decimal>(),
                    Currency       = token["asset"].ToStringUpperInvariant(),
                    Address        = token["address"].ToStringInvariant(),
                    AddressTag     = token["addressTag"].ToStringInvariant(),
                    BlockchainTxId = token["txId"].ToStringInvariant()
                };
                int status = token["status"].ConvertInvariant <int>();
                switch (status)
                {
                case 0:
                    transaction.Status = TransactionStatus.Processing;
                    break;

                case 1:
                    transaction.Status = TransactionStatus.Complete;
                    break;

                default:
                    // If new states are added, see https://github.com/binance-exchange/binance-official-api-docs/blob/master/wapi-api.md
                    transaction.Status = TransactionStatus.Unknown;
                    transaction.Notes  = "Unknown transaction status: " + status;
                    break;
                }

                transactions.Add(transaction);
            }

            return(transactions);
        }
        /// <summary>Gets the deposit history for a symbol</summary>
        /// <param name="currency">(ignored) The currency to check.</param>
        /// <returns>Collection of ExchangeCoinTransfers</returns>
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string currency)
        {
            JToken result = await MakePrivateAPIRequestAsync("returnDepositsWithdrawals",
                                                             new object[]
            {
                "start", DateTime.MinValue.ToUniversalTime().UnixTimestampFromDateTimeSeconds(),
                "end", CryptoUtility.UtcNow.UnixTimestampFromDateTimeSeconds()
            });

            var transactions = new List <ExchangeTransaction>();

            foreach (JToken token in result["deposits"])
            {
                var deposit = new ExchangeTransaction
                {
                    Currency       = token["currency"].ToStringUpperInvariant(),
                    Address        = token["address"].ToStringInvariant(),
                    Amount         = token["amount"].ConvertInvariant <decimal>(),
                    BlockchainTxId = token["txid"].ToStringInvariant(),
                    Timestamp      = token["timestamp"].ConvertInvariant <double>().UnixTimeStampToDateTimeSeconds()
                };

                string status = token["status"].ToStringUpperInvariant();
                switch (status)
                {
                case "COMPLETE":
                    deposit.Status = TransactionStatus.Complete;
                    break;

                case "PENDING":
                    deposit.Status = TransactionStatus.Processing;
                    break;

                default:
                    // TODO: API Docs don't specify what other options there will be for transaction status
                    deposit.Status = TransactionStatus.Unknown;
                    deposit.Notes  = "Transaction status: " + status;
                    break;
                }

                transactions.Add(deposit);
            }

            return(transactions);
        }
        /// <summary>
        /// Cryptopia does support filtering by Transaction Type (deposits and withdraws), but here we're returning both. The Tx Type will be returned in the Message field
        /// By Symbol isn't supported, so we'll filter. Also, the default limit is 100 transactions, we could possibly increase this to support the extra data we have to return for Symbol
        /// </summary>
        /// <param name="symbol"></param>
        /// <returns></returns>
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string symbol)
        {
            List <ExchangeTransaction> deposits = new List <ExchangeTransaction>();
            var payload = await GetNoncePayloadAsync();

            symbol = NormalizeSymbol(symbol);

            // Uncomment as desired
            //payload["Type"] = "Deposit";
            //payload["Type"] = "Withdraw";
            //payload["Count"] = 100;

            // [ {"Id": 23467,"Currency": "DOT", "TxId": "6ddbaca454c97ba4e8a87a1cb49fa5ceace80b89eaced84b46a8f52c2b8c8ca3", "Type": "Deposit", "Amount": 145.98000000, "Fee": "0.00000000", "Status": "Confirmed", "Confirmations": "20", "TimeStamp":"2014-12-07T20:04:05.3947572", "Address": "" }, ... ]
            JToken token = await MakeJsonRequestAsync <JToken>("/GetTransactions", null, payload, "POST");

            foreach (JToken data in token)
            {
                if (data["Currency"].ToStringInvariant().Equals(symbol))
                {
                    ExchangeTransaction tx = new ExchangeTransaction()
                    {
                        Address        = data["Address"].ToStringInvariant(),
                        Amount         = data["Amount"].ConvertInvariant <decimal>(),
                        BlockchainTxId = data["TxId"].ToStringInvariant(),
                        Notes          = data["Type"].ToStringInvariant(),
                        PaymentId      = data["Id"].ToStringInvariant(),
                        Timestamp      = data["TimeStamp"].ToDateTimeInvariant(),
                        Symbol         = data["Currency"].ToStringInvariant(),
                        TxFee          = data["Fee"].ConvertInvariant <decimal>()
                    };
                    // They may support more status types, but it's not documented
                    switch ((string)data["Status"])
                    {
                    case "Confirmed": tx.Status = TransactionStatus.Complete; break;

                    case "Pending": tx.Status = TransactionStatus.Processing; break;

                    default: tx.Status = TransactionStatus.Unknown; break;
                    }
                    deposits.Add(tx);
                }
            }
            return(deposits);
        }
        /// <summary>
        /// Cryptopia does support filtering by Transaction Type (deposits and withdraws), but here we're returning both. The Tx Type will be returned in the Message field
        /// By Symbol isn't supported, so we'll filter. Also, the default limit is 100 transactions, we could possibly increase this to support the extra data we have to return for Symbol
        /// </summary>
        /// <param name="symbol"></param>
        /// <returns></returns>
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string symbol)
        {
            var deposits = new List <ExchangeTransaction>();
            var payload  = await GetNoncePayloadAsync();

            // Uncomment as desired
            //payload["Type"] = "Deposit";
            //payload["Type"] = "Withdraw";
            //payload["Count"] = 100;

            var token = await MakeJsonRequestAsync <JToken>("/GetTransactions", null, payload, "POST");

            foreach (var data in token)
            {
                if (data["Currency"].ToStringInvariant().Equals(symbol))
                {
                    var tx = new ExchangeTransaction()
                    {
                        Address        = data["Address"].ToStringInvariant(),
                        Amount         = data["Amount"].ConvertInvariant <decimal>(),
                        BlockchainTxId = data["TxId"].ToStringInvariant(),
                        Notes          = data["Type"].ToStringInvariant(),
                        PaymentId      = data["Id"].ToStringInvariant(),
                        Timestamp      = data["TimeStamp"].ToDateTimeInvariant(),
                        Currency       = data["Currency"].ToStringInvariant(),
                        TxFee          = data["Fee"].ConvertInvariant <decimal>()
                    };
                    // They may support more status types, but it's not documented
                    switch ((string)data["Status"])
                    {
                    case "Confirmed": tx.Status = TransactionStatus.Complete; break;

                    case "Pending": tx.Status = TransactionStatus.Processing; break;

                    default: tx.Status = TransactionStatus.Unknown; break;
                    }
                    deposits.Add(tx);
                }
            }
            return(deposits);
        }
        protected override async Task <IEnumerable <ExchangeTransaction> > OnGetDepositHistoryAsync(string symbol)
        {
            List <ExchangeTransaction> deposits = new List <ExchangeTransaction>();

            var payload = GetNoncePayload();

            payload["limit"] = 1000;

            // History by symbol is not supported, so we'll get max and filter the results
            // response fields = deposit_id currency date amount fee status (awaiting-email-confirmation pending complete) url
            JArray token = await MakeJsonRequestAsync <JArray>("/deposits/history", null, payload, "GET");

            if (token != null && token.HasValues)
            {
                ExchangeTransaction deposit = new ExchangeTransaction()
                {
                    Symbol       = token["currency"].ToStringInvariant(),
                    Amount       = token["amount"].ConvertInvariant <decimal>(),
                    TimestampUTC = token["date"].ConvertInvariant <DateTime>(),
                    PaymentId    = token["deposit_id"].ToStringInvariant(),
                    TxFee        = token["fee"].ConvertInvariant <decimal>()
                };
                switch (token["status"].ToStringInvariant())
                {
                case "complete": deposit.Status = TransactionStatus.Complete; break;

                case "pending": deposit.Status = TransactionStatus.Processing; break;

                default: deposit.Status = TransactionStatus.AwaitingApproval; break;
                }
                if (deposit.Symbol == symbol)
                {
                    deposits.Add(deposit);
                }
            }
            return(deposits);
        }