private async Task UpdateSwapBalanceAsync()
        {
            queryingNotify = "Querying balance ...";
            await InvokeAsync(() =>
            {
                StateHasChanged();
            });

            lyrReserveBalance = await SwapUtils.GetLyraBalanceAsync(Configuration["network"], swapOptions.CurrentValue.lyrPvk);

            tlyrReserveBalance = await SwapUtils.GetEthContractBalanceAsync(swapOptions.CurrentValue.ethUrl,
                                                                            swapOptions.CurrentValue.ethContract, swapOptions.CurrentValue.ethPub);

            //         var ethGas = await SwapUtils.EstimateEthTransferFeeAsync(swapOptions.CurrentValue.ethUrl,
            //                 swapOptions.CurrentValue.ethContract, swapOptions.CurrentValue.ethPub);

            //         ICoinGeckoClient _client;
            //         _client = CoinGeckoClient.Instance;
            //         const string vsCurrencies = "usd";
            //         var prices = await _client.SimpleClient.GetSimplePrice(new[] { "ethereum", "lyra" }, new[] { vsCurrencies });

            //ethGasFee = (decimal)((double)(ethGas / 10000000000) * prices["ethereum"]["usd"].GetValueOrDefault());
            //lyraPrice = (decimal) prices["lyra"]["usd"].Value;

            queryingNotify = "";
            await InvokeAsync(() =>
            {
                StateHasChanged();
            });
        }
        private async Task UpdateSwapFromBalanceAsync()
        {
            if (string.IsNullOrEmpty(_swapFromTokenName))
            {
                _swapFromTokenName = "LYR";
            }

            if (_swapFromTokenName == "LYR")
            {
                // get lyr balance
                fromTokenBalance = walletState.Value.wallet.BaseBalance;
            }
            else if (_swapFromTokenName == "TLYR")
            {
                fromTokenBalance = 0;
                fromTokenBalance = await SwapUtils.GetEthContractBalanceAsync(swapOptions.CurrentValue.ethUrl,
                                                                              swapOptions.CurrentValue.ethContract, SelectedAccount);
            }

            await InvokeAsync(() =>
            {
                StateHasChanged();
            });
        }
