public async Task GetTx() { var userPrivateKey = new PrivateKey(); var queryFormat = @"query {{ getTx(txId: ""{0}"") {{ id nonce signer signature timestamp updatedAddresses actions {{ inspection }} }} }}"; var queryResult = await ExecuteAsync(string.Format(queryFormat, new TxId())); Assert.Equal( new Dictionary <string, object?> { ["getTx"] = null }, queryResult.Data ); var action = new CreateAvatar2 { index = 0, hair = 1, lens = 2, ear = 3, tail = 4, name = "action", }; var transaction = _blockChain.MakeTransaction(userPrivateKey, new PolymorphicAction <ActionBase>[] { action }); _blockChain.StageTransaction(transaction); await _blockChain.MineBlock(new PrivateKey()); queryResult = await ExecuteAsync(string.Format(queryFormat, transaction.Id)); var tx = queryResult.Data .As <Dictionary <string, object> >()["getTx"] .As <Dictionary <string, object> >(); Assert.Equal(tx["id"], transaction.Id.ToString()); Assert.Equal(tx["nonce"], transaction.Nonce); Assert.Equal(tx["signer"], transaction.Signer.ToString()); Assert.Equal(tx["signature"], ByteUtil.Hex(transaction.Signature)); Assert.Equal(tx["timestamp"], transaction.Timestamp.ToString()); Assert.Equal(tx["updatedAddresses"], transaction.UpdatedAddresses.Select(a => a.ToString())); var plainValue = tx["actions"] .As <List <object> >() .First() .As <Dictionary <string, object> >()["inspection"]; Assert.Equal(transaction.Actions.First().PlainValue.Inspection, plainValue); }
public void Execute() { var action = new CreateAvatar2() { index = 0, hair = 0, ear = 0, lens = 0, tail = 0, name = "test", }; var gold = new GoldCurrencyState(new Currency("NCG", 2, minter: null)); var ranking = new RankingState0(); for (var i = 0; i < RankingState0.RankingMapCapacity; i++) { ranking.RankingMap[RankingState0.Derive(i)] = new HashSet <Address>().ToImmutableHashSet(); } var sheets = TableSheetsImporter.ImportSheets(); var state = new State() .SetState(GoldCurrencyState.Address, gold.Serialize()) .SetState( Addresses.GoldDistribution, GoldDistributionTest.Fixture.Select(v => v.Serialize()).Serialize() ) .SetState( Addresses.GameConfig, new GameConfigState(sheets[nameof(GameConfigSheet)]).Serialize() ) .SetState(Addresses.Ranking, ranking.Serialize()) .MintAsset(GoldCurrencyState.Address, gold.Currency * 100000000000); foreach (var(key, value) in sheets) { state = state.SetState(Addresses.TableSheet.Derive(key), value.Serialize()); } var nextState = action.Execute(new ActionContext() { PreviousStates = state, Signer = _agentAddress, BlockIndex = 0, }); Assert.Equal( 0, nextState.GetBalance(default, gold.Currency).MajorUnit
public async Task ClaimMonsterCollectionReward() { var playerPrivateKey = StandaloneContextFx.NineChroniclesNodeService !.MinerPrivateKey !; var avatarAddress = playerPrivateKey.ToAddress(); string query = $@"mutation {{ action {{ claimMonsterCollectionReward(avatarAddress: ""{avatarAddress}"") }} }}"; PolymorphicAction <ActionBase> createAvatar = new CreateAvatar2 { index = 0, hair = 0, lens = 0, ear = 0, tail = 0, name = "avatar", }; BlockChain.MakeTransaction(playerPrivateKey, new[] { createAvatar }); await BlockChain.MineBlock(playerPrivateKey.ToAddress()); Assert.NotNull(BlockChain.GetState(playerPrivateKey.ToAddress())); var result = await ExecuteQueryAsync(query); Assert.Null(result.Errors); var txIds = BlockChain.GetStagedTransactionIds(); Assert.Single(txIds); var tx = BlockChain.GetTransaction(txIds.First()); var expected = new Dictionary <string, object> { ["action"] = new Dictionary <string, object> { ["claimMonsterCollectionReward"] = tx.Id.ToString(), } }; Assert.Equal(expected, result.Data); Assert.Single(tx.Actions); var action = (ClaimMonsterCollectionReward)tx.Actions.First().InnerAction; Assert.Equal(avatarAddress, action.avatarAddress); Assert.Equal(0, action.collectionRound); }
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 ); }
public async Task MonsterCollect() { const string query = @"mutation { action { monsterCollect(level: 1) } }"; PolymorphicAction <ActionBase> createAvatar = new CreateAvatar2 { index = 0, hair = 0, lens = 0, ear = 0, tail = 0, name = "avatar", }; var playerPrivateKey = StandaloneContextFx.NineChroniclesNodeService !.MinerPrivateKey !; BlockChain.MakeTransaction(playerPrivateKey, new[] { createAvatar }); await BlockChain.MineBlock(playerPrivateKey.ToAddress()); Assert.NotNull(BlockChain.GetState(playerPrivateKey.ToAddress())); var result = await ExecuteQueryAsync(query); Assert.Null(result.Errors); var txIds = BlockChain.GetStagedTransactionIds(); Assert.Single(txIds); var tx = BlockChain.GetTransaction(txIds.First()); var expected = new Dictionary <string, object> { ["action"] = new Dictionary <string, object> { ["monsterCollect"] = tx.Id.ToString(), } }; Assert.Equal(expected, result.Data); Assert.Single(tx.Actions); var action = (MonsterCollect)tx.Actions.First().InnerAction; Assert.Equal(1, action.level); }
public async Task Avatar() { var userPrivateKey = new PrivateKey(); var userAddress = userPrivateKey.ToAddress(); var service = MakeMineChroniclesNodeService(userPrivateKey); StandaloneContextFx.NineChroniclesNodeService = service; StandaloneContextFx.BlockChain = service.Swarm !.BlockChain; 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()); var avatarAddress = userAddress.Derive( string.Format( CultureInfo.InvariantCulture, CreateAvatar2.DeriveFormat, 0 ) ); string query = $@"query {{ stateQuery {{ avatar(avatarAddress: ""{avatarAddress}"") {{ name }} }} }}"; var queryResult = await ExecuteQueryAsync(query); Assert.Null(queryResult.Errors); }
public IObservable <ActionBase.ActionEvaluation <CreateAvatar2> > CreateAvatar(int index, string nickName, int hair = 0, int lens = 0, int ear = 0, int tail = 0) { if (States.Instance.AvatarStates.ContainsKey(index)) { throw new Exception($"Already contains {index} in {States.Instance.AvatarStates}"); } var action = new CreateAvatar2 { index = index, hair = hair, lens = lens, ear = ear, tail = tail, name = nickName, }; ProcessAction(action); return(_renderer.EveryRender <CreateAvatar2>() .SkipWhile(eval => !eval.Action.Id.Equals(action.Id)) .Take(1) .Last() .ObserveOnMainThread() .Timeout(ActionTimeout) .DoOnError(e => HandleException(action.Id, e)) .Finally(() => { var agentAddress = States.Instance.AgentState.address; var avatarAddress = agentAddress.Derive( string.Format( CultureInfo.InvariantCulture, CreateAvatar2.DeriveFormat, index ) ); Dialog.DeleteDialogPlayerPrefs(avatarAddress); })); }
public async Task CreateUnsignedTx() { var privateKey = new PrivateKey(); PublicKey publicKey = privateKey.PublicKey; Address signer = publicKey.ToAddress(); long nonce = _blockChain.GetNextTxNonce(signer); NCAction action = new CreateAvatar2 { index = 0, hair = 1, lens = 2, ear = 3, tail = 4, name = "action", }; var codec = new Codec(); var queryFormat = @"query {{ createUnsignedTx(publicKey: ""{0}"", plainValue: ""{1}"") }}"; var queryResult = await ExecuteAsync(string.Format( queryFormat, Convert.ToBase64String(publicKey.Format(false)), Convert.ToBase64String(codec.Encode(action.PlainValue)))); var base64EncodedUnsignedTx = (string)queryResult.Data .As <Dictionary <string, object> >()["createUnsignedTx"]; Transaction <NCAction> unsignedTx = Transaction <NCAction> .Deserialize(Convert.FromBase64String(base64EncodedUnsignedTx), validate : false); Assert.Empty(unsignedTx.Signature); Assert.Equal(publicKey, unsignedTx.PublicKey); Assert.Equal(signer, unsignedTx.Signer); Assert.Equal(nonce, unsignedTx.Nonce); Assert.Contains(signer, unsignedTx.UpdatedAddresses); }
public ActionMutation(NineChroniclesNodeService service) { Field <NonNullGraphType <TxIdType> >("createAvatar", description: "Create new avatar.", arguments: new QueryArguments( new QueryArgument <NonNullGraphType <StringGraphType> > { Name = "avatarName", Description = "Avatar name." }, new QueryArgument <NonNullGraphType <IntGraphType> > { Name = "avatarIndex", Description = "The index of character slot. 0 ~ 2" }, new QueryArgument <NonNullGraphType <IntGraphType> > { Name = "hairIndex", Description = "The index of character hair color. 0 ~ 8" }, new QueryArgument <NonNullGraphType <IntGraphType> > { Name = "lensIndex", Description = "The index of character eye color. 0 ~ 8" }, new QueryArgument <NonNullGraphType <IntGraphType> > { Name = "earIndex", Description = "The index of character ear color. 0 ~ 8" }, new QueryArgument <NonNullGraphType <IntGraphType> > { Name = "tailIndex", Description = "The index of character tail color. 0 ~ 8" } ), resolve: context => { try { if (!(service.MinerPrivateKey is { } privateKey)) { throw new InvalidOperationException($"{nameof(service.MinerPrivateKey)} is null."); } if (!(service.Swarm?.BlockChain is { } blockChain)) { throw new InvalidOperationException($"{nameof(service.Swarm.BlockChain)} is null."); } var avatarName = context.GetArgument <string>("avatarName"); var avatarIndex = context.GetArgument <int>("avatarIndex"); var hairIndex = context.GetArgument <int>("hairIndex"); var lensIndex = context.GetArgument <int>("lensIndex"); var earIndex = context.GetArgument <int>("earIndex"); var tailIndex = context.GetArgument <int>("tailIndex"); var action = new CreateAvatar2 { index = avatarIndex, hair = hairIndex, lens = lensIndex, ear = earIndex, tail = tailIndex, name = avatarName, }; var actions = new NCAction[] { action }; Transaction <NCAction> tx = blockChain.MakeTransaction(privateKey, actions); return(tx.Id); }