예제 #1
0
        /// <summary>
        ///    Converts total supply from ethereum format to Lykke's number of coins
        /// </summary>
        /// <param name="token">
        ///    Instance of Erc20Token.
        /// </param>
        /// <returns>
        ///    String instance, that repesents total supply in Lykke's format.
        /// </returns>
        private static string GetNumberOfCoins(Erc20Token token)
        {
            if (string.IsNullOrEmpty(token.TokenTotalSupply))
            {
                return(string.Empty);
            }
            else
            {
                var tokenDecimals = token.TokenDecimals ?? 0;

                if (tokenDecimals == 0)
                {
                    return(token.TokenTotalSupply);
                }

                string numberOfCoins;

                if (tokenDecimals >= token.TokenTotalSupply.Length)
                {
                    numberOfCoins = token.TokenTotalSupply.PadLeft(tokenDecimals + 1, '0');
                    numberOfCoins = numberOfCoins.Insert(numberOfCoins.Length - tokenDecimals, ".");
                }
                else
                {
                    numberOfCoins = token.TokenTotalSupply.Insert(token.TokenTotalSupply.Length - tokenDecimals, ".");
                }

                numberOfCoins = numberOfCoins.TrimEnd('0').TrimEnd('.');

                return(numberOfCoins);
            }
        }
        private async Task ProcessMessageAsync(Erc20ContractCreatedMessage arg)
        {
            _log.Info($"Got Erc20ContractCreatedMessage: {arg.Address} ");

            var token = new Erc20Token
            {
                Address          = arg.Address,
                AssetId          = null,
                BlockHash        = arg.BlockHash,
                BlockTimestamp   = arg.BlockTimestamp,
                DeployerAddress  = arg.DeployerAddress,
                TokenDecimals    = (int?)arg.TokenDecimals,
                TokenName        = arg.TokenName,
                TokenSymbol      = arg.TokenSymbol,
                TokenTotalSupply = arg.TokenTotalSupply,
                TransactionHash  = arg.TransactionHash
            };

            // todo: refactor into event generation + projection logic
            var existingContract = await _erc20TokenService.GetByTokenAddressAsync(token.Address);

            if (existingContract == null)
            {
                await _erc20TokenService.AddAsync(token);
            }
        }
        public async Task <IReadOnlyList <BlockchainBalanceResult> > GetBalancesAsync(string address)
        {
            var balances = new List <BlockchainBalanceResult>();

            object response = await _retryPolicy.ExecuteAsync(() =>
                                                              _ethereumServiceClient.ApiErc20BalancePostAsync(new GetErcBalance(address)));

            if (response is ApiException ex)
            {
                _log.Error(message: ex.Error?.Message, context: ex.ToJson());

                throw new WalletAddressBalanceException(BlockchainType.EthereumIata, address);
            }

            if (response is AddressTokenBalanceContainerResponse result)
            {
                foreach (AddressTokenBalanceResponse balanceResponse in result.Balances)
                {
                    Erc20Token token =
                        await _assetsService.Erc20TokenGetByAddressAsync(balanceResponse.Erc20TokenAddress);

                    if (string.IsNullOrEmpty(token?.AssetId))
                    {
                        continue;
                    }

                    Asset asset = await _assetsLocalCache.GetAssetByIdAsync(token.AssetId);

                    if (asset == null)
                    {
                        continue;
                    }

                    balances.Add(new BlockchainBalanceResult
                    {
                        AssetId = asset.Id,
                        Balance = balanceResponse.Balance.FromContract(asset.MultiplierPower, asset.Accuracy)
                    });
                }

                return(balances);
            }

            throw new UnrecognizedApiResponse(response?.GetType().FullName);
        }
        public async Task Handle(TransferEvent transferEvent)
        {
            if (transferEvent == null)
            {
                return;
            }

            Erc20Token token = await _assetsService.Erc20TokenGetByAddressAsync(transferEvent.TokenAddress);

            if (token == null)
            {
                throw new UnknownErc20TokenException(transferEvent.TokenAddress);
            }

            Asset asset = await _assetsService.AssetGetAsync(token.AssetId);

            if (asset == null)
            {
                throw new UnknownErc20AssetException(token.AssetId);
            }

            switch (transferEvent.SenderType)
            {
            case SenderType.Customer:
                var inboundTransactionRequest = Mapper.Map <RegisterInboundTxModel>(
                    transferEvent, opt =>
                {
                    opt.Items["AssetId"]         = asset.DisplayId;
                    opt.Items["AssetMultiplier"] = asset.MultiplierPower;
                    opt.Items["AssetAccuracy"]   = asset.Accuracy;
                });
                await _log.LogPayInternalExceptionIfAny(() =>
                                                        _payInternalClient.RegisterEthereumInboundTransactionAsync(inboundTransactionRequest));

                break;

            case SenderType.EthereumCore:
                switch (transferEvent.EventType)
                {
                case EventType.Started:
                    var outboundTransactionRequest = Mapper.Map <RegisterOutboundTxModel>(
                        transferEvent, opt =>
                    {
                        opt.Items["AssetId"]         = asset.DisplayId;
                        opt.Items["AssetMultiplier"] = asset.MultiplierPower;
                        opt.Items["AssetAccuracy"]   = asset.Accuracy;
                    });
                    await _log.LogPayInternalExceptionIfAny(() =>
                                                            _payInternalClient
                                                            .RegisterEthereumOutboundTransactionAsync(outboundTransactionRequest));

                    break;

                case EventType.Failed:
                    await _log.LogPayInternalExceptionIfAny(() =>
                                                            _payInternalClient.FailEthereumOutboundTransactionAsync(
                                                                Mapper.Map <FailOutboundTxModel>(transferEvent)));

                    break;

                case EventType.Completed:
                    await _log.LogPayInternalExceptionIfAny(() =>
                                                            _payInternalClient.CompleteEthereumOutboundTransactionAsync(
                                                                Mapper.Map <CompleteOutboundTxModel>(transferEvent, opt =>
                    {
                        opt.Items["AssetMultiplier"] = asset.MultiplierPower;
                        opt.Items["AssetAccuracy"]   = asset.Accuracy;
                    })));

                    break;

                case EventType.NotEnoughFunds:
                    await _log.LogPayInternalExceptionIfAny(() =>
                                                            _payInternalClient.FailEthereumOutboundTransactionAsync(
                                                                Mapper.Map <NotEnoughFundsOutboundTxModel>(transferEvent)));

                    break;

                default: throw new UnexpectedEthereumEventTypeException(transferEvent.EventType);
                }

                break;

            default:
                throw new UnexpectedEthereumTransferTypeException(transferEvent.SenderType);
            }
        }
        public async Task <IActionResult> Update([FromBody] Erc20Token token)
        {
            await _erc20TokenService.UpdateAsync(token);

            return(NoContent());
        }
        public async Task <IActionResult> Add([FromBody] Erc20Token token)
        {
            await _erc20TokenService.AddAsync(token);

            return(Ok());
        }
