コード例 #1
0
        public async Task UpdateBalancesAsync(IDbConnection con, IDbTransaction tx, PoolConfig poolConfig, IPayoutHandler payoutHandler, Block block, decimal blockReward)
        {
            // calculate rewards
            var rewards         = new Dictionary <string, decimal>();
            var shareCutOffDate = CalculateRewards(poolConfig, block, blockReward, rewards);

            // update balances
            foreach (var address in rewards.Keys)
            {
                var amount = rewards[address];

                if (amount > 0)
                {
                    logger.Info(() => $"Adding {payoutHandler.FormatAmount(amount)} to balance of {address} for block {block.BlockHeight}");
                    await balanceRepo.AddAmountAsync(con, tx, poolConfig.Id, address, amount, $"Reward for block {block.BlockHeight}");
                }
            }

            // delete discarded shares
            if (shareCutOffDate.HasValue)
            {
                var cutOffCount = await shareRepo.CountSharesSoloBeforeCreatedAsync(con, tx, poolConfig.Id, block.Miner, shareCutOffDate.Value);

                if (cutOffCount > 0)
                {
#if !DEBUG
                    logger.Info(() => $"Deleting {cutOffCount} discarded shares for {block.Miner}");
                    await shareRepo.DeleteSharesSoloBeforeCreatedAsync(con, tx, poolConfig.Id, block.Miner, shareCutOffDate.Value);
#endif
                }
            }
        }
コード例 #2
0
        public async Task UpdateBalancesAsync(IDbConnection con, IDbTransaction tx, PoolConfig poolConfig,
                                              IPayoutHandler payoutHandler, Block block, decimal blockReward)
        {
            var payoutConfig = poolConfig.PaymentProcessing.PayoutSchemeConfig;

            // POWRShare window (see https://bitcointalk.org/index.php?topic=39832)
            var window = payoutConfig?.ToObject <Config>()?.Factor ?? 2.0m;

            // calculate rewards
            var shares          = new Dictionary <string, double>();
            var rewards         = new Dictionary <string, decimal>();
            var shareCutOffDate = await CalculateRewards(poolConfig, window, block, blockReward, shares, rewards);

            // var updatedShares = PostAsync(

            // update balances
            foreach (var address in rewards.Keys)
            {
                var amount = rewards[address];

                if (amount > 0)
                {
                    logger.Info(() => $"Adding {payoutHandler.FormatAmount(amount)} to balance of {address} for {FormatUtil.FormatQuantity(shares[address])} ({shares[address]}) shares for block {block.BlockHeight}");
                    await balanceRepo.AddAmountAsync(con, tx, poolConfig.Id, address, amount, $"Reward for {FormatUtil.FormatQuantity(shares[address])} shares for block {block.BlockHeight}");
                }
            }

            // delete discarded shares
            if (shareCutOffDate.HasValue)
            {
                var cutOffCount = await shareRepo.CountSharesBeforeCreatedAsync(con, tx, poolConfig.Id, shareCutOffDate.Value);

                if (cutOffCount > 0)
                {
                    LogDiscardedShares(poolConfig, block, shareCutOffDate.Value);

#if !DEBUG
                    logger.Info(() => $"Deleting {cutOffCount} discarded shares before {shareCutOffDate.Value:O}");
                    shareRepo.DeleteSharesBeforeCreated(con, tx, poolConfig.Id, shareCutOffDate.Value);
#endif
                }
            }

            // diagnostics
            var totalShareCount = shares.Values.ToList().Sum(x => new decimal(x));
            var totalRewards    = rewards.Values.ToList().Sum(x => x);

            if (totalRewards > 0)
            {
                logger.Info(() => $"{FormatUtil.FormatQuantity((double) totalShareCount)} ({Math.Round(totalShareCount, 2)}) shares contributed to a total payout of {payoutHandler.FormatAmount(totalRewards)} ({totalRewards / blockReward * 100:0.00}% of block reward) to {rewards.Keys.Count} addresses");
            }
        }
コード例 #3
0
        public virtual async Task <decimal> UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, Block block, PoolConfig pool)
        {
            var blockRewardRemaining = block.Reward;

            // Distribute funds to configured reward recipients
            foreach (var recipient in poolConfig.RewardRecipients.Where(x => x.Percentage > 0))
            {
                var amount  = block.Reward * (recipient.Percentage / 100.0m);
                var address = recipient.Address;

                blockRewardRemaining -= amount;

                // skip transfers from pool wallet to pool wallet
                if (address != poolConfig.Address)
                {
                    logger.Info(() => $"Adding {FormatAmount(amount)} to balance of {address}");
                    await balanceRepo.AddAmountAsync(con, tx, poolConfig.Id, address, amount, $"Reward for block {block.BlockHeight}");
                }
            }

            return(blockRewardRemaining);
        }
