public void transferBalance(int playerId, int amount, TransactionType type, Action <BalanceActionResult> callback)
        {
            var id  = new Id(playerId);
            var cmd = new APICmd(CmdId.Request_Player_Info) + id;

            broker.ExecuteCommand <PlayerInfo>(cmd, (x, y) => {
                log(() => "****player info received");
                BalanceActionResult result;
                var factionAccount = SafeGetAccount(AccountType.Crew, y.factionId, y);
                var playerAccount  = SafeGetAccount(AccountType.Player, y.entityId, y);

                result = new BalanceActionResult()
                {
                    crewBalance     = factionAccount.balances[ResourceType.Points],
                    playerBalance   = playerAccount.balances[ResourceType.Points],
                    amountRequested = amount,
                    playerAccount   = playerId,
                    crewAccount     = y.factionId,
                    transactionType = type,
                    playerName      = y.playerName
                };

                var requestedCrewBalance   = result.crewBalance - amount;
                var requestedPlayerBalance = result.playerBalance + amount;

                if (requestedCrewBalance < 0)
                {
                    result.reason    = "insufficient crew balance";
                    result.succeeded = false;
                }
                else if (requestedPlayerBalance < 0)
                {
                    result.reason    = "insufficient player balance";
                    result.succeeded = false;
                }
                else
                {
                    result.crewBalance   = requestedCrewBalance;
                    result.playerBalance = requestedPlayerBalance;
                    result.succeeded     = true;
                }

                log(() => $"***transaction: {Serializer.Serialize(result)}");

                playerAccount.balances[ResourceType.Points] = result.playerBalance;
                SaveAccount(playerAccount);
                factionAccount.balances[ResourceType.Points] = result.crewBalance;
                SaveAccount(factionAccount);
                var ledger = new PlayerLedger(y, factionAccount, playerAccount);
                normalizePlayer(ledger);

                callback(result);
            });
        }
        private BalanceActionResult convertPointsToCredits(int playerId, int points)
        {
            var account = SafeGetAccount(AccountType.Player, playerId, null);

            log(() => $"*** before account: {Serializer.Serialize(account)}");
            var result = new BalanceActionResult()
            {
                amountRequested = points,
                playerAccount   = playerId,
                transactionType = TransactionType.Credits,
                playerBalance   = account.balances[ResourceType.Points]
            };

            if (result.playerBalance >= points)
            {
                var credits = points * settings.creditExchangeRate;
                account.balances[ResourceType.Points] -= points;
                result.playerBalance = account.balances[ResourceType.Points];

                normalizePlayerPoints(playerId, account);
                SaveAccount(account);

                log(() => $"*** after account: {Serializer.Serialize(account)}");
                var idCredits = new IdCredits()
                {
                    id      = playerId,
                    credits = credits
                };

                var cmd = new APICmd(CmdId.Request_Player_AddCredits, idCredits);
                broker.ExecuteCommand(cmd);
                result.succeeded = true;
            }
            else
            {
                result.succeeded = false;
                result.reason    = "insuffucient point balance";
            }
            return(result);
        }