Ejemplo n.º 1
0
        public async Task TransferGold()
        {
            NineChroniclesNodeService service = StandaloneContextFx.NineChroniclesNodeService !;
            Currency goldCurrency             = new GoldCurrencyState(
                (Dictionary)BlockChain.GetState(GoldCurrencyState.Address)
                ).Currency;

            Address senderAddress = service.MinerPrivateKey !.ToAddress();

            var store = service.Store;
            await BlockChain.MineBlock(service.MinerPrivateKey);

            await BlockChain.MineBlock(service.MinerPrivateKey);

            // 10 + 10 (mining rewards)
            Assert.Equal(
                20 * goldCurrency,
                BlockChain.GetBalance(senderAddress, goldCurrency)
                );

            var             recipientKey = new PrivateKey();
            Address         recipient    = recipientKey.ToAddress();
            var             query        = $"mutation {{ transferGold(recipient: \"{recipient}\", amount: \"17.5\") }}";
            ExecutionResult result       = await ExecuteQueryAsync(query);

            var stagedTxIds = BlockChain.GetStagedTransactionIds().ToImmutableList();

            Assert.Single(stagedTxIds);

            var expectedResult = new Dictionary <string, object>
            {
                ["transferGold"] = stagedTxIds.Single().ToString(),
            };

            Assert.Null(result.Errors);
            Assert.Equal(expectedResult, result.Data);

            await BlockChain.MineBlock(recipientKey);

            // 10 + 10 - 17.5(transfer)
            Assert.Equal(
                FungibleAssetValue.Parse(goldCurrency, "2.5"),
                BlockChain.GetBalance(senderAddress, goldCurrency)
                );

            // 0 + 17.5(transfer) + 10(mining reward)
            Assert.Equal(
                FungibleAssetValue.Parse(goldCurrency, "27.5"),
                BlockChain.GetBalance(recipient, goldCurrency)
                );
        }
Ejemplo n.º 2
0
        public int TransferAsset(
            [Argument("SENDER-ADDRESS", Description = "A hex-encoded sender address.")] string senderAddress,
            [Argument("RECIPIENT-ADDRESS", Description = "A hex-encoded recipient address.")] string recipientAddress,
            [Argument("AMOUNT", Description = "The amount of asset to transfer.")]  string amount,
            [Argument("PATH", Description = "A file path of base64 encoded action.")] string?filePath = null,
            [Argument("MEMO", Description = "A memo of asset transfer")] string?memo = null
            )
        {
            try
            {
                filePath ??= Path.Combine(Path.GetTempPath(), Path.GetTempFileName());

                // Minter for 9c-mainnet
                var currency = new Currency("NCG", 2, minter: new Address("47d082a115c63e7b58b1532d20e631538eafadde"));
                FungibleAssetValue amountFungibleAssetValue =
                    FungibleAssetValue.Parse(currency, amount);
                Address sender    = new Address(ByteUtil.ParseHex(senderAddress));
                Address recipient = new Address(ByteUtil.ParseHex(recipientAddress));
                Nekoyume.Action.TransferAsset action = new TransferAsset(
                    sender,
                    recipient,
                    amountFungibleAssetValue,
                    memo);

                var encoded = new List(
                    new[]
                {
                    (Text)nameof(Nekoyume.Action.TransferAsset),
                    action.PlainValue
                }
                    );

                byte[] raw = Codec.Encode(encoded);
                File.WriteAllText(filePath, Convert.ToBase64String(raw));
                Console.Write(Convert.ToBase64String(raw));
                return(0);
            }
            catch (Exception e)
            {
                _console.Error.WriteLine(e);
                return(-1);
            }
        }
Ejemplo n.º 3
0
        public IAccountStateDelta MinerReward(IActionContext ctx, IAccountStateDelta states)
        {
            // 마이닝 보상
            // https://www.notion.so/planetarium/Mining-Reward-b7024ef463c24ebca40a2623027d497d
            Currency           currency            = states.GetGoldCurrency();
            FungibleAssetValue defaultMiningReward = currency * 10;
            var countOfHalfLife             = (int)Math.Pow(2, Convert.ToInt64((ctx.BlockIndex - 1) / 12614400));
            FungibleAssetValue miningReward =
                defaultMiningReward.DivRem(countOfHalfLife, out FungibleAssetValue _);

            if (miningReward >= FungibleAssetValue.Parse(currency, "1.25"))
            {
                states = states.TransferAsset(
                    GoldCurrencyState.Address,
                    ctx.Miner,
                    miningReward
                    );
            }

            return(states);
        }
