public static async Task <CoroutineResult> TransmuteMaterials(CurrencyType from, CurrencyType to)
        {
            if (!ZetaDia.IsInTown)
            {
                return(CoroutineResult.NoAction);
            }

            if (!CurrencyConversionTypes.Contains(to) || !CurrencyConversionTypes.Contains(from))
            {
                Core.Logger.Log($"[{nameof(TransmuteMaterials)}] Unable to convert from '{from}' to '{to}'");
                return(CoroutineResult.NoAction);
            }

            if (!IsMaterialTransmutationPossible(from, to))
            {
                return(CoroutineResult.NoAction);
            }

            var item   = GetSacraficialItems(to).First();
            var recipe = GetRecipeFromCurrency(from);

            if (await TransmuteRecipe(recipe, item) == CoroutineResult.Running)
            {
                return(CoroutineResult.Running);
            }

            Core.Logger.Log($"[{nameof(TransmuteMaterials)}] Converted from '{from}' to '{to}'");
            return(CoroutineResult.Done);
        }
        /// <summary>
        /// Converts crafting materials into other types of crafting materials
        /// </summary>
        /// <param name="from">the type of material you will consume</param>
        /// <param name="to">the type of material you will get more of</param>
        public static async Task <bool> Execute(CurrencyType from, CurrencyType to)
        {
            Core.Logger.Log("[ConvertMaterials] Wooo! Lets convert some {0} to {1}", from, to);

            if (!ZetaDia.IsInGame || !ZetaDia.IsInTown)
            {
                return(false);
            }

            if (!CurrencyConversionTypes.Contains(to) || !CurrencyConversionTypes.Contains(from))
            {
                Core.Logger.Log("[Cube] Unable to convert from {0} to {1}", from, to);
                return(false);
            }

            var fromAmount       = GetCurrency(from);
            var toAmount         = GetCurrency(to);
            var sacraficialItems = GetSacraficialItems(to);

            Core.Logger.Verbose($"[ConvertMaterials] Starting Material Counts DeathsBreath={Core.Inventory.Currency.DeathsBreath} {from}={fromAmount} {to}={toAmount} SacraficialItems={sacraficialItems.Count}");

            while (CanRun(from, to))
            {
                var item   = GetSacraficialItems(to).First();
                var recipe = GetRecipeFromCurrency(from);

                await Transmute.Execute(item, recipe);

                await Coroutine.Yield();

                Core.Update();

                var newToAmount = GetCurrency(to);
                if (newToAmount > toAmount)
                {
                    Core.Logger.Log("[ConvertMaterials] Converted materials '{0}' ---> '{1}'", from, to);
                    toAmount            = newToAmount;
                    fromAmount          = GetCurrency(from);
                    ConsecutiveFailures = 0;
                    Core.Inventory.InvalidAnnIds.Add(item.AnnId);
                }
                else
                {
                    ConsecutiveFailures++;
                    if (ConsecutiveFailures > 3)
                    {
                        Core.Inventory.InvalidAnnIds.Add(item.AnnId);
                    }
                    Core.Logger.Error("[ConvertMaterials] Failed to convert materials");
                    return(false);
                }

                await Coroutine.Yield();
            }

            Core.Logger.Verbose($"[ConvertMaterials] Finishing Material Counts DeathsBreath={Core.Inventory.Currency.DeathsBreath} {from}={fromAmount} {to}={toAmount} SacraficialItems={sacraficialItems.Count}");

            return(true);
        }