Exemplo n.º 1
0
        public void Serialize()
        {
            var monsterCollectionState = new MonsterCollectionState(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);
            var serialized             = (Dictionary)monsterCollectionState.Serialize();

            Assert.Equal(serialized, new MonsterCollectionState(serialized).Serialize());
        }
Exemplo n.º 2
0
        public void CalulateStep(long startedBlockIndex, long receivedBlockIndex, long blockIndex, int expectedStep)
        {
            var monsterCollectionState = new MonsterCollectionState(_address, 1, startedBlockIndex, _tableSheets.MonsterCollectionRewardSheet);
            var serialized             = (Dictionary)monsterCollectionState.Serialize();

            serialized             = serialized.SetItem(ReceivedBlockIndexKey, receivedBlockIndex.Serialize());
            monsterCollectionState = new MonsterCollectionState(serialized);
            Assert.Equal(expectedStep, monsterCollectionState.CalculateStep(blockIndex));
        }
Exemplo n.º 3
0
        public void Serialize_DotNet_API()
        {
            var monsterCollectionState = new MonsterCollectionState(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);
            var formatter = new BinaryFormatter();

            using var ms = new MemoryStream();
            formatter.Serialize(ms, monsterCollectionState);
            ms.Seek(0, SeekOrigin.Begin);

            var deserialized = (MonsterCollectionState)formatter.Deserialize(ms);

            Assert.Equal(monsterCollectionState.Serialize(), deserialized.Serialize());
        }
        public async Task MonsterCollectionStatus_MonsterCollectionState_Null(bool miner)
        {
            var userPrivateKey = new PrivateKey();
            var userAddress    = userPrivateKey.ToAddress();
            var service        = MakeMineChroniclesNodeService(userPrivateKey);

            StandaloneContextFx.NineChroniclesNodeService = service;
            StandaloneContextFx.BlockChain = service.Swarm !.BlockChain;
            if (!miner)
            {
                StandaloneContextFx.NineChroniclesNodeService.MinerPrivateKey = null;
            }
            var action = new CreateAvatar2
            {
                index = 0,
                hair  = 1,
                lens  = 2,
                ear   = 3,
                tail  = 4,
                name  = "action",
            };
            var blockChain  = StandaloneContextFx.BlockChain;
            var transaction = blockChain.MakeTransaction(userPrivateKey, new PolymorphicAction <ActionBase>[] { action });

            blockChain.StageTransaction(transaction);
            await blockChain.MineBlock(new PrivateKey());

            string queryArgs   = miner ? "" : $@"(address: ""{userAddress}"")";
            string query       = $@"query {{
                monsterCollectionStatus{queryArgs} {{
                    fungibleAssetValue {{
                        quantity
                        currency
                    }}
                    rewardInfos {{
                        itemId
                        quantity
                    }}
                }}
            }}";
            var    queryResult = await ExecuteQueryAsync(query);

            Assert.Single(queryResult.Errors);
            Assert.Equal(
                $"{nameof(MonsterCollectionState)} Address: {MonsterCollectionState.DeriveAddress(userAddress, 0)} is null.",
                queryResult.Errors.First().Message
                );
        }
