Skip to content

Commit

Permalink
Merge pull request #2717 from planetarium/feature/issue-2704
Browse files Browse the repository at this point in the history
Introduce MigrateFee action
  • Loading branch information
ipdae authored Aug 14, 2024
2 parents 75b792f + fa433c5 commit cc420c8
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .Lib9c.Tests/Action/ActionEvaluationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace Lib9c.Tests.Action
{
using System;
using System.Collections.Generic;
using System.Numerics;
using Bencodex.Types;
using Lib9c.Formatters;
using Libplanet.Action.State;
Expand Down Expand Up @@ -93,6 +94,7 @@ public ActionEvaluationTest()
[InlineData(typeof(RuneSummon))]
[InlineData(typeof(ActivateCollection))]
[InlineData(typeof(RetrieveAvatarAssets))]
[InlineData(typeof(MigrateFee))]
public void Serialize_With_MessagePack(Type actionType)
{
var action = GetAction(actionType);
Expand Down Expand Up @@ -479,6 +481,14 @@ private ActionBase GetAction(Type type)
},
},
RetrieveAvatarAssets _ => new RetrieveAvatarAssets(avatarAddress: new PrivateKey().Address),
MigrateFee _ => new MigrateFee
{
TransferData = new List<(Address sender, Address recipient, BigInteger amount)>
{
(new PrivateKey().Address, new PrivateKey().Address, 1),
(new PrivateKey().Address, new PrivateKey().Address, 2),
},
},
_ => throw new InvalidCastException(),
};
}
Expand Down
105 changes: 105 additions & 0 deletions .Lib9c.Tests/Action/MigrateFeeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
namespace Lib9c.Tests.Action;

using System.Collections.Generic;
using System.Globalization;
using System.Numerics;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Mocks;
using Libplanet.Types.Assets;
using Nekoyume.Action;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Xunit;

public class MigrateFeeTest
{
private readonly Currency _ncgCurrency;

public MigrateFeeTest()
{
#pragma warning disable CS0618
_ncgCurrency = Currency.Legacy("NCG", 2, null);
#pragma warning restore CS0618
}

[Fact]
public void Execute()
{
var admin = new Address("8d9f76aF8Dc5A812aCeA15d8bf56E2F790F47fd7");
var context = new ActionContext();
var state = new World(MockUtil.MockModernWorldState)
.SetLegacyState(AdminState.Address, new AdminState(admin, 100).Serialize())
.SetLegacyState(GoldCurrencyState.Address, new GoldCurrencyState(_ncgCurrency).Serialize());
var recipient = new PrivateKey().Address;
var transferData = new List<(Address sender, Address recipient, BigInteger amount)>();
var amount = FungibleAssetValue.Parse(_ncgCurrency, 0.1m.ToString(CultureInfo.InvariantCulture));
for (int i = 1; i < 10; i++)
{
var address = new PrivateKey().Address;
var balance = 0.1m * i;
var fav = FungibleAssetValue.Parse(_ncgCurrency, balance.ToString(CultureInfo.InvariantCulture));
state = state.MintAsset(context, address, fav);
transferData.Add((address, recipient, amount.RawValue));
}

var action = new MigrateFee
{
TransferData = transferData,
Memo = "memo",
};

var nextState = action.Execute(new ActionContext
{
BlockIndex = 1L,
PreviousState = state,
RandomSeed = 0,
Signer = admin,
});

foreach (var (sender, _, _) in transferData)
{
var prevBalance = state.GetBalance(sender, _ncgCurrency);
Assert.Equal(prevBalance - amount, nextState.GetBalance(sender, _ncgCurrency));
}

Assert.Equal(FungibleAssetValue.Parse(_ncgCurrency, "0.9"), nextState.GetBalance(recipient, _ncgCurrency));
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void PlainValue(bool memo)
{
var transferData = new List<(Address sender, Address recipient, BigInteger amount)>();
// 0.9
// 1.0
// 1.1
for (int i = 9; i < 12; i++)
{
var sender = new PrivateKey().Address;
var recipient = new PrivateKey().Address;
var amount = FungibleAssetValue.Parse(_ncgCurrency, (0.1m * i).ToString(CultureInfo.InvariantCulture));
transferData.Add((sender, recipient, amount.RawValue));
}

var action = new MigrateFee
{
TransferData = transferData,
Memo = memo ? "memo" : null,
};

var des = new MigrateFee();
des.LoadPlainValue(action.PlainValue);

for (int i = 0; i < action.TransferData.Count; i++)
{
var data = action.TransferData[i];
Assert.Equal(des.TransferData[i].sender, data.sender);
Assert.Equal(des.TransferData[i].recipient, data.recipient);
Assert.Equal(des.TransferData[i].amount, data.amount);
}

Assert.Equal(memo, !string.IsNullOrEmpty(des.Memo));
}
}
88 changes: 88 additions & 0 deletions Lib9c/Action/MigrateFee.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Libplanet.Types.Assets;
using Nekoyume.Model.State;
using Nekoyume.Module;

namespace Nekoyume.Action
{
[ActionType(TypeIdentifier)]
public class MigrateFee : ActionBase
{
public const string TypeIdentifier = "migrate_fee";
public List<(Address sender, Address recipient, BigInteger amount)> TransferData;
public string Memo;

public MigrateFee()
{
}

public override IValue PlainValue
{
get
{
var values = Dictionary.Empty
.Add("td",
new List(TransferData.Select(a =>
List.Empty
.Add(a.sender.Serialize())
.Add(a.recipient.Serialize())
.Add(a.amount.Serialize()))
)
);
if (!string.IsNullOrEmpty(Memo))
{
values = values.Add("m", Memo);
}
return Dictionary.Empty
.Add("type_id", TypeIdentifier)
.Add("values", values);
}
}

public override void LoadPlainValue(IValue plainValue)
{
var dict = (Dictionary)((Dictionary)plainValue)["values"];
var asList = (List) dict["td"];
TransferData = new List<(Address sender, Address recipient, BigInteger amount)>();
foreach (var v in asList)
{
var innerList = (List) v;
var sender = innerList[0].ToAddress();
var recipient = innerList[1].ToAddress();
var amount = innerList[2].ToBigInteger();
TransferData.Add((sender, recipient, amount));
}

if (dict.TryGetValue((Text)"m", out var m))
{
Memo = (Text) m;
}
}

public override IWorld Execute(IActionContext context)
{
context.UseGas(1);

CheckPermission(context);
var states = context.PreviousState;
var goldCurrency = states.GetGoldCurrency();
foreach (var (sender, recipient, raw) in TransferData)
{
var balance = states.GetBalance(sender, goldCurrency);
var amount = FungibleAssetValue.FromRawValue(goldCurrency, raw);
if (balance >= amount)
{
states = states.TransferAsset(context, sender, recipient, amount);
}
}

return states;
}
}
}

0 comments on commit cc420c8

Please sign in to comment.