public void Execute( ItemType itemType, bool orderExist, int itemCount, bool backward ) { var avatarState = _initialState.GetAvatarState(_avatarAddress); ITradableItem tradableItem; switch (itemType) { case ItemType.Consumable: tradableItem = ItemFactory.CreateItemUsable( _tableSheets.ConsumableItemSheet.First, Guid.NewGuid(), 0); break; case ItemType.Costume: tradableItem = ItemFactory.CreateCostume( _tableSheets.CostumeItemSheet.First, Guid.NewGuid()); break; case ItemType.Equipment: tradableItem = ItemFactory.CreateItemUsable( _tableSheets.EquipmentItemSheet.First, Guid.NewGuid(), 0); break; case ItemType.Material: var tradableMaterialRow = _tableSheets.MaterialItemSheet.OrderedList .First(row => row.ItemSubType == ItemSubType.Hourglass); tradableItem = ItemFactory.CreateTradableMaterial(tradableMaterialRow); break; default: throw new ArgumentOutOfRangeException(nameof(itemType), itemType, null); } Assert.Equal(0, tradableItem.RequiredBlockIndex); avatarState.inventory.AddItem2((ItemBase)tradableItem, itemCount); var previousStates = _initialState; if (backward) { previousStates = previousStates.SetState(_avatarAddress, avatarState.Serialize()); } else { previousStates = previousStates .SetState(_avatarAddress.Derive(LegacyInventoryKey), avatarState.inventory.Serialize()) .SetState(_avatarAddress.Derive(LegacyWorldInformationKey), avatarState.worldInformation.Serialize()) .SetState(_avatarAddress.Derive(LegacyQuestListKey), avatarState.questList.Serialize()) .SetState(_avatarAddress, avatarState.SerializeV2()); } var currencyState = previousStates.GetGoldCurrency(); var price = new FungibleAssetValue(currencyState, ProductPrice, 0); var orderId = new Guid("6f460c1a755d48e4ad6765d5f519dbc8"); var existOrderId = new Guid("229e5f8c-fabe-4c04-bab9-45325cfa69a4"); var orderAddress = Order.DeriveAddress(orderId); var shardedShopAddress = ShardedShopStateV2.DeriveAddress( tradableItem.ItemSubType, orderId); long blockIndex = 1; if (orderExist) { var shardedShopState = new ShardedShopStateV2(shardedShopAddress); var existOrder = OrderFactory.Create( _agentAddress, _avatarAddress, existOrderId, price, tradableItem.TradableId, 0, tradableItem.ItemSubType, 1 ); existOrder.Sell2(avatarState); blockIndex = existOrder.ExpiredBlockIndex; shardedShopState.Add(existOrder.Digest2(avatarState, _tableSheets.CostumeStatSheet), blockIndex); Assert.Single(shardedShopState.OrderDigestList); previousStates = previousStates.SetState( shardedShopAddress, shardedShopState.Serialize()); } else { Assert.Null(previousStates.GetState(shardedShopAddress)); } var sellAction = new Sell7 { sellerAvatarAddress = _avatarAddress, tradableId = tradableItem.TradableId, count = itemCount, price = price, itemSubType = tradableItem.ItemSubType, orderId = orderId, }; var nextState = sellAction.Execute(new ActionContext { BlockIndex = blockIndex, PreviousStates = previousStates, Rehearsal = false, Signer = _agentAddress, Random = new TestRandom(), }); long expiredBlockIndex = Order.ExpirationInterval + blockIndex; // Check AvatarState and Inventory var nextAvatarState = nextState.GetAvatarStateV2(_avatarAddress); Assert.Single(nextAvatarState.inventory.Items); Assert.True(nextAvatarState.inventory.TryGetTradableItems( tradableItem.TradableId, expiredBlockIndex, 1, out var inventoryItems)); Assert.Single(inventoryItems); ITradableItem nextTradableItem = (ITradableItem)inventoryItems.First().item; Assert.Equal(expiredBlockIndex, nextTradableItem.RequiredBlockIndex); // Check ShardedShopState var nextSerializedShardedShopState = nextState.GetState(shardedShopAddress); Assert.NotNull(nextSerializedShardedShopState); var nextShardedShopState = new ShardedShopStateV2((Dictionary)nextSerializedShardedShopState); var expectedCount = orderExist ? 2 : 1; Assert.Equal(expectedCount, nextShardedShopState.OrderDigestList.Count); var orderDigest = nextShardedShopState.OrderDigestList.First(o => o.OrderId.Equals(orderId)); Assert.Equal(price, orderDigest.Price); Assert.Equal(blockIndex, orderDigest.StartedBlockIndex); Assert.Equal(expiredBlockIndex, orderDigest.ExpiredBlockIndex); Assert.Equal(((ItemBase)tradableItem).Id, orderDigest.ItemId); Assert.Equal(tradableItem.TradableId, orderDigest.TradableId); var serializedOrder = nextState.GetState(orderAddress); Assert.NotNull(serializedOrder); var serializedItem = nextState.GetState(Addresses.GetItemAddress(tradableItem.TradableId)); Assert.NotNull(serializedItem); var order = OrderFactory.Deserialize((Dictionary)serializedOrder); ITradableItem orderItem = (ITradableItem)ItemFactory.Deserialize((Dictionary)serializedItem); Assert.Equal(price, order.Price); Assert.Equal(orderId, order.OrderId); Assert.Equal(tradableItem.TradableId, order.TradableId); Assert.Equal(blockIndex, order.StartedBlockIndex); Assert.Equal(expiredBlockIndex, order.ExpiredBlockIndex); Assert.Equal(_agentAddress, order.SellerAgentAddress); Assert.Equal(_avatarAddress, order.SellerAvatarAddress); Assert.Equal(expiredBlockIndex, orderItem.RequiredBlockIndex); var mailList = nextAvatarState.mailBox.OfType <OrderExpirationMail>().ToList(); Assert.Single(mailList); var mail = mailList.First(); Assert.NotNull(mail); Assert.Equal(expiredBlockIndex, mail.requiredBlockIndex); Assert.Equal(orderId, mail.OrderId); var receiptDict = nextState.GetState(OrderDigestListState.DeriveAddress(_avatarAddress)); Assert.NotNull(receiptDict); var orderDigestList = new OrderDigestListState((Dictionary)receiptDict); Assert.Single(orderDigestList.OrderDigestList); OrderDigest orderDigest2 = orderDigestList.OrderDigestList.First(); Assert.Equal(orderDigest, orderDigest2); }
public void Execute( ItemType itemType, string guid, int itemCount, int inventoryCount, int expectedCount, bool fromPreviousAction, bool legacy ) { var avatarState = _initialState.GetAvatarState(_avatarAddress); ITradableItem tradableItem; var itemId = new Guid(guid); var orderId = Guid.NewGuid(); var updateSellOrderId = Guid.NewGuid(); ItemSubType itemSubType; const long requiredBlockIndex = Order.ExpirationInterval; switch (itemType) { case ItemType.Equipment: { var itemUsable = ItemFactory.CreateItemUsable( _tableSheets.EquipmentItemSheet.First, itemId, requiredBlockIndex); tradableItem = itemUsable; itemSubType = itemUsable.ItemSubType; break; } case ItemType.Costume: { var costume = ItemFactory.CreateCostume(_tableSheets.CostumeItemSheet.First, itemId); costume.Update(requiredBlockIndex); tradableItem = costume; itemSubType = costume.ItemSubType; break; } default: { var material = ItemFactory.CreateTradableMaterial( _tableSheets.MaterialItemSheet.OrderedList.First(r => r.ItemSubType == ItemSubType.Hourglass)); itemSubType = material.ItemSubType; material.RequiredBlockIndex = requiredBlockIndex; tradableItem = material; break; } } var shardedShopAddress = ShardedShopStateV2.DeriveAddress(itemSubType, orderId); var shopState = new ShardedShopStateV2(shardedShopAddress); var order = OrderFactory.Create( _agentAddress, _avatarAddress, orderId, new FungibleAssetValue(_goldCurrencyState.Currency, 100, 0), tradableItem.TradableId, requiredBlockIndex, itemSubType, itemCount ); var orderDigestList = new OrderDigestListState(OrderDigestListState.DeriveAddress(_avatarAddress)); var prevState = _initialState; if (inventoryCount > 1) { for (int i = 0; i < inventoryCount; i++) { // Different RequiredBlockIndex for divide inventory slot. if (tradableItem is ITradableFungibleItem tradableFungibleItem) { var tradable = (TradableMaterial)tradableFungibleItem.Clone(); tradable.RequiredBlockIndex = tradableItem.RequiredBlockIndex - i; avatarState.inventory.AddItem2(tradable, 2 - i); } } } else { avatarState.inventory.AddItem2((ItemBase)tradableItem, itemCount); } var sellItem = legacy ? order.Sell2(avatarState) : order.Sell3(avatarState); var orderDigest = legacy ? order.Digest2(avatarState, _tableSheets.CostumeStatSheet) : order.Digest(avatarState, _tableSheets.CostumeStatSheet); shopState.Add(orderDigest, requiredBlockIndex); orderDigestList.Add(orderDigest); if (legacy) { Assert.True(avatarState.inventory.TryGetTradableItems(itemId, requiredBlockIndex * 2, itemCount, out _)); } else { Assert.True(avatarState.inventory.TryGetLockedItem(new OrderLock(orderId), out _)); } Assert.Equal(inventoryCount, avatarState.inventory.Items.Count); Assert.Equal(expectedCount, avatarState.inventory.Items.Sum(i => i.count)); Assert.Single(shopState.OrderDigestList); Assert.Single(orderDigestList.OrderDigestList); Assert.Equal(requiredBlockIndex * 2, sellItem.RequiredBlockIndex); if (fromPreviousAction) { prevState = prevState.SetState(_avatarAddress, avatarState.Serialize()); } else { prevState = prevState .SetState(_avatarAddress.Derive(LegacyInventoryKey), avatarState.inventory.Serialize()) .SetState(_avatarAddress.Derive(LegacyWorldInformationKey), avatarState.worldInformation.Serialize()) .SetState(_avatarAddress.Derive(LegacyQuestListKey), avatarState.questList.Serialize()) .SetState(_avatarAddress, avatarState.SerializeV2()); } prevState = prevState .SetState(Addresses.GetItemAddress(itemId), sellItem.Serialize()) .SetState(Order.DeriveAddress(order.OrderId), order.Serialize()) .SetState(orderDigestList.Address, orderDigestList.Serialize()) .SetState(shardedShopAddress, shopState.Serialize()); var currencyState = prevState.GetGoldCurrency(); var price = new FungibleAssetValue(currencyState, ProductPrice, 0); var action = new UpdateSell0 { orderId = orderId, updateSellOrderId = updateSellOrderId, tradableId = itemId, sellerAvatarAddress = _avatarAddress, itemSubType = itemSubType, price = price, count = itemCount, }; var nextState = action.Execute(new ActionContext { BlockIndex = 101, PreviousStates = prevState, Random = new TestRandom(), Rehearsal = false, Signer = _agentAddress, }); var updateSellShopAddress = ShardedShopStateV2.DeriveAddress(itemSubType, updateSellOrderId); var nextShopState = new ShardedShopStateV2((Dictionary)nextState.GetState(updateSellShopAddress)); Assert.Equal(1, nextShopState.OrderDigestList.Count); Assert.NotEqual(orderId, nextShopState.OrderDigestList.First().OrderId); Assert.Equal(updateSellOrderId, nextShopState.OrderDigestList.First().OrderId); Assert.Equal(itemId, nextShopState.OrderDigestList.First().TradableId); Assert.Equal(requiredBlockIndex + 101, nextShopState.OrderDigestList.First().ExpiredBlockIndex); }