public static async Task <GetBalancesResponse> GetBalances() { //Get nonce: TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); double timeUnix = t.TotalSeconds; //Form request Uri: HttpRequestMessage mesg = new HttpRequestMessage() { RequestUri = new Uri("account/getbalances?apikey=" + API_KEY + "&nonce=" + timeUnix, UriKind.Relative), Method = HttpMethod.Get }; //Compute Signature and add to request header: string sign = GetSignature(new Uri(client.BaseAddress, mesg.RequestUri)); mesg.Headers.Add("apisign", sign); //SendAsync request and await response object: GetBalancesResponse balancesResponse = null; HttpResponseMessage response = await client.SendAsync(mesg); if (response.IsSuccessStatusCode) { balancesResponse = await response.Content.ReadAsAsync <GetBalancesResponse>(); } return(balancesResponse); }
private async Task <GetBalancesResponse> RefreshBalancesAsync() { using var activity = MyTelemetry.StartActivity("Load balance info"); var data = await _restApi.GetBalancesAsync(); if (data.Success) { _response = new GetBalancesResponse() { Balances = data.Result.Select(e => new ExchangeBalance() { Symbol = e.Coin, Balance = e.Total, Free = e.Free }).ToList() }; _lastUpdate = DateTime.UtcNow; } else { throw new Exception($"Cannot get balance, error: {data.Error}"); } _response.AddToActivityAsJsonTag("balance"); _logger.LogDebug("Balance refreshed"); return(_response); }
public void shouldGetBalances() { GetBalancesResponse res = iotaApi.GetBalances(new[] { TEST_ADDRESS_WITH_CHECKSUM }.ToList(), 100); Assert.IsNotNull(res.Balances); Assert.IsNotNull(res.Milestone); Assert.IsNotNull(res.MilestoneIndex); }
public static List <WalletBalance> BittrexToWalletBalances(GetBalancesResponse response) { var walletBalances = new List <WalletBalance>(); foreach (var wallet in response) { if (wallet.Balance > 0) { var walletBalance = Mapper.Map <WalletBalance>(wallet); walletBalance.Exchange = Constants.Bittrex; walletBalances.Add(walletBalance); } } return(walletBalances); }
/// <summary> /// Gets the balances of the specified addresses and calculates the total balance till the threshold is reached. /// </summary> /// <param name="addresses">addresses</param> /// <param name="start">start index</param> /// <param name="threshold">the threshold </param> /// <returns>an Inputs object</returns> /// <exception cref="NotEnoughBalanceException">is thrown if threshold exceeds the sum of balance of the specified addresses</exception> private Inputs GetBalanceAndFormat(string[] addresses, int start, long threshold = 100) { GetBalancesResponse getBalancesResponse = GetBalances(addresses.ToList(), 100); List <long> balances = getBalancesResponse.Balances; Inputs inputs = new Inputs() { InputsList = new List <Input>(), TotalBalance = 0 }; bool threshholdReached = false; for (int i = 0; i < addresses.Length; i++) { if (balances[i] > 0) { inputs.InputsList.Add(new Input() { Address = addresses[i], Balance = balances[i], KeyIndex = start + i }); inputs.TotalBalance += balances[i]; if (inputs.TotalBalance >= threshold) { threshholdReached = true; break; } } } if (threshholdReached) { return(inputs); } throw new NotEnoughBalanceException(); }
public GetBalancesResponse GetBalances(GetBalancesRequest request, IAuthContext authContext) { var balanceRepo = _unitOfWork.GetRepository <Balance>(); var balances = balanceRepo.GetList(x => x.AccountId.ToString() == request.AccountId); GetBalancesResponse response = new GetBalancesResponse(); response.Items = new List <GetBalancesResponseItem>(); foreach (Balance blc in balances) { response.Items.Add(new GetBalancesResponseItem() { Amount = blc.Amount, BalanceType = BalanceType.GetInstance(blc.BalanceType).Text, Currency = CurrencyType.GetInstance(blc.CurrencyType).Text }); } return(response); }
/// <summary> /// /// </summary> /// <param name="securitySum"></param> /// <param name="inputAddress"></param> /// <param name="remainderAddress"></param> /// <param name="transfers"></param> /// <param name="testMode"></param> /// <returns></returns> public List <Transaction> InitiateTransfer( int securitySum, string inputAddress, string remainderAddress, List <Transfer> transfers, bool testMode) { // validate input address if (!InputValidator.IsAddress(inputAddress)) { throw new ArgumentException("Invalid addresses provided."); } // validate remainder address if (remainderAddress != null && !InputValidator.IsAddress(remainderAddress)) { throw new ArgumentException("Invalid addresses provided."); } // Input validation of transfers object if (!InputValidator.IsTransfersCollectionValid(transfers)) { throw new ArgumentException("Invalid transfers provided."); } // Create a new bundle Bundle bundle = new Bundle(); long totalValue = 0; List <String> signatureFragments = new List <string>(); String tag = ""; // // Iterate over all transfers, get totalValue // and prepare the signatureFragments, message and tag foreach (Transfer transfer in transfers) { // remove the checksum of the address if provided if (transfer.Address.IsValidChecksum()) { transfer.Address = transfer.Address.RemoveChecksum(); } int signatureMessageLength = 1; // If message longer than 2187 trytes, increase signatureMessageLength (add next transaction) if (transfer.Message.Length > Constants.MessageLength) { // Get total length, message / maxLength (2187 trytes) signatureMessageLength += (int)Math.Floor((double)transfer.Message.Length / Constants.MessageLength); String msgCopy = transfer.Message; // While there is still a message, copy it while (!string.IsNullOrEmpty(msgCopy)) { string fragment = msgCopy.Substring(0, Constants.MessageLength); msgCopy = msgCopy.Substring(Constants.MessageLength, msgCopy.Length - Constants.MessageLength); // Pad remainder of fragment fragment = fragment.PadRight(Constants.MessageLength, '9'); signatureFragments.Add(fragment); } } else { // Else, get single fragment with 2187 of 9's trytes String fragment = transfer.Message; if (transfer.Message.Length < Constants.MessageLength) { fragment = fragment.PadRight(Constants.MessageLength, '9'); } signatureFragments.Add(fragment); } tag = transfer.Tag; // pad for required 27 tryte length if (transfer.Tag.Length < Constants.TagLength) { tag = tag.PadRight(Constants.TagLength, '9'); } // get current timestamp in seconds long timestamp = (long)Math.Floor(GetCurrentTimestampInSeconds()); // Add first entry to the bundle bundle.AddEntry(signatureMessageLength, transfer.Address, transfer.Value, tag, timestamp); // Sum up total value totalValue += transfer.Value; } // Get inputs if we are sending tokens if (totalValue != 0) { GetBalancesResponse balancesResponse = GetBalances(new List <string> { inputAddress }, 100); var balances = balancesResponse.Balances; long totalBalance = 0; foreach (var balance in balances) { totalBalance += balance; } // get current timestamp in seconds long timestamp = (long)Math.Floor(GetCurrentTimestampInSeconds()); // bypass the balance checks during unit testing if (testMode) { totalBalance += 1000; } if (totalBalance > 0) { long toSubtract = 0 - totalBalance; // Add input as bundle entry // Only a single entry, signatures will be added later bundle.AddEntry(securitySum, inputAddress, toSubtract, tag, timestamp); } // Return not enough balance error if (totalValue > totalBalance) { throw new IllegalStateException("Not enough balance."); } // If there is a remainder value // Add extra output to send remaining funds to if (totalBalance > totalValue) { long remainder = totalBalance - totalValue; // Remainder bundle entry if necessary if (remainderAddress == null) { throw new IllegalStateException("No remainder address defined."); } bundle.AddEntry(1, remainderAddress, remainder, tag, timestamp); } bundle.FinalizeBundle(new Curl(CurlMode.CurlP81)); bundle.AddTrytes(signatureFragments); return(bundle.Transactions); } else { throw new System.Exception("Invalid value transfer: the transfer does not require a signature."); } }
/// <summary> /// Main purpose of this function is to get an array of transfer objects as input, and then prepare the transfer by generating the correct bundle, /// as well as choosing and signing the inputs if necessary (if it's a value transfer). The output of this function is an array of the raw transaction data (trytes) /// </summary> /// <param name="seed">81-tryte encoded address of recipient</param> /// <param name="transfers">the transfers to prepare</param> /// <param name="inputs">Optional (default null). The inputs</param> /// <param name="remainderAddress">Optional (default null). if defined, this address will be used for sending the remainder value (of the inputs) to.</param> /// <returns>a list containing the trytes of the new bundle</returns> public List <string> PrepareTransfers(string seed, Transfer[] transfers, List <Input> inputs = null, string remainderAddress = null) { InputValidator.CheckTransferArray(transfers); // Create a new bundle Bundle bundle = new Bundle(); List <string> signatureFragments = new List <string>(); long totalValue = 0; string tag = ""; // // Iterate over all transfers, get totalValue // and prepare the signatureFragments, message and tag // for (int i = 0; i < transfers.Length; i++) { int signatureMessageLength = 1; // If message longer than 2187 trytes, increase signatureMessageLength (add 2nd transaction) if (transfers[i].Message.Length > 2187) { // Get total length, message / maxLength (2187 trytes) signatureMessageLength += (int)Math.Floor(((double)transfers[i].Message.Length / 2187)); var msgCopy = transfers[i].Message; // While there is still a message, copy it while (msgCopy != null) { var fragment = msgCopy.Substring(0, 2187 > msgCopy.Length ? msgCopy.Length : 2187); msgCopy = msgCopy.Substring(2187, msgCopy.Length - 2187); // Pad remainder of fragment for (var j = 0; fragment.Length < 2187; j++) { fragment += '9'; } signatureFragments.Add(fragment); } } else { // Else, get single fragment with 2187 of 9's trytes string fragment = ""; if (transfers[i].Message != null) { fragment = transfers[i].Message.Substring(0, transfers[i].Message.Length < 2187 ? transfers[i].Message.Length : 2187); } for (var j = 0; fragment.Length < 2187; j++) { fragment += '9'; } signatureFragments.Add(fragment); } // get current timestamp in seconds long timestamp = IotaApiUtils.CreateTimeStampNow(); // If no tag defined, get 27 tryte tag. tag = transfers[i].Tag != null ? transfers[i].Tag : "999999999999999999999999999"; // Pad for required 27 tryte length for (var j = 0; tag.Length < 27; j++) { tag += '9'; } // Add first entries to the bundle // Slice the address in case the user provided a checksummed one bundle.AddEntry(signatureMessageLength, transfers[i].Address, transfers[i].Value, tag, timestamp); // Sum up total value totalValue += transfers[i].Value; } // Get inputs if we are sending tokens if (totalValue != 0) { // Case 1: user provided inputs // // Validate the inputs by calling getBalances if (inputs != null && inputs.Count > 0) { // Get list if addresses of the provided inputs List <string> inputAddresses = new List <string>(); foreach (var input in inputs) { inputAddresses.Add(input.Address); } GetBalancesResponse balances = GetBalances(inputAddresses, 100); List <Input> confirmedInputs = new List <Input>(); long totalBalance = 0; for (var i = 0; i < balances.Balances.Count; i++) { var thisBalance = balances.Balances[i]; totalBalance += thisBalance; // If input has balance, add it to confirmedInputs if (thisBalance > 0) { var inputEl = inputs[i]; inputEl.Balance = thisBalance; confirmedInputs.Add(inputEl); } } // Return not enough balance error if (totalValue > totalBalance) { throw new NotEnoughBalanceException(totalValue); } return(AddRemainder(seed, confirmedInputs, bundle, tag, totalValue, remainderAddress, signatureFragments)); } // Case 2: Get inputs deterministically // // If no inputs provided, derive the addresses from the seed and // confirm that the inputs exceed the threshold else { List <Input> inputList = GetInputs(seed, 0, 0, (int)totalValue).InputsList; return(AddRemainder(seed, inputList, bundle, tag, totalValue, remainderAddress, signatureFragments)); } } else { // If no input required, don't sign and simply finalize the bundle bundle.FinalizeBundle(curl); bundle.AddTrytes(signatureFragments); List <String> bundleTrytes = new List <string>(); bundle.Transactions.ForEach(tx => bundleTrytes.Add(tx.ToTransactionTrytes())); bundleTrytes.Reverse(); return(bundleTrytes); } }
public ActionResult <GetBalancesResponse> GetBalances([FromQuery] GetBalancesRequest request) { GetBalancesResponse response = _accountDataService.GetBalances(request, _authContext); return(Ok(response)); }
/// <summary> /// /// </summary> /// <param name="seed"></param> /// <param name="security"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="threshold"></param> /// <param name="tips"></param> /// <returns></returns> public GetBalancesAndFormatResponse GetInputs(string seed, int security, int start, int end, long threshold, params string[] tips) { // validate the seed if (!InputValidator.IsValidSeed(seed)) { throw new IllegalStateException(Constants.INVALID_SEED_INPUT_ERROR); } seed = InputValidator.PadSeedIfNecessary(seed); if (!InputValidator.IsValidSecurityLevel(security)) { throw new ArgumentException(Constants.INVALID_SECURITY_LEVEL_INPUT_ERROR); } // If start value bigger than end, return error if (start > end) { throw new ArgumentException("start must be smaller than end", nameof(start)); } // or if difference between end and start is bigger than 500 keys if (end - start > 500) { throw new ArgumentException("total number of keys exceeded 500"); } Stopwatch stopwatch = Stopwatch.StartNew(); // Case 1: start and end // // If start and end is defined by the user, simply iterate through the keys // and call getBalances if (end != 0) { var allAddresses = new string[end - start]; for (var i = start; i < end; i++) { var address = IotaApiUtils.NewAddress(seed, security, i, true, SpongeFactory.Create(SpongeFactory.Mode.KERL)); allAddresses[i] = address; } return(GetBalanceAndFormat(allAddresses, tips, threshold, start, security, stopwatch)); } { // Case 2: iterate till threshold // // Either start from index: 0 or start (if defined) until threshold is reached. List <Input> allInputs = new List <Input>(); bool thresholdReached = true; long currentTotal = 0; for (int i = start; thresholdReached; i++) { string address = IotaApiUtils.NewAddress(seed, security, i, true, SpongeFactory.Create(SpongeFactory.Mode.KERL)); // Received input, this epoch or previous GetBalancesResponse response = IotaClient.GetBalances(100, new List <string>() { address }, tips.ToList()); var balance = response.Balances[0]; if (balance > 0) { // Is it already spent from? WereAddressesSpentFromResponse wasSpent = IotaClient.WereAddressesSpentFrom(address); if (wasSpent.States.Length > 0 && !wasSpent.States[0]) { // We can use this! allInputs.Add(new Input { Address = address, Balance = balance, KeyIndex = i, Security = security }); currentTotal += balance; if (threshold != 0 && threshold <= currentTotal) { // Stop because we found threshold thresholdReached = false; } } } else { // Check if there was any activity at all FindTransactionsResponse tx = IotaClient.FindTransactionsByAddresses(address); if (tx.Hashes.Count == 0 || i - start > 500) { // Stop because we reached our limit or no activity thresholdReached = false; } } } stopwatch.Stop(); return(new GetBalancesAndFormatResponse(allInputs, currentTotal, stopwatch.ElapsedMilliseconds)); } }