Ejemplo n.º 4
0
        public async Task Transfer(string?memo, bool error)
        {
            NineChroniclesNodeService service = StandaloneContextFx.NineChroniclesNodeService !;
            Currency goldCurrency             = new GoldCurrencyState(
                (Dictionary)BlockChain.GetState(GoldCurrencyState.Address)
                ).Currency;

            Address senderAddress = service.MinerPrivateKey !.ToAddress();
            var     store         = service.Store;
            await BlockChain.MineBlock(senderAddress);

            await BlockChain.MineBlock(senderAddress);

            // 10 + 10 (mining rewards)
            Assert.Equal(
                20 * goldCurrency,
                BlockChain.GetBalance(senderAddress, goldCurrency)
                );

            Address recipient = new PrivateKey().ToAddress();
            long    txNonce   = BlockChain.GetNextTxNonce(senderAddress);

            var args = $"recipient: \"{recipient}\", txNonce: {txNonce}, amount: \"17.5\"";

            if (!(memo is null))
            {
                args += $"memo: \"{memo}\"";
            }

            var             query  = $"mutation {{ transfer({args}) }}";
            ExecutionResult result = await ExecuteQueryAsync(query);

            if (error)
            {
                Assert.NotNull(result.Errors);
            }
            else
            {
                Assert.Null(result.Errors);

                var stagedTxIds = BlockChain.GetStagedTransactionIds().ToImmutableList();
                Assert.Single(stagedTxIds);
                string transferTxIdString = stagedTxIds.Single().ToString();
                TxId   transferTxId       = new TxId(ByteUtil.ParseHex(transferTxIdString));

                Transaction <NCAction>?tx = BlockChain.StagePolicy.Get(BlockChain, transferTxId, false);
                Assert.NotNull(tx);
                Assert.IsType <TransferAsset>(tx !.Actions.Single().InnerAction);
                TransferAsset transferAsset = (TransferAsset)tx.Actions.Single().InnerAction;
                Assert.Equal(memo, transferAsset.Memo);

                var expectedResult = new Dictionary <string, object>
                {
                    ["transfer"] = transferTxIdString,
                };

                Assert.Equal(expectedResult, result.Data);

                await BlockChain.MineBlock(recipient);

                // 10 + 10 - 17.5(transfer)
                Assert.Equal(
                    FungibleAssetValue.Parse(goldCurrency, "2.5"),
                    BlockChain.GetBalance(senderAddress, goldCurrency)
                    );

                // 0 + 17.5(transfer) + 10(mining reward)
                Assert.Equal(
                    FungibleAssetValue.Parse(goldCurrency, "27.5"),
                    BlockChain.GetBalance(recipient, goldCurrency)
                    );
            }
        }
