public static async Task Verify([QueueTrigger("verify")] string msg, ILogger log) { if (String.IsNullOrWhiteSpace(msg)) { log.LogError("Empty request received."); } var parts = msg.Split(","); if (parts.Length != 2) { log.LogError("Invalid request received."); } var daemonURL = ConfigurationProvider.GetSetting("DaemonURL"); var daemonCredential = ConfigurationProvider.GetSetting("DaemonCredential"); var client = new Web3(url: daemonURL, authenticationHeader: new AuthenticationHeaderValue("basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(daemonCredential)))); var table = CloudStorage.GetTable <Transaction>(); var transaction = await table.RetrieveAsync <Transaction>(parts[0], parts[1]); var receipt = await client.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(transaction.RowKey); if (receipt != null && receipt.Status.Value == 1) { if (receipt.Status.Value == 1) { log.LogInformation("Transaction {0} has been verified in success state.", transaction.RowKey); transaction.Confirmed = true; await table.ReplaceAsync(new[] { transaction }); } else { var errormsg = $"Transaction {transaction.RowKey} has not yet been verified."; log.LogInformation(errormsg); throw new ApplicationException(errormsg); } } }
public static async Task Distribute([BlobTrigger("airdrop/{name}")] Stream myBlob, string name, ILogger log) { //reads distribution addresses and amount line by line from the CSV file input var distributions = ReadLines(myBlob, Encoding.UTF8); var requests = new List <AirdropRequest>(); foreach (var distribution in distributions) { //ignores any empty line if (String.IsNullOrWhiteSpace(distribution)) { continue; } //treats the first parts of lines seperated by comma as distribution addresses, the second as amount var parts = distribution.Split(','); if (parts.Length != 4 || !parts[0].Trim().StartsWith("0x") || !Double.TryParse(parts[1], out var amount) || !parts[2].Trim().StartsWith("0x") || parts[3].Trim().StartsWith("0x")) { log.LogDebug("Invalid distribution found: {0}", distribution); continue; } requests.Add(new AirdropRequest { Amount = amount, Contract = parts[2].Trim(), From = parts[3].Trim(), To = parts[0].Trim(), Reference = name }); } var daemonURL = ConfigurationProvider.GetSetting("DaemonURL"); var daemonCredential = ConfigurationProvider.GetSetting("DaemonCredential"); var froms = requests.GroupBy(r => r.From).Select(g => g.Key).Distinct(); var nonces = new Dictionary <string, long>(); foreach (var from in froms) { var account = new Account(from); var client = new Web3(new Account(from), url: daemonURL, authenticationHeader: new AuthenticationHeaderValue("basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(daemonCredential)))); var nonce = await client.Eth.Transactions.GetTransactionCount.SendRequestAsync(account.Address); nonces.Add(from, (long)nonce.Value); } var queue = CloudStorage.GetQueue("airdrop"); foreach (var request in requests) { request.Nonce = nonces[request.From]; var msg = JsonConvert.SerializeObject(request); await queue.AddMessageAsync(new CloudQueueMessage(msg)); nonces[request.From] = request.Nonce + 1; } }
public static async Task Airdrop([QueueTrigger("airdrop")] string msg, ILogger log) { var request = JsonConvert.DeserializeObject <AirdropRequest>(msg); var daemonURL = ConfigurationProvider.GetSetting("DaemonURL"); var daemonCredential = ConfigurationProvider.GetSetting("DaemonCredential"); //the real transactional amount needs to be multiplied by the decimals of Relex Token var amountInWei = request.Amount * (long)Math.Pow(10, ERC20Decimals); //initialize an Ethereum RPC client and build a standard ERC20 contract for use to interact with var account = new Account(request.From); var client = new Web3(account, url: daemonURL, authenticationHeader: new AuthenticationHeaderValue("basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(daemonCredential)))); //builds and sends token transfering request //standard ERC20 tokens can be transfered by calling the 'transfer' method defined in their contract var transferHandler = client.Eth.GetContractTransactionHandler <TransferFunction>(); var transfer = new TransferFunction() { To = request.To, TokenAmount = new BigInteger(amountInWei), Nonce = request.Nonce }; log.LogInformation($"Sending {request.Amount} tokens({request.Contract}) to {request.To}... "); await transferHandler.SendRequestAsync(request.Contract, transfer); var receipt = await transferHandler.SendRequestAndWaitForReceiptAsync(request.Contract, transfer); if (receipt == null || (receipt.HasErrors().HasValue&& receipt.HasErrors().Value)) { log.LogError("Failed."); throw new ApplicationException("Failed in processing airdrop request."); } else if (receipt.HasErrors().HasValue&& receipt.HasErrors().Value) { log.LogError($"Failed with status code: {(int)receipt.Status.Value}"); var errormsg = receipt.Logs.ToString(); log.LogError(errormsg); throw new ApplicationException(errormsg); } else { var transaction = new Transaction { Amount = request.Amount, Confirmed = false, Contract = request.Contract, Creation = DateTimeOffset.UtcNow, From = request.From, PartitionKey = request.To, RowKey = receipt.TransactionHash, Reference = request.Reference, Gas = (int)receipt.GasUsed.Value }; log.LogInformation($"Done. Transaction hash: {receipt.TransactionHash}."); await CloudStorage.GetTable <Transaction>().InsertAsync(new[] { transaction }); await CloudStorage.GetQueue("verify").AddMessageAsync(new CloudQueueMessage($"{transaction.PartitionKey},{transaction.RowKey}")); } }
public static CloudStorageAccount GetAccount() => CloudStorageAccount.Parse(ConfigurationProvider.GetSetting("AzureWebJobsStorage"));