From f7b413f1623b62329d9be172937fb8873bb609fb Mon Sep 17 00:00:00 2001 From: XxshiftxX Date: Fri, 17 Nov 2023 14:36:08 +0900 Subject: [PATCH 1/5] update transferAsset to accept custom ticker --- .../GraphTypes/ActionQuery.cs | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/NineChronicles.Headless/GraphTypes/ActionQuery.cs b/NineChronicles.Headless/GraphTypes/ActionQuery.cs index 42a06176a..c93e3acd1 100644 --- a/NineChronicles.Headless/GraphTypes/ActionQuery.cs +++ b/NineChronicles.Headless/GraphTypes/ActionQuery.cs @@ -165,15 +165,10 @@ public ActionQuery(StandaloneContext standaloneContext) Description = "Address of recipient.", Name = "recipient", }, - new QueryArgument> - { - Description = "A string value to be transferred.", - Name = "amount", - }, - new QueryArgument> + new QueryArgument> { - Description = "A currency type to be transferred.", - Name = "currency", + Name = "value", + Description = "FungibleAssetValue to transfer." }, new QueryArgument { @@ -185,15 +180,9 @@ public ActionQuery(StandaloneContext standaloneContext) { var sender = context.GetArgument
("sender"); var recipient = context.GetArgument
("recipient"); - var currencyEnum = context.GetArgument("currency"); - if (!standaloneContext.CurrencyFactory!.TryGetCurrency(currencyEnum, out var currency)) - { - throw new ExecutionError($"Currency {currencyEnum} is not found."); - } - - var amount = FungibleAssetValue.Parse(currency, context.GetArgument("amount")); + var value = context.GetArgument("value"); var memo = context.GetArgument("memo"); - ActionBase action = new TransferAsset(sender, recipient, amount, memo); + ActionBase action = new TransferAsset(sender, recipient, value, memo); return Encode(context, action); }); Field>( From 779af193b315f04b72109bdf3225fe220496f894 Mon Sep 17 00:00:00 2001 From: XxshiftxX Date: Fri, 17 Nov 2023 15:32:27 +0900 Subject: [PATCH 2/5] separate fav into currency and amount --- .../GraphTypes/ActionQuery.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/NineChronicles.Headless/GraphTypes/ActionQuery.cs b/NineChronicles.Headless/GraphTypes/ActionQuery.cs index c93e3acd1..da23d78ed 100644 --- a/NineChronicles.Headless/GraphTypes/ActionQuery.cs +++ b/NineChronicles.Headless/GraphTypes/ActionQuery.cs @@ -4,6 +4,7 @@ using System.Numerics; using Bencodex; using Bencodex.Types; +using Google.Protobuf.WellKnownTypes; using GraphQL; using GraphQL.Types; using Libplanet.Crypto; @@ -165,10 +166,15 @@ public ActionQuery(StandaloneContext standaloneContext) Description = "Address of recipient.", Name = "recipient", }, - new QueryArgument> + new QueryArgument> + { + Description = "A string value to be transferred.", + Name = "amount", + }, + new QueryArgument> { - Name = "value", - Description = "FungibleAssetValue to transfer." + Description = "A currency type to be transferred.", + Name = "currency", }, new QueryArgument { @@ -180,9 +186,10 @@ public ActionQuery(StandaloneContext standaloneContext) { var sender = context.GetArgument
("sender"); var recipient = context.GetArgument
("recipient"); - var value = context.GetArgument("value"); + var currency = context.GetArgument("currency"); + var amount = FungibleAssetValue.Parse(currency, context.GetArgument("amount")); var memo = context.GetArgument("memo"); - ActionBase action = new TransferAsset(sender, recipient, value, memo); + ActionBase action = new TransferAsset(sender, recipient, amount, memo); return Encode(context, action); }); Field>( From cbaee0d05f1698abde17ba8ae4fb30eaf9c8f3b4 Mon Sep 17 00:00:00 2001 From: XxshiftxX Date: Fri, 17 Nov 2023 15:32:49 +0900 Subject: [PATCH 3/5] fix test code --- .../GraphTypes/ActionQueryTest.cs | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs index 54b0d79c5..9d6b401fe 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs @@ -232,15 +232,20 @@ public async Task UnlockWorld() } [Theory] - [InlineData("NCG", true)] - [InlineData("NCG", false)] - [InlineData("CRYSTAL", true)] - [InlineData("CRYSTAL", false)] - public async Task TransferAsset(string currencyType, bool memo) + [InlineData("{ ticker: \"NCG\", minters: [], decimalPlaces: 2 }", true)] + [InlineData("{ ticker: \"NCG\", minters: [], decimalPlaces: 2 }", false)] + [InlineData("{ ticker: \"CRYSTAL\", minters: [], decimalPlaces: 18 }", true)] + [InlineData("{ ticker: \"CRYSTAL\", minters: [], decimalPlaces: 18 }", false)] + public async Task TransferAsset(string valueType, bool memo) { + var rawState = _standaloneContext.BlockChain!.GetState(Addresses.GoldCurrency); + var goldCurrencyState = new GoldCurrencyState((Dictionary)rawState); + var recipient = new PrivateKey().ToAddress(); var sender = new PrivateKey().ToAddress(); - var args = $"recipient: \"{recipient}\", sender: \"{sender}\", amount: \"17.5\", currency: {currencyType}"; + var valueTypeWithMinter = valueType.Replace("[]", + valueType.Contains("NCG") ? $"[\"{goldCurrencyState.Currency.Minters.First()}\"]" : "[]"); + var args = $"recipient: \"{recipient}\", sender: \"{sender}\", currency: {valueTypeWithMinter}, amount: \"17.5\""; if (memo) { args += ", memo: \"memo\""; @@ -253,9 +258,8 @@ public async Task TransferAsset(string currencyType, bool memo) Assert.IsType(plainValue); var actionBase = DeserializeNCAction(plainValue); var action = Assert.IsType(actionBase); - var rawState = _standaloneContext.BlockChain!.GetState(Addresses.GoldCurrency); - var goldCurrencyState = new GoldCurrencyState((Dictionary)rawState); - Currency currency = currencyType == "NCG" ? goldCurrencyState.Currency : CrystalCalculator.CRYSTAL; + + Currency currency = valueType.Contains("NCG") ? goldCurrencyState.Currency : CrystalCalculator.CRYSTAL; Assert.Equal(recipient, action.Recipient); Assert.Equal(sender, action.Sender); From 8a01b4ffe298694528c6c0c124358dd449bbf33a Mon Sep 17 00:00:00 2001 From: XxshiftxX Date: Mon, 20 Nov 2023 11:04:26 +0900 Subject: [PATCH 4/5] add support for currency enum --- .../GraphTypes/ActionQueryTest.cs | 41 ++++++++++++++++++- .../GraphTypes/ActionQuery.cs | 36 ++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs index 9d6b401fe..3fbc870d1 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs @@ -231,6 +231,45 @@ public async Task UnlockWorld() ); } + [Theory] + [InlineData("NCG", true)] + [InlineData("NCG", false)] + [InlineData("CRYSTAL", true)] + [InlineData("CRYSTAL", false)] + public async Task TransferAssetWithCurrencyEnum(string currencyType, bool memo) + { + var recipient = new PrivateKey().ToAddress(); + var sender = new PrivateKey().ToAddress(); + var args = $"recipient: \"{recipient}\", sender: \"{sender}\", amount: \"17.5\", currency: {currencyType}"; + if (memo) + { + args += ", memo: \"memo\""; + } + + var query = $"{{ transferAsset({args}) }}"; + var queryResult = await ExecuteQueryAsync(query, standaloneContext: _standaloneContext); + var data = (Dictionary)((ExecutionNode)queryResult.Data!).ToValue()!; + var plainValue = _codec.Decode(ByteUtil.ParseHex((string)data["transferAsset"])); + Assert.IsType(plainValue); + var actionBase = DeserializeNCAction(plainValue); + var action = Assert.IsType(actionBase); + var rawState = _standaloneContext.BlockChain!.GetState(Addresses.GoldCurrency); + var goldCurrencyState = new GoldCurrencyState((Dictionary)rawState); + Currency currency = currencyType == "NCG" ? goldCurrencyState.Currency : CrystalCalculator.CRYSTAL; + + Assert.Equal(recipient, action.Recipient); + Assert.Equal(sender, action.Sender); + Assert.Equal(FungibleAssetValue.Parse(currency, "17.5"), action.Amount); + if (memo) + { + Assert.Equal("memo", action.Memo); + } + else + { + Assert.Null(action.Memo); + } + } + [Theory] [InlineData("{ ticker: \"NCG\", minters: [], decimalPlaces: 2 }", true)] [InlineData("{ ticker: \"NCG\", minters: [], decimalPlaces: 2 }", false)] @@ -245,7 +284,7 @@ public async Task TransferAsset(string valueType, bool memo) var sender = new PrivateKey().ToAddress(); var valueTypeWithMinter = valueType.Replace("[]", valueType.Contains("NCG") ? $"[\"{goldCurrencyState.Currency.Minters.First()}\"]" : "[]"); - var args = $"recipient: \"{recipient}\", sender: \"{sender}\", currency: {valueTypeWithMinter}, amount: \"17.5\""; + var args = $"recipient: \"{recipient}\", sender: \"{sender}\", rawCurrency: {valueTypeWithMinter}, amount: \"17.5\""; if (memo) { args += ", memo: \"memo\""; diff --git a/NineChronicles.Headless/GraphTypes/ActionQuery.cs b/NineChronicles.Headless/GraphTypes/ActionQuery.cs index da23d78ed..7e092c6ba 100644 --- a/NineChronicles.Headless/GraphTypes/ActionQuery.cs +++ b/NineChronicles.Headless/GraphTypes/ActionQuery.cs @@ -171,11 +171,16 @@ public ActionQuery(StandaloneContext standaloneContext) Description = "A string value to be transferred.", Name = "amount", }, - new QueryArgument> + new QueryArgument { - Description = "A currency type to be transferred.", + Description = "A enum value of currency to be transferred.", Name = "currency", }, + new QueryArgument + { + Description = "A currency to be transferred.", + Name = "rawCurrency", + }, new QueryArgument { Description = "A 80-max length string to note.", @@ -186,7 +191,32 @@ public ActionQuery(StandaloneContext standaloneContext) { var sender = context.GetArgument
("sender"); var recipient = context.GetArgument
("recipient"); - var currency = context.GetArgument("currency"); + var nullableRawCurrency = context.GetArgument("rawCurrency"); + var nullableCurrencyEnum = context.GetArgument("currency"); + + Currency currency; + if (nullableRawCurrency is not null && nullableCurrencyEnum is not null) + { + throw new ExecutionError("Only one of currency and rawCurrency must be set."); + } + if (nullableCurrencyEnum is { } currencyEnum) + { + if (!standaloneContext.CurrencyFactory!.TryGetCurrency(currencyEnum, out var currencyFromEnum)) + { + throw new ExecutionError($"Currency {currencyEnum} is not found."); + } + + currency = currencyFromEnum; + } + else if (nullableRawCurrency is { } rawCurrency) + { + currency = rawCurrency; + } + else + { + throw new ExecutionError("Either currency or rawCurrency must be set."); + } + var amount = FungibleAssetValue.Parse(currency, context.GetArgument("amount")); var memo = context.GetArgument("memo"); ActionBase action = new TransferAsset(sender, recipient, amount, memo); From ddb19b3b1bb1194d6de19568d66cec41afb0e00c Mon Sep 17 00:00:00 2001 From: XxshiftxX Date: Mon, 20 Nov 2023 11:27:42 +0900 Subject: [PATCH 5/5] lint --- NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs index 3fbc870d1..120983907 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs @@ -282,7 +282,7 @@ public async Task TransferAsset(string valueType, bool memo) var recipient = new PrivateKey().ToAddress(); var sender = new PrivateKey().ToAddress(); - var valueTypeWithMinter = valueType.Replace("[]", + var valueTypeWithMinter = valueType.Replace("[]", valueType.Contains("NCG") ? $"[\"{goldCurrencyState.Currency.Minters.First()}\"]" : "[]"); var args = $"recipient: \"{recipient}\", sender: \"{sender}\", rawCurrency: {valueTypeWithMinter}, amount: \"17.5\""; if (memo)