private static async Task LoadGenInvDb()
        {
            //We use ProtoBuf protocol to store data
            string fileName = "invDb.proto";

            if (File.Exists(fileName))
            {
                byte[] data = await File.ReadAllBytesAsync(fileName);

                using var streamFile = new MemoryStream(data);
                //Load All data inside Library, cause this data will be use also for internal call like checking player name/info, you can use same data to check item/player in your code
                FutManager.InvDb = Serializer.Deserialize <Dictionary <uint, FifaInvBase> >(streamFile);
                return;
            }

            //Load All data inside Library, cause this data will be use also for internal call like checking player name/info, you can use same data to check item/player type in your code
            FutManager.InvDb = new Dictionary <uint, FifaInvBase>();

            //Add Inv Items to our Db, usually dont need to create/update it cause data are static and not update during season contracts/fitness/healt ...
            await FutManager.GenInvItems(FutManager.InvDb);

            //Icons and Standard player (no inform) dont need to update so offen, cause inform players are not here, to add Inform must use inside a instance seassion search Variants or try to add by other method like try to import from futbin ?
            await FutManager.GenInvPlayers(FutManager.InvDb);

            using var stream = new MemoryStream();
            Serializer.Serialize(stream, FutManager.InvDb);
            await File.WriteAllBytesAsync(fileName, stream.ToArray());
        }
        static async Task Main(string[] args)
        {
            //Avoid issue with libraries
            EncodingProvider provider = CodePagesEncodingProvider.Instance;

            Encoding.RegisterProvider(provider);

            _logger = new Logger();

            //Must call it first time or return errors other calls
            //Use FbmLibraryUi to gen user key-pass
            await FutManager.Init(_logger, Guid.Parse("6a17f074-2836-4ec3-9540-f5253205735f"), "7oxF51lNya+1yom4mjiNuQ==");

            _logger.Log("Main", "Current Tokens left " + FutManager.TokenLeft);

            await LoadGenInvDb();
            await ProcessAccount();

            Console.WriteLine("End");
            Console.ReadKey();
        }
        private static async Task ProcessAccount()
        {
            if (!await FutManager.IsFifaSupported(_logger))
            {
                throw new NotImplementedException("New Fifa Code");
            }

            IFutClient futClient    = FutManager.CreateNewInstance(_logger);
            int        errorTrigger = 0;

            while (true)
            {
                //Usually all main exception should be catch here ... specific exception like deny when bidding or stuck should be catch in specific method
                try
                {
                    await WorksProcess(futClient);

                    errorTrigger = 0;
                }
                catch (FifaConfigException ex)
                {
                    //All exceptions about wrong config like password ...
                    string message = "Config Exception: " + ex.Message;
                    _logger.LogError("Main", message);
                    break;
                }
                catch (FifaLogicException ex)
                {
                    _logger.LogWarning("Main", "Logic Exception: " + ex.Message);
                    errorTrigger++;

                    if (errorTrigger >= 3)
                    {
                        break;
                    }
                }
                catch (FifaInternalServerException e)
                {
                    _logger.LogWarning("Main", "Issue with server task sleep for 10 minutes");
                    await Task.Delay(10 * 60 * 1000);
                }
                catch (FifaSessionExceptionCaptcha e)
                {
                    _logger.Log("Main", "Session Captcha: " + e.Message);
                    //Must call it when trigger funcaptcha, then you need to login again and solve it, method setup IsLogged false to help you, at this point you can also force people to solve captcha by their self if dont wanna use solver after logout
                    //Remember must be solved only when trigger on GetUserInfo() not here
                    await futClient.LogOut();
                }
                catch (FifaSessionException e)
                {
                    _logger.LogWarning("Main", "Session: " + e.Message);

                    if (errorTrigger >= 3)
                    {
                        break;
                    }

                    //Usually happen when somebody is logged at same time
                    await futClient.ReSession();
                }
                catch (FifaException e)
                {
                    _logger.LogError("Main", "FifaException: " + e.Message);
                    errorTrigger++;

                    if (errorTrigger >= 3)
                    {
                        break;
                    }
                }
                catch (TaskCanceledException)
                {
                    //Network Issue? Perfomance Issue?
                    await Task.Delay(10 * 1000);
                }
                catch (Exception e)
                {
                    _logger.LogError("Main", "Exception: " + e.Message);
                    errorTrigger++;

                    if (errorTrigger >= 3)
                    {
                        break;
                    }
                }

                int secPause = FutManager.RandomNumber(2 * 10, 4 * 10);
                await Task.Delay(secPause * 100);
            }

            futClient.Dispose(); //Remember to Dispose when finish to use instance to release resources
        }
        private static async Task <bool> IsLogged(IFutClient futClient)
        {
            if (futClient.IsLogged)
            {
                return(true);
            }

            string fifaEmail         = "*****@*****.**";
            string fifaPass          = "******";
            string proxyAddress      = null; //"192.168.1.2:8888";
            string proxyUser         = null;
            string proxyPass         = null;
            Regex  rgx               = new Regex("[^a-zA-Z0-9]");
            string storageFile       = Path.Combine(AssemblyPath, rgx.Replace(fifaEmail, "") + ".storage.bin"); //must be unique for each account
            string solverApiKey      = "";                                                                      //Get key on http://api.de-ltd.co.uk/login
            bool   useFunSolverProxy = false;                                                                   //if true require proxy setup on loggin function
            ITwoFactorCodeProvider twoFactorCodeProvider = new AppAuthTwoFactorCodeProvider("xxxxxxxxxxxxx");   //You can also use ImapAuthTwoFactorCodeProvider, DisabledTwoFactorCodeProvider, AppAuthTwoFactorCodeProvider or implement a new by your self

            //Will throw Exception if detect new fifa code, then not need to use FutManager.IsFifaSupported before call it
            var accountType = await futClient.Loggin(fifaEmail, fifaPass, twoFactorCodeProvider, proxyAddress, proxyUser, proxyPass, storageFile);

            _logger.Log("IsLogged", "Logged on accountType " + accountType);

            FifaUserResponse accountInfo = null;

            try
            {
                accountInfo = await futClient.GetUserInfo();
            }
            catch (FifaSessionExceptionCaptcha)
            {
                //Need to solve captcha before we can continue

                //We use futmsolver solver but you can add a new one just implement here ... or you can also stop bot and ask to people to solve in standard app

                if (useFunSolverProxy)
                {
                    //Require proxy setup on Loggin function or will return error
                    if (!await futClient.FuncaptchaProxySolver(solverApiKey))
                    {
                        throw new Exception("too many tenatives");
                    }
                }
                else
                {
                    //We need to request captcha data before call funcaptcha
                    var captchaData = await futClient.GetCaptchaKey();

                    string callBack = null;

                    //It try to make max 3 tentatives
                    for (byte t = 0; t < 3; t++)
                    {
                        callBack = await futClient.FuncaptchaSolver(solverApiKey, captchaData.Pk, captchaData.Blob);

                        if (!string.IsNullOrEmpty(callBack))
                        {
                            break;
                        }
                    }

                    if (string.IsNullOrEmpty(callBack))
                    {
                        throw new Exception("too many tenatives");
                    }

                    //need to validate code on EA side
                    bool result = await futClient.ValidateCaptchaKey(callBack);

                    if (!result)
                    {
                        throw new Exception("usually never happen, session expired ?!?");
                    }
                }

                //Call again after captcha solved
                accountInfo = await futClient.GetUserInfo();
            }

            //0: "NONE" 1: "BLACKLIST" 2: "WHITELIST" 3: "GREYLIST" 100: "MAINTENANCE"
            if (accountInfo.UserInfo.Feature.Trade == 0)
            {
                throw new FifaConfigException("MarketNotUnlocked");
            }
            else if (accountInfo.UserInfo.Feature.Trade == 1)
            {
                throw new FifaConfigException("MarketLockedBlack");
            }
            else if (accountInfo.UserInfo.Feature.Trade == 3)
            {
                throw new FifaConfigException("MarketLockedGrey");
            }

            Coins = accountInfo.UserInfo.Credits; //Usually you will update credits when call GetTrade/GetWatch

            //Must Use it cause EA cache data for 5 minutes then you can't ask Each time this data
            NextTradePileCheck  = DateTime.UtcNow.AddMinutes(5);
            NextWatchListCheck  = DateTime.UtcNow.AddMinutes(5);
            NextUnassignedCheck = DateTime.UtcNow.AddMinutes(5);

            var liveMessages = await futClient.GetLiveMessage(); //Call only here no other part

            var unassignedData = await futClient.GetUnassignedItems();

            var tradeData = await futClient.GetTradePile();          //You can use Credits inside to update current credit when call it

            var watchlistData = await futClient.GetWatchList();      //You can use Credits inside to update current credit when call it

            var activeMessages = await futClient.GetActiveMessage(); //Call only here no other part

            Unassigned = unassignedData.ItemData;                    //DuplicateItemIdList should be use to know if you can send player to club
            TradePile  = tradeData.AuctionInfo;
            WatchList  = watchlistData.AuctionInfo;

            foreach (var message in liveMessages?.MessageList)
            {
                _logger.Log("IsLogged", "LiveMessage " + message.Renders.FirstOrDefault(i => i.Name == "bodyText").Value);
                await Task.Delay(FutManager.RandomNumber(30, 50) * 100);

                await futClient.CloseLiveMessage(message.MessageId);
            }

            foreach (var message in activeMessages?.ActiveMessage)
            {
                _logger.Log("IsLogged", "ActiveMessage You have Active Message message[" + message.Message + "] id[" + message.Id + "] rewardType[" + message.RewardType + "] rewardValue[" + message.RewardValue + "]");
                await Task.Delay(FutManager.RandomNumber(30, 50) * 100);

                await futClient.CloseActiveMessage(message.Id);
            }

            _logger.Log("IsLogged", "Logged");
            return(true);
        }