private DataTransaction MapTransaction( string key, EthereumTransactionHash hash, BloxyTokenTransfer summary, EthplorerTransaction transaction) { return(new DataTransaction() { Address = key, Hash = hash, BlockNumber = transaction.BlockNumber, Confirmations = transaction.Confirmations, ConfirmedAt = summary.ConfirmedAt.UtcDateTime, Sender = string.IsNullOrWhiteSpace(transaction.From) ? EthereumAddress.Empty.Address : transaction.From, Recipient = string.IsNullOrWhiteSpace(transaction.To) ? EthereumAddress.Empty.Address : transaction.To, Input = transaction.Input, Gas = transaction.GasUsed, GasLimit = transaction.GasLimit, Eth = transaction.Value, Success = transaction.Success }); }
public async Task <DataTransaction> GetTransactionAsync(Symbol symbol, EthereumTransactionHash hash) { var key = dataKeyProvider.GetKey(symbol); var response = await DynamoDB.GetItemAsync( TableName, new Dictionary <string, AttributeValue>() { [nameof(DataTransaction.Address)] = new AttributeValue(key), [nameof(DataTransaction.Hash)] = new AttributeValue(hash) }, CancellationToken); if (response.HttpStatusCode != HttpStatusCode.OK) { throw new HttpRequestException($"Response code did not indicate success: {response.HttpStatusCode}"); } if (response.Item.Any()) { return(Map(response.Item)); } return(null); }
public async Task <DataOperation> GetOperationAsync(EthereumTransactionHash hash, int order) { var response = await DynamoDB.GetItemAsync( TableName, new Dictionary <string, AttributeValue>() { [nameof(DataOperation.Hash)] = new AttributeValue(hash), [nameof(DataOperation.Order)] = new AttributeValue() { N = order.ToString() } }, CancellationToken); if (response.HttpStatusCode != HttpStatusCode.OK) { throw new HttpRequestException($"Response code did not indicate success: {response.HttpStatusCode}"); } if (response.Item.Any()) { return(Map(response.Item)); } return(null); }
private DataOperation MapOperation(EthereumTransactionHash hash, EthplorerOperation operation, int order) { return(new DataOperation() { Hash = hash, Order = order, Type = operation.Type.ToUpper(), Address = operation.Address, Sender = string.IsNullOrWhiteSpace(operation.From) ? EthereumAddress.Empty.Address : operation.From, Recipient = string.IsNullOrWhiteSpace(operation.To) ? EthereumAddress.Empty.Address : operation.To, Addresses = operation.Addresses, Value = operation.Value, Price = operation.Price, IsEth = operation.IsEth, Priority = operation.Priority, ContractAddress = operation.TokenInfo.ContractAddress, ContractName = operation.TokenInfo.Name, ContractSymbol = operation.TokenInfo.Symbol, ContractDecimals = int.Parse(operation.TokenInfo.Decimals), ContractHolders = operation.TokenInfo.HolderCount, ContractIssuances = operation.TokenInfo.IssuanceCount, ContractLink = operation.TokenInfo.WebsiteUri }); }
private async Task SyncTransactionsAsync( IEthplorerClient ethplorerClient, IBloxyClient bloxyClient, ITransactionRepository transactionService, IOperationRepository operationService, EthereumAddress contractAddress, DateTime startDate, DateTime endDate) { Console.WriteLine($"[{contractAddress}] Processing Batch: {startDate} -> {endDate}"); await foreach (var transactionSummary in bloxyClient.ListTransactionsAsync(contractAddress, startDate, endDate)) { var hash = new EthereumTransactionHash(transactionSummary.Hash); var transaction = await ethplorerClient.GetTransactionAsync(hash); if (transaction != null) { Console.WriteLine($"[{contractAddress}] Discovering Hash {hash} with ({transaction.Operations.Count}) operations."); var dynamoTransaction = MapTransaction(hash, contractAddress, transactionSummary, transaction); await transactionService.UploadItemsAsync(dynamoTransaction); var dynamoOperations = Enumerable.Range(0, transaction.Operations.Count) .Select(i => MapOperation(hash, transaction.Operations[i], i)) .ToArray(); await operationService.UploadItemsAsync(dynamoOperations); } } Console.WriteLine($"[{contractAddress}] Finished Batch: {startDate} -> {endDate}"); }
public async Task <ApiStakeEvent> GetStake( [Required, FromRoute, EthereumAddress] string address, [Required, FromRoute] Symbol symbol, [Required, FromRoute] Symbol fundSymbol, [Required, FromRoute, TransactionHash] string hash) { var txHash = new EthereumTransactionHash(hash); var stake = await stakeService.GetStakeEventAsync( symbol, GetAddress(address), fundSymbol, txHash); return(MapStakeEvent(stake)); }
public async IAsyncEnumerable <DataOperation> ListOperationsAsync(EthereumTransactionHash hash) { var lastEvaluatedKey = new Dictionary <string, AttributeValue>(); while (!CancellationToken.IsCancellationRequested) { var response = await DynamoDB.QueryAsync( new QueryRequest() { TableName = TableName, Select = Select.ALL_ATTRIBUTES, KeyConditionExpression = string.Format("#{0} = :{0}Val", nameof(DataOperation.Hash)), ExpressionAttributeNames = new Dictionary <string, string>() { [$"#{nameof(DataOperation.Hash)}"] = nameof(DataOperation.Hash), }, ExpressionAttributeValues = new Dictionary <string, AttributeValue>() { [$":{nameof(DataOperation.Hash)}Val"] = new AttributeValue { S = hash }, }, ExclusiveStartKey = lastEvaluatedKey.Any() ? lastEvaluatedKey : null }, CancellationToken); if (response.HttpStatusCode != HttpStatusCode.OK) { throw new HttpRequestException($"Response code did not indicate success: {response.HttpStatusCode}"); } else { lastEvaluatedKey = response.LastEvaluatedKey; } foreach (var attributes in response.Items) { yield return(Map(attributes)); } if (!lastEvaluatedKey.Any()) { break; } } }
public async Task <ITransactionSet> GetTransactionAsync(Symbol symbol, EthereumTransactionHash hash, CurrencyCode currencyCode) { var fundInfo = GetFundInfo(symbol); var transaction = await Transactions.GetTransactionAsync(fundInfo.Symbol, hash) ?? throw new PermanentException($"Transaction not found {hash}"); var transactionSet = MapTransaction <BusinessTransactionSet>(transaction); var operations = await Operations .ListOperationsAsync(hash) .ToListAsync(CancellationToken); transactionSet.Operations = operations .Select(o => MapOperation(o, currencyCode)) .ToList(); return(transactionSet); }
public Task <EthplorerTransaction> GetTransactionAsync(EthereumTransactionHash hash) { return(GetAsync <EthplorerTransaction>($"/getTxInfo/{hash}")); }
public async Task <IStakeEvent> GetStakeEventAsync(Symbol stakeSymbol, EthereumAddress?address, Symbol symbol, EthereumTransactionHash hash) { var fundInfo = GetFundInfo(symbol); var stakeInfo = GetStakeInfo(stakeSymbol); var transaction = await Transactions.GetTransactionAsync(fundInfo.ContractAddress, hash); if (transaction != null) { var stake = transaction.Sender.Equals(stakeInfo.StakingAddress, StringComparison.OrdinalIgnoreCase) ? await GetStakeReleaseAsync(fundInfo, stakeInfo, MapTransaction <BusinessTransaction>(transaction)) : await GetStakeLockupAsync(fundInfo, stakeInfo, MapTransaction <BusinessTransaction>(transaction)) ?? await GetStakeReleaseAsync(fundInfo, stakeInfo, MapTransaction <BusinessTransaction>(transaction)); if (stake != null) { return(stake); } } throw new PermanentException($"No transaction found with hash {hash}{(address.HasValue ? $" for address {address}." : ".")}"); }
public Task <IStakeEvent> GetStakeEventAsync(Symbol stakeSymbol, EthereumAddress address, Symbol symbol, EthereumTransactionHash hash) { return(GetStakeEventAsync(stakeSymbol, new EthereumAddress?(address), symbol, hash)); }
public Task <IStakeEvent> GetStakeEventAsync(Symbol stakeSymbol, Symbol symbol, EthereumTransactionHash hash) { return(GetStakeEventAsync(stakeSymbol, null, symbol, hash)); }
protected BusinessOperation MapOperation(DataOperation operation, CurrencyCode currencyCode) { var sanitisedId = operation.ContractName?.Replace(" ", "-").Replace(".", "-").ToLower().Trim() ?? string.Empty; var isInvictus = Enum.TryParse(operation.ContractSymbol, out Symbol symbol); var assetInfo = GetAssetInfo(operation.ContractSymbol); var coinloreId = assetInfo?.CoinLore ?? sanitisedId; var coinMarketCapId = assetInfo?.CoinMarketCap ?? sanitisedId; var isUSDStableCoin = assetInfo?.IsUSDStableCoin ?? false; var fund = isInvictus && symbol.IsFund() ? GetFundInfo(symbol) : null; var stake = isInvictus && symbol.IsStake() ? GetStakeInfo(symbol) : null; return(new BusinessOperation() { Hash = new EthereumTransactionHash(operation.Hash), Order = operation.Order, Type = operation.Type, Address = string.IsNullOrEmpty(operation.Address) ? default(EthereumAddress?) : new EthereumAddress(operation.Address), Sender = string.IsNullOrEmpty(operation.Sender) ? default(EthereumAddress?) : new EthereumAddress(operation.Sender), Recipient = string.IsNullOrEmpty(operation.Recipient) ? default(EthereumAddress?) : new EthereumAddress(operation.Recipient), Addresses = operation.Addresses .Select(a => new EthereumAddress(a)) .ToList(), IsEth = operation.IsEth, PricePerToken = operation.Price == default && isUSDStableCoin ? CurrencyConverter.Convert(1, currencyCode) : CurrencyConverter.Convert(operation.Price, currencyCode), Quantity = operation.Type == OperationTypes.Transfer ? Web3.Convert.FromWei(BigInteger.Parse(operation.Value), fund?.Decimals ?? stake?.Decimals ?? operation.ContractDecimals) : 0, Value = operation.Value, Priority = operation.Priority, ContractAddress = new EthereumAddress(operation.ContractAddress), ContractSymbol = operation.ContractSymbol, ContractDecimals = operation.ContractDecimals, ContractHolders = operation.ContractHolders, ContractIssuances = operation.ContractIssuances, ContractName = fund?.Name ?? stake?.Name ?? operation.ContractName, ContractLink = fund?.Links?.External ?? stake?.Links?.External ?? (!string.IsNullOrEmpty(operation.ContractLink) ? new Uri(operation.ContractLink, UriKind.Absolute) : new Uri(string.Format(LinkTemplate, coinMarketCapId), UriKind.Absolute)), ContractImageLink = isInvictus ? new Uri($"https://{HostUrl.Host}/resources/{symbol}.png", UriKind.Absolute) : new Uri(string.Format(ImageTemplate, coinloreId), UriKind.Absolute), ContractMarketLink = !string.IsNullOrEmpty(coinloreId) && !symbol.IsStake() && (fund == null || fund.Tradable) ? new Uri(string.Format(MarketTemplate, coinloreId, currencyCode), UriKind.Absolute) : null });