예제 #7
0
        private static IEnumerable <string> CreateAssets(IEnumerable <ContractMetadata> contracts, bool skipTransferCheck)
        {
            var assetIds = new ConcurrentBag <string>();

            ResetOutputCounter();

            Console.WriteLine("Creating assets...");

            Parallel.ForEach(contracts, contract =>
            {
                var operationResult    = "";
                var operationSucceeded = true;

                try
                {
                    var tokenAddress = contract.Address.ToLowerInvariant();
                    var erc20Token   = _assetsService.Erc20TokenGetByAddress(tokenAddress);

                    if (erc20Token == null)
                    {
                        erc20Token = new Erc20Token
                        {
                            Address = tokenAddress
                        };

                        if (!skipTransferCheck)
                        {
                            if (!ContractHasOrCallsTransferMethod(contract))
                            {
                                operationResult    = "transfer method not detected";
                                operationSucceeded = false;
                            }
                        }

                        if (operationSucceeded)
                        {
                            if (TryGetTokenDecimals(contract, out var tokenDecimals))
                            {
                                erc20Token.TokenDecimals = tokenDecimals;
                            }
                            else
                            {
                                operationResult    = "can not get token decimals";
                                operationSucceeded = false;
                            }
                        }

                        if (operationSucceeded)
                        {
                            if (TryGetTokenSymbol(contract, out var tokenSymbol))
                            {
                                erc20Token.TokenName   = GetTokenName(contract, tokenSymbol);
                                erc20Token.TokenSymbol = tokenSymbol;
                            }
                            else
                            {
                                operationResult    = "can not get token symbol";
                                operationSucceeded = false;
                            }
                        }

                        if (operationSucceeded)
                        {
                            erc20Token.TokenTotalSupply = GetTokenTotalSupply(contract);
                        }

                        // Bug workaround
                        try
                        {
                            _assetsService.Erc20TokenAdd(erc20Token);
                        }
                        catch (HttpOperationException e) when(e.Response.StatusCode == HttpStatusCode.OK)
                        {
                        }
                    }

                    if (operationSucceeded)
                    {
                        var assetId      = contract.AssetId;
                        Asset asset      = null;
                        bool updateAsset = !string.IsNullOrEmpty(contract.AssetId);

                        if (updateAsset)
                        {
                            asset = _assetsService.AssetGet(contract.AssetId);

                            if (asset == null)
                            {
                                Console.WriteLine($"Wrong assetId {contract.AssetId}");

                                return;
                            }
                        }

                        if (!updateAsset && string.IsNullOrEmpty(assetId))
                        {
                            asset = _assetsService.Erc20TokenCreateAsset(contract.Address);

                            assetId = asset.Id;

                            operationResult = $"asset {assetId} created";
                        }
                        else
                        {
                            operationResult = "asset already exists";
                        }

                        if (updateAsset)
                        {
                            var oldTokens = _assetsService.Erc20TokenGetBySpecification(new Erc20TokenSpecification()
                            {
                                Ids = new List <string>()
                                {
                                    assetId
                                }
                            });

                            var oldToken = oldTokens.Items?.FirstOrDefault();
                            if (oldToken != null)
                            {
                                oldToken.AssetId = null;
                                _assetsService.Erc20TokenUpdate(oldToken);
                            }

                            asset.BlockChainAssetId = tokenAddress;
                            erc20Token         = erc20Token ?? _assetsService.Erc20TokenGetByAddress(tokenAddress);
                            erc20Token.AssetId = assetId;
                            asset.Blockchain   = Blockchain.Ethereum;
                            asset.Type         = AssetType.Erc20Token;
                            _assetsService.AssetUpdate(asset);
                            _assetsService.Erc20TokenUpdate(erc20Token);
                        }
                        else
                        {
                            assetIds.Add(assetId);
                        }
                    }
                }
                catch (Exception e)
                {
                    operationResult    = e.ToOperationResult();
                    operationSucceeded = false;
                }

                OutputOperationResult(contract.Address, operationResult, operationSucceeded);
            });

            return(assetIds);
        }