Ejemplo n.º 5
0
        public void Parse()
        {
            Currency        baz = new Currency("BAZ", 1, minter: null);
            FormatException e;

            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "abc"));
            Assert.StartsWith("The value string must consist of digits", e.Message);

            const string signError = "Plus (+) or minus (-) sign can be appeared only at";

            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "++123"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "--123"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "++123.45"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "--123.45"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "23.4-5"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "45.6+7"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "2-3"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "45+6"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "+12-3"));
            Assert.StartsWith(signError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "-45+6"));
            Assert.StartsWith(signError, e.Message);

            const string decimalSeparatorError = "The decimal separator (.) cannot be appeared";

            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "123..4"));
            Assert.Contains(decimalSeparatorError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "123.4.5"));
            Assert.Contains(decimalSeparatorError, e.Message);

            const string decimalsError = "does not allow more than";

            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(FOO, "123.456"));
            Assert.Contains(decimalsError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(BAR, "123.0"));
            Assert.Contains(decimalsError, e.Message);
            e = Assert.Throws <FormatException>(() => FungibleAssetValue.Parse(baz, "123.12"));
            Assert.Contains(decimalsError, e.Message);

            Assert.Equal(
                new FungibleAssetValue(FOO, 123, 45),
                FungibleAssetValue.Parse(FOO, "123.45")
                );
            Assert.Equal(
                new FungibleAssetValue(FOO, 123, 45),
                FungibleAssetValue.Parse(FOO, "+123.45")
                );
            Assert.Equal(
                new FungibleAssetValue(FOO, -123, 45),
                FungibleAssetValue.Parse(FOO, "-123.45")
                );
            Assert.Equal(
                new FungibleAssetValue(FOO, 123, 40),
                FungibleAssetValue.Parse(FOO, "123.4")
                );
            Assert.Equal(
                new FungibleAssetValue(FOO, 123, 40),
                FungibleAssetValue.Parse(FOO, "+123.4")
                );
            Assert.Equal(
                new FungibleAssetValue(FOO, -123, 40),
                FungibleAssetValue.Parse(FOO, "-123.4")
                );
            Assert.Equal(new FungibleAssetValue(FOO, 123, 0), FungibleAssetValue.Parse(FOO, "123"));
            Assert.Equal(new FungibleAssetValue(FOO, 12, 0), FungibleAssetValue.Parse(FOO, "+12"));
            Assert.Equal(new FungibleAssetValue(FOO, -12, 0), FungibleAssetValue.Parse(FOO, "-12"));
        }
        public StandaloneMutation(StandaloneContext standaloneContext)
        {
            Field <KeyStoreMutation>(
                name: "keyStore",
                resolve: context => standaloneContext.KeyStore);

            Field <ActivationStatusMutation>(
                name: "activationStatus",
                resolve: context => standaloneContext.NineChroniclesNodeService);

            Field <ActionMutation>(
                name: "action",
                resolve: context => standaloneContext.NineChroniclesNodeService);

            Field <NonNullGraphType <BooleanGraphType> >(
                name: "stageTx",
                description: "Add a new transaction to staging",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name        = "payload",
                Description = "Hex-encoded bytes for new transaction."
            }
                    ),
                resolve: context =>
            {
                try
                {
                    byte[] bytes = ByteUtil.ParseHex(context.GetArgument <string>("payload"));
                    Transaction <NCAction> tx         = Transaction <NCAction> .Deserialize(bytes);
                    NineChroniclesNodeService service = standaloneContext.NineChroniclesNodeService;
                    BlockChain <NCAction> blockChain  = service.Swarm.BlockChain;

                    if (blockChain.Policy.DoesTransactionFollowsPolicy(tx, blockChain))
                    {
                        blockChain.StageTransaction(tx);
                        return(true);
                    }
                    else
                    {
                        context.Errors.Add(new ExecutionError("The given transaction is invalid."));
                        return(false);
                    }
                }
                catch (Exception e)
                {
                    context.Errors.Add(new ExecutionError("An unexpected exception occurred.", e));
                    return(false);
                }
            }
                );

            Field <TxIdType>(
                name: "transferGold",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <AddressType> >
            {
                Name = "recipient",
            },
                    new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "amount"
            }
                    ),
                resolve: context =>
            {
                NineChroniclesNodeService service = standaloneContext.NineChroniclesNodeService;
                PrivateKey privateKey             = service.PrivateKey;
                if (privateKey is null)
                {
                    // FIXME We should cover this case on unittest.
                    var msg = "No private key was loaded.";
                    context.Errors.Add(new ExecutionError(msg));
                    Log.Error(msg);
                    return(null);
                }

                BlockChain <NCAction> blockChain = service.BlockChain;
                var currency = new GoldCurrencyState(
                    (Dictionary)blockChain.GetState(GoldCurrencyState.Address)
                    ).Currency;
                FungibleAssetValue amount =
                    FungibleAssetValue.Parse(currency, context.GetArgument <string>("amount"));

                Address recipient = context.GetArgument <Address>("recipient");

                Transaction <NCAction> tx = blockChain.MakeTransaction(
                    privateKey,
                    new NCAction[]
                {
                    new TransferAsset(
                        privateKey.ToAddress(),
                        recipient,
                        amount
                        ),
                }
                    );
                return(tx.Id);
            }
                );
        }
        public ActionMutation()
        {
            Field <NonNullGraphType <BooleanGraphType> >("createAvatar",
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address userAddress   = privatekey.PublicKey.ToAddress();
                    Address avatarAddress = userAddress.Derive("avatar_0");

                    var action = new CreateAvatar
                    {
                        avatarAddress = avatarAddress,
                        index         = 0,
                        hair          = 0,
                        lens          = 0,
                        ear           = 0,
                        tail          = 0,
                        name          = "createbymutation",
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });

            Field <NonNullGraphType <BooleanGraphType> >("hackAndSlash",
                                                         arguments: new QueryArguments(
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "weeklyArenaAddress",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "rankingArenaAddress",
            }),
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address userAddress         = privatekey.PublicKey.ToAddress();
                    Address avatarAddress       = userAddress.Derive("avatar_0");
                    Address weeklyArenaAddress  = new Address(context.GetArgument <string>("weeklyArenaAddress"));
                    Address rankingArenaAddress = new Address(context.GetArgument <string>("rankingArenaAddress"));

                    var action = new HackAndSlash
                    {
                        avatarAddress      = avatarAddress,
                        worldId            = 1,
                        stageId            = 1,
                        WeeklyArenaAddress = weeklyArenaAddress,
                        RankingMapAddress  = rankingArenaAddress,
                        costumes           = new List <int>(),
                        equipments         = new List <Guid>(),
                        foods = new List <Guid>(),
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });

            Field <NonNullGraphType <BooleanGraphType> >("combinationEquipment",
                                                         arguments: new QueryArguments(
                                                             new QueryArgument <NonNullGraphType <DecimalGraphType> >
            {
                Name = "recipeId",
            },
                                                             new QueryArgument <NonNullGraphType <DecimalGraphType> >
            {
                Name = "slotIndex",
            },
                                                             new QueryArgument <DecimalGraphType>
            {
                Name = "subRecipeId",
            }),
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address userAddress   = privatekey.PublicKey.ToAddress();
                    Address avatarAddress = userAddress.Derive("avatar_0");
                    int recipeId          = context.GetArgument <int>("recipeId");
                    int slotIndex         = context.GetArgument <int>("slotIndex");
                    int?subRecipeId       = context.GetArgument <int>("subRecipeId");

                    var action = new CombinationEquipment
                    {
                        AvatarAddress = avatarAddress,
                        RecipeId      = recipeId,
                        SlotIndex     = slotIndex,
                        SubRecipeId   = subRecipeId
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });

            Field <NonNullGraphType <BooleanGraphType> >("itemEnhancement",
                                                         arguments: new QueryArguments(
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "itemId",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "materialIds",
            }),
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address userAddress   = privatekey.PublicKey.ToAddress();
                    Address avatarAddress = userAddress.Derive("avatar_0");
                    Guid itemId           = Guid.Parse(context.GetArgument <string>("itemId"));
                    Guid materialId       = Guid.Parse(context.GetArgument <string>("materialIds"));

                    var action = new ItemEnhancement
                    {
                        avatarAddress = avatarAddress,
                        slotIndex     = 0,
                        itemId        = itemId,
                        materialIds   = new[] { materialId }
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });

            Field <NonNullGraphType <BooleanGraphType> >("buy",
                                                         arguments: new QueryArguments(
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "sellerAgentAddress",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "sellerAvatarAddress",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "productId",
            }),
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address userAddress         = privatekey.PublicKey.ToAddress();
                    Address avatarAddress       = userAddress.Derive("avatar_0");
                    Address sellerAgentAddress  = new Address(context.GetArgument <string>("sellerAgentAddress"));
                    Address sellerAvatarAddress = new Address(context.GetArgument <string>("sellerAvatarAddress"));
                    Guid productId = Guid.Parse(context.GetArgument <string>("productId"));

                    var action = new Buy
                    {
                        buyerAvatarAddress  = avatarAddress,
                        sellerAgentAddress  = sellerAgentAddress,
                        sellerAvatarAddress = sellerAvatarAddress,
                        productId           = productId,
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });
            Field <NonNullGraphType <BooleanGraphType> >("sell",
                                                         arguments: new QueryArguments(
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "sellerAvatarAddress",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "productId",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "itemId",
            },
                                                             new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name = "price",
            }),
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address sellerAvatarAddress = new Address(context.GetArgument <string>("sellerAvatarAddress"));
                    Guid itemId  = Guid.Parse(context.GetArgument <string>("itemId"));
                    var currency = new GoldCurrencyState(
                        (Dictionary)blockChain.GetState(GoldCurrencyState.Address)
                        ).Currency;
                    FungibleAssetValue price =
                        FungibleAssetValue.Parse(currency, context.GetArgument <string>("price"));

                    var action = new Sell
                    {
                        sellerAvatarAddress = sellerAvatarAddress,
                        itemId = itemId,
                        price  = price
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });

            Field <NonNullGraphType <BooleanGraphType> >("dailyReward",
                                                         resolve: context =>
            {
                try
                {
                    NineChroniclesNodeService service = context.Source;
                    PrivateKey privatekey             = service.PrivateKey;
                    BlockChain <NineChroniclesActionType> blockChain = service.Swarm.BlockChain;
                    Address userAddress   = privatekey.PublicKey.ToAddress();
                    Address avatarAddress = userAddress.Derive("avatar_0");

                    var action = new DailyReward
                    {
                        avatarAddress = avatarAddress
                    };

                    var actions = new PolymorphicAction <ActionBase>[] { action };
                    blockChain.MakeTransaction(privatekey, actions);
                }
                catch (Exception e)
                {
                    var msg = $"Unexpected exception occurred during {typeof(ActionMutation)}: {e}";
                    context.Errors.Add(new ExecutionError(msg, e));
                    Log.Error(msg, e);
                    return(false);
                }

                return(true);
            });
        }