diff --git a/CHANGES.md b/CHANGES.md index 75a80a863e4..fafbf38dd44 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,15 @@ Version 5.5.1 To be released. +### Added APIs + + - (Libplanet.Extensions.Cocona) Added new commands to store command: + [[#4032]] + - `GetTxNonce` + - `SetTxNonce` + +[#4032]: https://github.com/planetarium/libplanet/pull/4032 + Version 5.5.0 ------------- diff --git a/test/Libplanet.Extensions.Cocona.Tests/Commands/StoreCommandTest.cs b/test/Libplanet.Extensions.Cocona.Tests/Commands/StoreCommandTest.cs index ef04d4b3c8d..64676c83217 100644 --- a/test/Libplanet.Extensions.Cocona.Tests/Commands/StoreCommandTest.cs +++ b/test/Libplanet.Extensions.Cocona.Tests/Commands/StoreCommandTest.cs @@ -347,6 +347,38 @@ public void TestTxById() } } + [SkippableFact] + public void TestGetTxNonce() + { + foreach (var fx in _storeFixtures) + { + using var sw = new StringWriter(); + Console.SetOut(sw); + new StoreCommand().GetTxNonce( + fx.Scheme + fx.Path, + new PrivateKey().Address.ToString()); + var actual = sw.ToString(); + Assert.Equal("0", actual.TrimEnd()); + } + } + + [SkippableFact] + public void TestSetTxNonce() + { + foreach (var fx in _storeFixtures) + { + using var sw = new StringWriter(); + Console.SetOut(sw); + const int target = 5; + new StoreCommand().SetTxNonce( + fx.Scheme + fx.Path, + new PrivateKey().Address.ToString(), + target); + var actual = sw.ToString(); + Assert.Equal($"{target}", actual.TrimEnd()); + } + } + public void Dispose() { foreach (var storeFixture in _storeFixtures) diff --git a/tools/Libplanet.Extensions.Cocona/Commands/StoreCommand.cs b/tools/Libplanet.Extensions.Cocona/Commands/StoreCommand.cs index 29a88587583..12694b1627b 100644 --- a/tools/Libplanet.Extensions.Cocona/Commands/StoreCommand.cs +++ b/tools/Libplanet.Extensions.Cocona/Commands/StoreCommand.cs @@ -5,6 +5,7 @@ using System.Linq; using global::Cocona; using Libplanet.Common; +using Libplanet.Crypto; using Libplanet.Store; using Libplanet.Types.Blocks; using Libplanet.Types.Tx; @@ -160,6 +161,49 @@ public void MigrateIndex(string storePath) } } + [Command(Description = "Query a tx nonce for the address for the canonical chain.")] + public void GetTxNonce( + [Argument("STORE", Description = StoreArgumentDescription)] + string home, + [Argument("ADDRESS", Description = "signer address")] + string address) + { + IStore store = Utils.LoadStoreFromUri(home); + var canon = store.GetCanonicalChainId(); + if (canon is not { } cid) + { + Console.WriteLine("No canonical chain."); + return; + } + + Console.WriteLine(store.GetTxNonce(cid, new Address(address))); + store?.Dispose(); + } + + [Command(Description = "Mutate a tx nonce for the address for the canonical chain.")] + public void SetTxNonce( + [Argument("STORE", Description = StoreArgumentDescription)] + string home, + [Argument("ADDRESS", Description = "signer address")] + string address, + [Argument("NONCE", Description = "nonce")] + long nonce) + { + IStore store = Utils.LoadStoreFromUri(home); + var canon = store.GetCanonicalChainId(); + if (canon is not { } cid) + { + Console.WriteLine("No canonical chain."); + return; + } + + var signer = new Address(address); + var currentNonce = store.GetTxNonce(cid, signer); + store.IncreaseTxNonce(cid, signer, nonce - currentNonce); + Console.WriteLine(store.GetTxNonce(cid, signer)); + store?.Dispose(); + } + private static Block GetBlock(IStore store, BlockHash blockHash) { if (!(store.GetBlock(blockHash) is { } block))