public async Task BotWalletBalanceAsync([Remainder] string _ = null) { try { if (!WalletUtilities.CheckWalletExist(SqliteDatabaseService, Context.Client.CurrentUser.Id, out var walletAccount)) { await ReplyAsync("Please use the `RegisterWallet` command to register your wallet first.").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var balance = await RpcService.WalletRpcClient.GetBalanceAsync(walletAccount.AccountIndex).ConfigureAwait(false); var walletHeight = await RpcService.WalletRpcClient.GetHeightAsync().ConfigureAwait(false); var daemonHeight = await RpcService.DaemonRpcClient.GetInfoAsync().ConfigureAwait(false); var availableBalance = balance.UnlockedBalance / Convert.ToDecimal(ConfigService.CoinUnit); var pendingBalance = (balance.Balance - balance.UnlockedBalance) / Convert.ToDecimal(ConfigService.CoinUnit); var embed = new EmbedBuilder() .WithColor(Color.Orange) .WithTitle(":moneybag: TIP BOT BALANCE") .WithDescription($":moneybag: Available: {WalletUtilities.FormatBalance(ConfigService, availableBalance)} {ConfigService.CoinSymbol}\n:purse: Pending: {WalletUtilities.FormatBalance(ConfigService, pendingBalance)} {ConfigService.CoinSymbol}\n:arrows_counterclockwise: Status: {walletHeight.Height} / {daemonHeight.Height}"); await ReplyAsync(embed.Build()).ConfigureAwait(false); await AddReactionAsync("✅").ConfigureAwait(false); } catch (Exception ex) { await CatchError(ex).ConfigureAwait(false); } }
public async Task TipAsync([Summary("Amount to tip")] decimal amount, [Remainder] string _ = null) { try { if (!WalletUtilities.CheckWalletExist(SqliteDatabaseService, Context.User.Id, out var walletAccount)) { await ReplyAsync("Please use the `RegisterWallet` command to register your wallet first.").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var atomicAmountToTip = Convert.ToUInt64(Math.Ceiling(amount * ConfigService.CoinUnit)); if (atomicAmountToTip < ConfigService.TipMinimumAmount) { await ReplyAsync($":x: Minimum tip amount is: {WalletUtilities.FormatBalance(ConfigService, ConfigService.TipMinimumAmount / Convert.ToDecimal(ConfigService.CoinUnit))} {ConfigService.CoinSymbol}").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var balance = await RpcService.WalletRpcClient.GetBalanceAsync(walletAccount.AccountIndex).ConfigureAwait(false); if (atomicAmountToTip * Convert.ToUInt64(Context.Message.MentionedUsers.Count) > balance.UnlockedBalance) { await ReplyAsync(":x: Insufficient balance to tip this amount.").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var transferDestinations = new List <CommandRpcTransferSplit.TransferDestination>(); var userTipped = new List <IUser>(); foreach (var user in Context.Message.MentionedUsers) { // @everyone @here if (user.Id == Context.Guild.Id || user.Id == Context.Channel.Id) { continue; } if (!WalletUtilities.CheckWalletExist(SqliteDatabaseService, user.Id, out var userWalletAccount)) { continue; } if (user.Id == Context.User.Id) { continue; } transferDestinations.Add(new CommandRpcTransferSplit.TransferDestination { Address = userWalletAccount.TipWalletAddress, Amount = atomicAmountToTip }); userTipped.Add(user); } if (userTipped.Count == 0) { var failEmbed = new EmbedBuilder() .WithColor(Color.Red) .WithTitle(":moneybag: TRANSFER RESULT") .WithDescription("Failed to tip this amount due to the users have not registered their wallet."); await ReplyDMAsync(failEmbed.Build()).ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var transferRequest = new CommandRpcTransferSplit.Request { AccountIndex = walletAccount.AccountIndex, Destinations = transferDestinations.ToArray(), Mixin = ConfigService.TipMixIn, GetTxHex = true }; var transferResult = await RpcService.WalletRpcClient.TransferSplitAsync(transferRequest).ConfigureAwait(false); if (!WalletUtilities.IsTransferSuccess(transferResult)) { var failEmbed = new EmbedBuilder() .WithColor(Color.Red) .WithTitle(":moneybag: TRANSFER RESULT") .WithDescription("Failed to tip this amount due to insufficient balance to cover the transaction fees."); await ReplyDMAsync(failEmbed.Build()).ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } // Tip Success for this user, inform them. foreach (var user in userTipped) { if (user.IsBot) { continue; } try { var dmChannel = await user.GetOrCreateDMChannelAsync().ConfigureAwait(false); var notificationEmbed = new EmbedBuilder() .WithColor(Color.Green) .WithTitle(":moneybag: INCOMING TIP") .WithDescription($":moneybag: You got a tip of {WalletUtilities.FormatBalance(ConfigService, atomicAmountToTip / Convert.ToDecimal(ConfigService.CoinUnit))} {ConfigService.CoinSymbol} from {Context.User}\n:hash: Transaction hash: {string.Join(", ", transferResult.TxHashList.Select(a => $"`{a}`"))}"); await dmChannel.SendMessageAsync("", false, notificationEmbed.Build()).ConfigureAwait(false); } catch (Exception) { // ignore. } } var successEmbed = new EmbedBuilder() .WithColor(Color.Green) .WithTitle(":moneybag: TRANSFER RESULT") .WithDescription($"You have tipped {WalletUtilities.FormatBalance(ConfigService, atomicAmountToTip / Convert.ToDecimal(ConfigService.CoinUnit))} {ConfigService.CoinSymbol} to {userTipped.Count} users"); await ReplyDMAsync(successEmbed.Build()).ConfigureAwait(false); for (var i = 0; i < transferResult.TxHashList.Length; i++) { var txAmount = transferResult.AmountList[i] / Convert.ToDecimal(ConfigService.CoinUnit); var txFee = transferResult.FeeList[i] / Convert.ToDecimal(ConfigService.CoinUnit); var txHash = transferResult.TxHashList[i]; var txEmbed = new EmbedBuilder() .WithColor(Color.Orange) .WithTitle($":moneybag: TRANSACTION PAID ({i + 1}/{transferResult.TxHashList.Length})") .WithDescription($"Amount: {WalletUtilities.FormatBalance(ConfigService, txAmount)} {ConfigService.CoinSymbol}\nFee: {WalletUtilities.FormatBalance(ConfigService, txFee)} {ConfigService.CoinSymbol}\nTransaction hash: `{txHash}`"); await ReplyDMAsync(txEmbed.Build()).ConfigureAwait(false); } await AddReactionAsync("💰").ConfigureAwait(false); } catch (Exception ex) { await CatchError(ex).ConfigureAwait(false); } }
public async Task WalletWithdrawAsync([Summary("Amount to withdraw")] decimal amount, [Remainder] string _ = null) { try { if (!WalletUtilities.CheckWalletExist(SqliteDatabaseService, Context.User.Id, out var walletAccount)) { await ReplyAsync("Please use the `RegisterWallet` command to register your wallet first.").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var atomicAmountToWithdraw = Convert.ToUInt64(Math.Ceiling(amount * ConfigService.CoinUnit)); if (atomicAmountToWithdraw < ConfigService.WithdrawMinimumAmount) { await ReplyAsync($":x: Minimum withdrawal amount is: {WalletUtilities.FormatBalance(ConfigService, ConfigService.WithdrawMinimumAmount / Convert.ToDecimal(ConfigService.CoinUnit))} {ConfigService.CoinSymbol}").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var balance = await RpcService.WalletRpcClient.GetBalanceAsync(walletAccount.AccountIndex).ConfigureAwait(false); if (atomicAmountToWithdraw > balance.UnlockedBalance) { await ReplyAsync(":x: Insufficient balance to withdraw this amount.").ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var transferRequest = new CommandRpcTransferSplit.Request { AccountIndex = walletAccount.AccountIndex, Destinations = new[] { new CommandRpcTransferSplit.TransferDestination { Address = walletAccount.RegisteredWalletAddress, Amount = atomicAmountToWithdraw } }, Mixin = ConfigService.TipMixIn, GetTxHex = true }; var transferResult = await RpcService.WalletRpcClient.TransferSplitAsync(transferRequest).ConfigureAwait(false); if (!WalletUtilities.IsTransferSuccess(transferResult)) { var failEmbed = new EmbedBuilder() .WithColor(Color.Red) .WithTitle(":moneybag: TRANSFER RESULT") .WithDescription("Failed to withdrawn this amount due to insufficient balance to cover the transaction fees."); await ReplyDMAsync(failEmbed.Build()).ConfigureAwait(false); await AddReactionAsync("❌").ConfigureAwait(false); return; } var successEmbed = new EmbedBuilder() .WithColor(Color.Green) .WithTitle(":moneybag: TRANSFER RESULT") .WithDescription($"You have withdrawn {WalletUtilities.FormatBalance(ConfigService, atomicAmountToWithdraw / Convert.ToDecimal(ConfigService.CoinUnit))} {ConfigService.CoinSymbol}"); await ReplyDMAsync(successEmbed.Build()).ConfigureAwait(false); for (var i = 0; i < transferResult.TxHashList.Length; i++) { var txAmount = transferResult.AmountList[i] / Convert.ToDecimal(ConfigService.CoinUnit); var txFee = transferResult.FeeList[i] / Convert.ToDecimal(ConfigService.CoinUnit); var txHash = transferResult.TxHashList[i]; var txEmbed = new EmbedBuilder() .WithColor(Color.Orange) .WithTitle($":moneybag: TRANSACTION PAID ({i + 1}/{transferResult.TxHashList.Length})") .WithDescription($"Amount: {WalletUtilities.FormatBalance(ConfigService, txAmount)} {ConfigService.CoinSymbol}\nFee: {WalletUtilities.FormatBalance(ConfigService, txFee)} {ConfigService.CoinSymbol}\nTransaction hash: `{txHash}`"); await ReplyDMAsync(txEmbed.Build()).ConfigureAwait(false); } await AddReactionAsync("💰").ConfigureAwait(false); } catch (Exception ex) { await CatchError(ex).ConfigureAwait(false); } }