コード例 #4
0
        protected virtual async Task PersistPaymentsAsync(Balance[] balances, string transactionConfirmation)
        {
            var coin = poolConfig.Template.As <CoinTemplate>();

            try
            {
                await faultPolicy.ExecuteAsync(async() =>
                {
                    await cf.RunTx(async(con, tx) =>
                    {
                        foreach (var balance in balances)
                        {
                            if (!string.IsNullOrEmpty(transactionConfirmation) &&
                                !poolConfig.RewardRecipients.Any(x => x.Address == balance.Address))
                            {
                                // record payment
                                var payment = new Payment
                                {
                                    PoolId  = poolConfig.Id,
                                    Coin    = coin.Symbol,
                                    Address = balance.Address,
                                    Amount  = balance.Amount,
                                    Created = clock.Now,
                                    TransactionConfirmationData = transactionConfirmation
                                };

                                await paymentRepo.InsertAsync(con, tx, payment);
                            }

                            // reset balance
                            logger.Debug(() => $"[{LogCategory}] Resetting balance of {balance.Address}");
                            await balanceRepo.AddAmountAsync(con, tx, poolConfig.Id, coin.Symbol, balance.Address, -balance.Amount, $"Balance reset after payment");
                        }
                    });
                });
            }

            catch (Exception ex)
            {
                logger.Error(ex, () => $"[{LogCategory}] Failed to persist the following payments: " +
                             $"{JsonConvert.SerializeObject(balances.Where(x => x.Amount > 0).ToDictionary(x => x.Address, x => x.Amount))}");
                throw;
            }
        }
コード例 #5
0
    public async Task UpdateBalancesAsync(IDbConnection con, IDbTransaction tx, IMiningPool pool, IPayoutHandler payoutHandler,
                                          Block block, decimal blockReward, CancellationToken ct)
    {
        var poolConfig      = pool.Config;
        var shares          = new Dictionary <string, double>();
        var rewards         = new Dictionary <string, decimal>();
        var shareCutOffDate = await CalculateRewardsAsync(pool, payoutHandler, block, blockReward, shares, rewards, ct);

        // update balances
        foreach (var address in rewards.Keys)
        {
            var amount = rewards[address];

            if (amount > 0)
            {
                logger.Info(() => $"Adding {payoutHandler.FormatAmount(amount)} to balance of {address} for {FormatUtil.FormatQuantity(shares[address])} ({shares[address]}) shares for block {block.BlockHeight}");
                await balanceRepo.AddAmountAsync(con, tx, poolConfig.Id, address, amount, $"Reward for {FormatUtil.FormatQuantity(shares[address])} shares for block {block.BlockHeight}");
            }
        }

        // delete discarded shares
        if (shareCutOffDate.HasValue)
        {
            var cutOffCount = await shareRepo.CountSharesBeforeCreatedAsync(con, tx, poolConfig.Id, shareCutOffDate.Value, ct);

            if (cutOffCount > 0)
            {
                await LogDiscardedSharesAsync(ct, poolConfig, block, shareCutOffDate.Value);

                logger.Info(() => $"Deleting {cutOffCount} discarded shares before {shareCutOffDate.Value:O}");
                await shareRepo.DeleteSharesBeforeCreatedAsync(con, tx, poolConfig.Id, shareCutOffDate.Value, ct);
            }
        }

        // diagnostics
        var totalShareCount = shares.Values.ToList().Sum(x => new decimal(x));
        var totalRewards    = rewards.Values.ToList().Sum(x => x);

        if (totalRewards > 0)
        {
            logger.Info(() => $"{FormatUtil.FormatQuantity((double) totalShareCount)} ({Math.Round(totalShareCount, 2)}) shares contributed to a total payout of {payoutHandler.FormatAmount(totalRewards)} ({totalRewards / blockReward * 100:0.00}% of block reward) to {rewards.Keys.Count} addresses");
        }
    }
コード例 #6
0
        public async Task <object> AddMinerBalanceAsync(AddBalanceRequest request)
        {
            request.Usage = request.Usage?.Trim();

            if (string.IsNullOrEmpty(request.Usage))
            {
                request.Usage = $"Баланс администратора был изменён с адреса {Request.HttpContext.Connection.RemoteIpAddress}";
            }

            var oldBalance = await cf.Run(con => balanceRepo.GetBalanceAsync(con, request.PoolId, request.Address));

            var count = await cf.RunTx(async (con, tx) =>
            {
                return(await balanceRepo.AddAmountAsync(con, tx, request.PoolId, request.Address, request.Amount, request.Usage));
            });

            var newBalance = await cf.Run(con => balanceRepo.GetBalanceAsync(con, request.PoolId, request.Address));

            return(new { oldBalance, newBalance });
        }