Skip to content

Commit

Permalink
Merge pull request #2309 from planetarium/PDX-126-add-custom-ticker-t…
Browse files Browse the repository at this point in the history
…o-transferasset

PDX-126: update transferAsset to accept custom ticker
  • Loading branch information
U-lis authored Nov 20, 2023
2 parents bc578ba + ddb19b3 commit e89c6a9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 6 deletions.
45 changes: 44 additions & 1 deletion NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public async Task UnlockWorld()
[InlineData("NCG", false)]
[InlineData("CRYSTAL", true)]
[InlineData("CRYSTAL", false)]
public async Task TransferAsset(string currencyType, bool memo)
public async Task TransferAssetWithCurrencyEnum(string currencyType, bool memo)
{
var recipient = new PrivateKey().ToAddress();
var sender = new PrivateKey().ToAddress();
Expand Down Expand Up @@ -270,6 +270,49 @@ public async Task TransferAsset(string currencyType, bool memo)
}
}

[Theory]
[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 valueTypeWithMinter = valueType.Replace("[]",
valueType.Contains("NCG") ? $"[\"{goldCurrencyState.Currency.Minters.First()}\"]" : "[]");
var args = $"recipient: \"{recipient}\", sender: \"{sender}\", rawCurrency: {valueTypeWithMinter}, amount: \"17.5\"";
if (memo)
{
args += ", memo: \"memo\"";
}

var query = $"{{ transferAsset({args}) }}";
var queryResult = await ExecuteQueryAsync<ActionQuery>(query, standaloneContext: _standaloneContext);
var data = (Dictionary<string, object>)((ExecutionNode)queryResult.Data!).ToValue()!;
var plainValue = _codec.Decode(ByteUtil.ParseHex((string)data["transferAsset"]));
Assert.IsType<Dictionary>(plainValue);
var actionBase = DeserializeNCAction(plainValue);
var action = Assert.IsType<TransferAsset>(actionBase);

Currency currency = valueType.Contains("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);
}
}

[Fact]
public async Task PatchTableSheet()
{
Expand Down
36 changes: 31 additions & 5 deletions NineChronicles.Headless/GraphTypes/ActionQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Numerics;
using Bencodex;
using Bencodex.Types;
using Google.Protobuf.WellKnownTypes;
using GraphQL;
using GraphQL.Types;
using Libplanet.Crypto;
Expand Down Expand Up @@ -170,11 +171,16 @@ public ActionQuery(StandaloneContext standaloneContext)
Description = "A string value to be transferred.",
Name = "amount",
},
new QueryArgument<NonNullGraphType<CurrencyEnumType>>
new QueryArgument<CurrencyEnumType>
{
Description = "A currency type to be transferred.",
Description = "A enum value of currency to be transferred.",
Name = "currency",
},
new QueryArgument<CurrencyInputType>
{
Description = "A currency to be transferred.",
Name = "rawCurrency",
},
new QueryArgument<StringGraphType>
{
Description = "A 80-max length string to note.",
Expand All @@ -185,10 +191,30 @@ public ActionQuery(StandaloneContext standaloneContext)
{
var sender = context.GetArgument<Address>("sender");
var recipient = context.GetArgument<Address>("recipient");
var currencyEnum = context.GetArgument<CurrencyEnum>("currency");
if (!standaloneContext.CurrencyFactory!.TryGetCurrency(currencyEnum, out var currency))
var nullableRawCurrency = context.GetArgument<Currency?>("rawCurrency");
var nullableCurrencyEnum = context.GetArgument<CurrencyEnum?>("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($"Currency {currencyEnum} is not found.");
throw new ExecutionError("Either currency or rawCurrency must be set.");
}

var amount = FungibleAssetValue.Parse(currency, context.GetArgument<string>("amount"));
Expand Down

0 comments on commit e89c6a9

Please sign in to comment.