示例#3
0
        public async Task HandleSwap(WebWalletBeginSwapTLYRAction action, IDispatcher dispatcher)
        {
            bool IsSuccess = false;

            try
            {
                if (action.fromToken == "LYR" && action.toToken == "TLYR")
                {
                    var syncResult = await action.wallet.Sync(null);

                    if (syncResult == APIResultCodes.Success)
                    {
                        var sendResult = await action.wallet.Send(action.fromAmount,
                                                                  action.options.lyrPub, "LYR");

                        if (sendResult.ResultCode == APIResultCodes.Success)
                        {
                            logger.LogInformation($"TokenSwap: first stage is ok for {action.fromAddress}");
                            var(txHash, result) = await SwapUtils.SendEthContractTokenAsync(
                                action.options.ethUrl, action.options.ethContract, action.options.ethPub,
                                action.options.ethPvk,
                                action.toAddress, new BigInteger(action.toAmount * 100000000),                                 // 10^8
                                action.gasPrice, action.gasLimit,
                                null);

                            logger.LogInformation($"TokenSwap: second stage for {action.fromAddress} eth tx hash is {txHash} IsSuccess: {result}");

                            if (!result)
                            {
                                throw new Exception("Eth sending failed.");
                            }

                            IsSuccess = true;
                        }
                        else
                        {
                            throw new Exception("Unable to send from your Lyra wallet.");
                        }
                    }
                    else
                    {
                        throw new Exception("Unable to sync Lyra Wallet.");
                    }
                }

                if (action.fromToken == "TLYR" && action.toToken == "LYR")
                {
                    var(txHash, result) = await SwapUtils.SendEthContractTokenAsync(
                        action.options.ethUrl, action.options.ethContract, action.fromAddress,
                        null,
                        action.options.ethPub, new BigInteger(action.fromAmount * 100000000),                         // 10^8
                        action.gasPrice, action.gasLimit,
                        action.metamask);

                    logger.LogInformation($"TokenSwap: first stage for {action.fromAddress} eth tx hash {result} IsSuccess: {result}");

                    if (result)                     // test if success transfer
                    {
                        var store  = new AccountInMemoryStorage();
                        var wallet = Wallet.Create(store, "default", "", config["network"],
                                                   action.options.lyrPvk);

                        var syncResult = await wallet.Sync(client);

                        if (syncResult == APIResultCodes.Success)
                        {
                            var sendResult = await wallet.Send(action.toAmount,
                                                               action.toAddress, "LYR");

                            if (sendResult.ResultCode == Lyra.Core.Blocks.APIResultCodes.Success)
                            {
                                IsSuccess = true;
                            }
                            else
                            {
                                throw new Exception("Unable to send from your wallet.");
                            }
                        }
                        else
                        {
                            throw new Exception("Unable to sync Lyra Wallet.");
                        }
                    }
                    else
                    {
                        throw new Exception("Eth sending failed.");
                    }
                }
                logger.LogInformation($"TokenSwap: Swapping {action.fromAmount} from {action.fromAddress} to {action.toAddress} is succeed.");
                dispatcher.Dispatch(new WebWalletSwapTLYRResultAction {
                    Success = IsSuccess
                });
            }
            catch (Exception ex)
            {
                logger.LogInformation($"TokenSwap: Swapping {action.fromAmount} from {action.fromAddress} to {action.toAddress} is failed. Error: {ex}");
                dispatcher.Dispatch(new WebWalletSwapTLYRResultAction {
                    Success = false, errMessage = ex.ToString()
                });
            }
        }
        private void UpdateSwapToBalance()
        {
            if (walletState.Value.stage == UIStage.SwapToken)
            {
                _ = Task.Run(async() => {
                    await UpdateSwapToBalanceForLyraSwapAsync();
                });
                return;
            }

            if (_swapToTokenName == "TLYR")
            {
                swapToAddress = SelectedAccount;
            }
            else if (_swapToTokenName == "LYR")
            {
                swapToAddress = walletState.Value.wallet.AccountId;
            }

            if (swapFromCount == 0)
            {
                swapToCount = 0;
                return;
            }

            if (swapToAddress == null || _svcFeeCalculationTask != null)
            {
                return;
            }

            walletState.Value.IsLoading = true;
            swapToCount = 0;
            IsDisabled  = true;
            swapFeeDesc = "Calculating swap service fee...";

            _svcFeeCalculationTask = Task.Run(async() => {
                try
                {
                    ICoinGeckoClient _client;
                    _client = CoinGeckoClient.Instance;
                    const string vsCurrencies = "usd";
                    var priceTask             = _client.SimpleClient.GetSimplePrice(new[] { "ethereum", "lyra" }, new[] { vsCurrencies });
                    var gasOracleTask         = SwapUtils.GetGasOracle(swapOptions.CurrentValue.ethScanApiKey);

                    await Task.WhenAll(priceTask, gasOracleTask);

                    if (priceTask.IsCompletedSuccessfully && gasOracleTask.IsCompletedSuccessfully)
                    {
                        var estFrom = _swapToTokenName == "TLYR" ? swapOptions.CurrentValue.ethPub : SelectedAccount;
                        var estTo   = _swapToTokenName == "TLYR" ? SelectedAccount : swapOptions.CurrentValue.ethPub;

                        var estimateGasTask = SwapUtils.EstimateEthTransferFeeAsync(swapOptions.CurrentValue.ethUrl,
                                                                                    swapOptions.CurrentValue.ethContract,
                                                                                    estFrom, estTo, new BigInteger(swapFromCount), gasOracleTask.Result);

                        await Task.WhenAll(estimateGasTask);

                        if (priceTask.IsCompletedSuccessfully && estimateGasTask.IsCompletedSuccessfully && gasOracleTask.IsCompletedSuccessfully)
                        {
                            var prices    = priceTask.Result;
                            var gasOracle = gasOracleTask.Result;
                            var gasLimit  = estimateGasTask.Result;

                            EthGasPrice = gasOracle;
                            EthGasLimit = gasLimit;

                            if (_swapToTokenName == "TLYR")
                            {
                                ethGasFee = (decimal)(gasOracle * (int)gasLimit * prices["ethereum"]["usd"] / 1000000000);
                                lyraPrice = (decimal)prices["lyra"]["usd"];

                                var totalFee       = swapFromCount * 0.0001m + 1 + ethGasFee / lyraPrice;
                                var totalfeeInLyra = Math.Round(totalFee, 2);

                                //swapFeeDesc = $"Ethereum Gas price: {gasOracle} Gas limit: {gasLimit} ETH price: ${prices["ethereum"]["usd"]} Lyra price: ${prices["lyra"]["usd"].Value} Final fee ${ethGasFee} in LYR: {feeInLyra}";
                                swapFeeDesc = $"{totalfeeInLyra} LYR ($ {Math.Round(totalfeeInLyra * lyraPrice, 2)})";
                                swapToCount = swapFromCount - totalfeeInLyra;
                            }
                            else
                            {
                                var totalFee       = swapFromCount * 0.0001m + 1;
                                var totalfeeInLyra = Math.Round(totalFee, 2);

                                swapFeeDesc = $"{totalfeeInLyra} LYR ($ {Math.Round(totalfeeInLyra * lyraPrice, 2)})";
                                swapToCount = swapFromCount - totalfeeInLyra;
                            }

                            IsDisabled = false;

                            swapFeeDesc = "Estimated OK.";
                        }
                        else
                        {
                            throw new Exception("Can't query fee. Network error.");
                        }
                    }
                    else
                    {
                        throw new Exception("Can't query fee. Network error.");
                    }
                }
                catch (Exception ex)
                {
                    swapFeeDesc = $"Error: {ex.Message}";
                }

                await InvokeAsync(() =>
                {
                    walletState.Value.IsLoading = false;
                    StateHasChanged();
                    _svcFeeCalculationTask = null;
                });
            });
        }
        private async Task BeginSwapTLYR(MouseEventArgs e)
        {
            IsDisabled        = true;
            swapResultMessage = "Checking for configurations...";
            await InvokeAsync(() =>
            {
                StateHasChanged();
            });

            // do check
            swapResultMessage = "";

            // check network id
            CurrentChainName = await metamaskService.GetChainName();

            if (Configuration["network"] == "testnet" && CurrentChainName != "Rinkeby Test Network")
            {
                swapResultMessage = "Only Rinkeby Test Network is supported for testnet.";
            }
            else if (Configuration["network"] == "mainnet" && CurrentChainName != "Ethereum Main Network")
            {
                swapResultMessage = "Only Ethereum Main Network is supported for mainnet.";
            }
            else if (!EthereumEnabled || !walletState.Value.IsOpening)
            {
                swapResultMessage = "Wallet(s) not opening or connected.";
            }
            else if (swapFromToken == swapToToken)
            {
                swapResultMessage = "No need to swap.";
            }
            else if (!((swapFromToken == "LYR" && swapToToken == "TLYR") || (swapFromToken == "TLYR" && swapToToken == "LYR")))
            {
                swapResultMessage = "Unknown token pair";
            }
            else if (swapFromCount < 10)
            {
                swapResultMessage = "Swap amount too small. (< 10)";
            }
            else if (swapFromCount > 1000000)
            {
                swapResultMessage = "Swap amount too large. (> 1M)";
            }
            else if (swapFromToken == "LYR" && swapFromCount > walletState.Value.wallet.BaseBalance)
            {
                swapResultMessage = "Not enough LYR in Lyra Wallet.";
            }
            else if (string.IsNullOrWhiteSpace(swapToAddress))
            {
                swapResultMessage = "Not valid swap to address.";
            }
            else if (swapToToken == "TLYR" && swapToCount > 0.8m * tlyrReserveBalance)
            {
                swapResultMessage = "Reserve account of TLYR is running low. Please contact support.";
            }
            else if (swapToToken == "LYR" && swapToCount > 0.8m * lyrReserveBalance)
            {
                swapResultMessage = "Reserve account of LYR is running low. Please contact support.";
            }
            else if (swapToCount < 1)
            {
                swapResultMessage = "Swap to amount too small.";
            }
            else if (swapFromToken == "TLYR")
            {
                try
                {
                    var tlyrBalance = await SwapUtils.GetEthContractBalanceAsync(swapOptions.CurrentValue.ethUrl,
                                                                                 swapOptions.CurrentValue.ethContract, SelectedAccount);

                    if (tlyrBalance < swapFromCount)
                    {
                        swapResultMessage = "Not enough TLYR in Ethereum Wallet.";
                    }
                }
                catch (Exception)
                {
                    swapResultMessage = "Unable to get TLYR balance.";
                }
            }

            if (!string.IsNullOrEmpty(swapResultMessage))
            {
                IsDisabled = false;
                await InvokeAsync(() =>
                {
                    StateHasChanged();
                });

                return;
            }

            var mmmsg = swapFromToken == "TLYR" ? "Please open Matamask and confirm transaction." : "";

            swapResultMessage         = $"Do swapping... {mmmsg} Please wait for a moment... ";
            walletState.Value.Message = "";
            await InvokeAsync(() =>
            {
                StateHasChanged();
            });

            var arg = new WebWalletBeginSwapTLYRAction
            {
                wallet = walletState.Value.wallet,

                fromToken   = swapFromToken,
                fromAddress = swapFromToken == "LYR" ? walletState.Value.wallet.AccountId : SelectedAccount,
                fromAmount  = swapFromCount,

                toToken   = swapToToken,
                toAddress = swapToAddress,
                toAmount  = swapToCount,

                gasPrice = EthGasPrice,
                gasLimit = EthGasLimit,

                options  = swapOptions.CurrentValue,
                metamask = metamaskInterceptor
            };

            logger.LogInformation($"TokenSwap: Begin  {arg.fromAmount} from {arg.fromAddress} to {arg.toAddress} amount {arg.toAmount}");
            Dispatcher.Dispatch(arg);
            IsDisabled = true;
        }