Exemplo n.º 5
0
        public void Execute(int balance, int?prevLevel, int level, long blockIndex, Type exc, int?expectedStakings)
        {
            Address            monsterCollectionAddress = MonsterCollectionState.DeriveAddress(_signer, 0);
            Currency           currency   = _initialState.GetGoldCurrency();
            FungibleAssetValue balanceFav = currency * balance;
            FungibleAssetValue staked     = currency * 0;

            if (prevLevel is { } prevLevelNotNull)
            {
                List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[prevLevelNotNull].Rewards;
                var prevMonsterCollectionState = new MonsterCollectionState(
                    address: monsterCollectionAddress,
                    level: prevLevelNotNull,
                    blockIndex: 0,
                    monsterCollectionRewardSheet: _tableSheets.MonsterCollectionRewardSheet
                    );
                _initialState = _initialState.SetState(monsterCollectionAddress, prevMonsterCollectionState.Serialize());
                for (int i = 0; i < prevLevel; i++)
                {
                    MonsterCollectionSheet.Row row = _tableSheets.MonsterCollectionSheet[i + 1];
                    staked       += row.RequiredGold * currency;
                    _initialState = _initialState.MintAsset(monsterCollectionAddress, row.RequiredGold * currency);
                }
            }

            balanceFav -= staked;

            _initialState = _initialState.MintAsset(_signer, balanceFav);
            var action = new MonsterCollect
            {
                level = level,
            };

            if (exc is { } excType)
            {
                Assert.Throws(excType, () => action.Execute(new ActionContext
                {
                    PreviousStates = _initialState,
                    Signer         = _signer,
                    BlockIndex     = blockIndex,
                }));
            }
Exemplo n.º 6
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states                  = context.PreviousStates;
            Address            inventoryAddress        = avatarAddress.Derive(LegacyInventoryKey);
            Address            worldInformationAddress = avatarAddress.Derive(LegacyWorldInformationKey);
            Address            questListAddress        = avatarAddress.Derive(LegacyQuestListKey);

            if (context.Rehearsal)
            {
                return(states
                       .SetState(avatarAddress, MarkChanged)
                       .SetState(inventoryAddress, MarkChanged)
                       .SetState(worldInformationAddress, MarkChanged)
                       .SetState(questListAddress, MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 0), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 1), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 2), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 3), MarkChanged));
            }

            CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context);

            if (!states.TryGetAgentAvatarStatesV2(context.Signer, avatarAddress, out AgentState agentState, out AvatarState avatarState))
            {
                throw new FailedLoadStateException($"Aborted as the avatar state of the signer failed to load.");
            }

            Address collectionAddress = MonsterCollectionState.DeriveAddress(context.Signer, agentState.MonsterCollectionRound);

            if (!states.TryGetState(collectionAddress, out Dictionary stateDict))
            {
                throw new FailedLoadStateException($"Aborted as the monster collection state failed to load.");
            }

            var monsterCollectionState = new MonsterCollectionState(stateDict);
            List <MonsterCollectionRewardSheet.RewardInfo> rewards =
                monsterCollectionState.CalculateRewards(
                    states.GetSheet <MonsterCollectionRewardSheet>(),
                    context.BlockIndex
                    );

            if (rewards.Count == 0)
            {
                throw new RequiredBlockIndexException($"{collectionAddress} is not available yet");
            }

            Guid id     = context.Random.GenerateRandomGuid();
            var  result = new MonsterCollectionResult(id, avatarAddress, rewards);
            var  mail   = new MonsterCollectionMail(result, context.BlockIndex, id, context.BlockIndex);

            avatarState.Update(mail);

            ItemSheet itemSheet = states.GetItemSheet();

            foreach (MonsterCollectionRewardSheet.RewardInfo rewardInfo in rewards)
            {
                ItemSheet.Row row  = itemSheet[rewardInfo.ItemId];
                ItemBase      item = row is MaterialItemSheet.Row materialRow
                    ? ItemFactory.CreateTradableMaterial(materialRow)
                    : ItemFactory.CreateItem(row, context.Random);
                avatarState.inventory.AddItem2(item, rewardInfo.Quantity);
            }
            monsterCollectionState.Claim(context.BlockIndex);

            return(states
                   .SetState(avatarAddress, avatarState.SerializeV2())
                   .SetState(inventoryAddress, avatarState.inventory.Serialize())
                   .SetState(worldInformationAddress, avatarState.worldInformation.Serialize())
                   .SetState(questListAddress, avatarState.questList.Serialize())
                   .SetState(collectionAddress, monsterCollectionState.Serialize()));
        }
Exemplo n.º 7
0
        public async Task Query(int goldBalance, string decimalString)
        {
            const string query        = @"
            {
                address
                avatarStates {
                    address
                    name
                }
                gold
                monsterCollectionRound
                monsterCollectionLevel
                hasTradedItem
            }";
            var          goldCurrency = new Currency("NCG", 2, minter: null);
            var          agentState   = new AgentState(new Address());

            agentState.avatarAddresses[0] = Fixtures.AvatarAddress;

            Address monsterCollectionAddress = MonsterCollectionState.DeriveAddress(agentState.address, 0);
            MonsterCollectionState monsterCollectionState = new MonsterCollectionState(monsterCollectionAddress, 7, 0, Fixtures.TableSheetsFX.MonsterCollectionRewardSheet);

            IValue?GetStateMock(Address address)
            {
                if (GoldCurrencyState.Address == address)
                {
                    return(new GoldCurrencyState(goldCurrency).Serialize());
                }

                if (monsterCollectionAddress == address)
                {
                    return(monsterCollectionState.Serialize());
                }

                if (Fixtures.AvatarAddress == address)
                {
                    return(Fixtures.AvatarStateFX.Serialize());
                }

                return(null);
            }

            FungibleAssetValue GetBalanceMock(Address address, Currency currency)
            {
                if (address == agentState.address)
                {
                    return(new FungibleAssetValue(currency, goldBalance, 0));
                }

                return(FungibleAssetValue.FromRawValue(currency, 0));
            }

            var queryResult = await ExecuteQueryAsync <AgentStateType>(
                query,
                source : (
                    agentState,
                    (AccountStateGetter)GetStateMock,
                    (AccountBalanceGetter)GetBalanceMock)
                );

            var expected = new Dictionary <string, object>()
            {
                ["address"]      = agentState.address.ToString(),
                ["avatarStates"] = new List <Dictionary <string, object> >
                {
                    new Dictionary <string, object>
                    {
                        ["address"] = Fixtures.AvatarAddress.ToString(),
                        ["name"]    = Fixtures.AvatarStateFX.name,
                    },
                },
                ["gold"] = decimalString,
                ["monsterCollectionRound"] = 0L,
                ["monsterCollectionLevel"] = 7L,
                ["hasTradedItem"]          = false,
            };

            Assert.Equal(expected, queryResult.Data);
        }
Exemplo n.º 8
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states = context.PreviousStates;

            if (context.Rehearsal)
            {
                return(states
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 0), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 1), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 2), MarkChanged)
                       .SetState(MonsterCollectionState.DeriveAddress(context.Signer, 3), MarkChanged)
                       .SetState(context.Signer, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 0))
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 1))
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 2))
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, MonsterCollectionState.DeriveAddress(context.Signer, 3)));
            }

            MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();

            AgentState agentState = states.GetAgentState(context.Signer);

            if (agentState is null)
            {
                throw new FailedLoadStateException("Aborted as the agent state failed to load.");
            }

            if (level < 0 || level > 0 && !monsterCollectionSheet.TryGetValue(level, out MonsterCollectionSheet.Row _))
            {
                throw new MonsterCollectionLevelException();
            }

            Currency currency = states.GetGoldCurrency();
            // Set default gold value.
            FungibleAssetValue requiredGold             = currency * 0;
            Address            monsterCollectionAddress = MonsterCollectionState.DeriveAddress(
                context.Signer,
                agentState.MonsterCollectionRound
                );

            if (states.TryGetState(monsterCollectionAddress, out Dictionary stateDict))
            {
                var existingStates = new MonsterCollectionState(stateDict);
                int previousLevel  = existingStates.Level;
                // Check collection level and required block index
                if (level < previousLevel && existingStates.IsLocked(context.BlockIndex))
                {
                    throw new RequiredBlockIndexException();
                }

                if (level == previousLevel)
                {
                    throw new MonsterCollectionLevelException();
                }

                if (existingStates.CalculateStep(context.BlockIndex) > 0)
                {
                    throw new MonsterCollectionExistingClaimableException();
                }

                // Refund holding NCG to user
                FungibleAssetValue gold = states.GetBalance(monsterCollectionAddress, currency);
                states = states.TransferAsset(monsterCollectionAddress, context.Signer, gold);
            }

            if (level == 0)
            {
                return(states.SetState(monsterCollectionAddress, new Null()));
            }

            FungibleAssetValue balance = states.GetBalance(context.Signer, currency);
            var monsterCollectionState = new MonsterCollectionState(monsterCollectionAddress, level, context.BlockIndex);

            for (int i = 0; i < level; i++)
            {
                requiredGold += currency * monsterCollectionSheet[i + 1].RequiredGold;
            }

            if (balance < requiredGold)
            {
                throw new InsufficientBalanceException(context.Signer, requiredGold,
                                                       $"There is no sufficient balance for {context.Signer}: {balance} < {requiredGold}");
            }
            states = states.TransferAsset(context.Signer, monsterCollectionAddress, requiredGold);
            states = states.SetState(monsterCollectionAddress, monsterCollectionState.Serialize());
            return(states);
        }
Exemplo n.º 9
0
        public void IsLocked(long blockIndex, bool expected)
        {
            var monsterCollectionState = new MonsterCollectionState(_address, 1, 0);

            Assert.Equal(expected, monsterCollectionState.IsLocked(blockIndex));
        }