Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction Stuffs #101

Merged
merged 13 commits into from
Aug 6, 2023
6 changes: 3 additions & 3 deletions src/chia-dotnet.tests/WalletTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public async Task GetWalletBalance()
public async Task GetTransactions()
{
using var cts = new CancellationTokenSource(15000);
var count = await _theWallet.GetTransactionCount(cts.Token);
var count = await _theWallet.GetTransactionCount(cancellationToken: cts.Token);
if (count == 0)
{
Assert.Inconclusive("no transactions");
Expand All @@ -66,7 +66,7 @@ public async Task GetTransactionsIncremental()
{
using var cts = new CancellationTokenSource(150000);

var count = await _theWallet.GetTransactionCount(cts.Token);
var count = await _theWallet.GetTransactionCount(cancellationToken: cts.Token);
Assert.IsTrue(count > 4);

var transactions1 = await _theWallet.GetTransactions(start: 0, end: 2, cancellationToken: cts.Token);
Expand Down Expand Up @@ -117,7 +117,7 @@ public async Task GetTransactionCount()
{
using var cts = new CancellationTokenSource(15000);

var count = await _theWallet.GetTransactionCount(cts.Token);
var count = await _theWallet.GetTransactionCount(cancellationToken: cts.Token);

Assert.IsNotNull(count);
}
Expand Down
15 changes: 13 additions & 2 deletions src/chia-dotnet/CATWallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,15 @@ public async Task SetName(string name, CancellationToken cancellationToken = def
/// </summary>
/// <param name="innerAddress">The inner address for the spend</param>
/// <param name="amount">The amount to put in the wallet (in units of mojos)</param>
/// <param name="fee">The fee to create the wallet (in units of mojos)</param>
/// <param name="memos">Optional list of byte string memos to include in the transaction</param>
/// <param name="minCoinAmount"></param>
/// <param name="maxCoinAmount"></param>
/// <param name="excludeCoinAmounts"></param>
/// <param name="reusePuzhash"></param>
/// <param name="fee">The fee to create the wallet (in units of mojos)</param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns>A <see cref="TransactionRecord"/></returns>
public async Task<TransactionRecord> Spend(string innerAddress, ulong amount, ulong fee, IEnumerable<string>? memos = null, CancellationToken cancellationToken = default)
public async Task<TransactionRecord> Spend(string innerAddress, ulong amount, IEnumerable<string>? memos = null, ulong minCoinAmount = 0, ulong maxCoinAmount = 0, IEnumerable<ulong>? excludeCoinAmounts = null, bool reusePuzhash = false, ulong fee = 0, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(innerAddress))
{
Expand All @@ -92,11 +96,18 @@ public async Task<TransactionRecord> Spend(string innerAddress, ulong amount, ul
dynamic data = CreateWalletDataObject();
data.inner_address = innerAddress;
data.amount = amount;
data.min_coin_amount = minCoinAmount;
data.max_coin_amount = maxCoinAmount;
data.fee = fee;
data.reuse_puzhash = reusePuzhash;
if (memos != null)
{
data.memos = memos.ToList();
}
if (excludeCoinAmounts != null)
{
data.exclude_coin_ids = excludeCoinAmounts.ToList();
}

return await WalletProxy.SendMessage<TransactionRecord>("cat_spend", data, "transaction", cancellationToken).ConfigureAwait(false);
}
Expand Down
87 changes: 62 additions & 25 deletions src/chia-dotnet/Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,42 +122,49 @@ public async Task<IEnumerable<Coin>> SelectCoins(ulong amount, IEnumerable<Coin>
}

/// <summary>
/// Get the list of transactions
/// </summary>
/// <param name="toAddress">Restrict results only to this address</param>
/// <param name="sortKey">Field to sort results by</param>
/// <param name="reverse">Reverse the sort order of the results</param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns>A list of <see cref="TransactionRecord"/>s</returns>
public async Task<IEnumerable<TransactionRecord>> GetTransactions(string? toAddress = null, string? sortKey = null, bool reverse = false, CancellationToken cancellationToken = default)
{
var count = await GetTransactionCount(cancellationToken).ConfigureAwait(false);
return await GetTransactions(0, count, toAddress, sortKey, reverse, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Get the list of transactions
/// Retrieves a list of transactions from a wallet.
/// </summary>
/// <param name="start">the start index of transactions (zero based)</param>
/// <param name="end">The end index of transactions (max of <see cref="GetTransactionCount(CancellationToken)"/></param>
/// <param name="toAddress">Restrict results only to this address</param>
/// <param name="sortKey">Field to sort results by</param>
/// <param name="reverse">Reverse the sort order of the results</param>
/// <param name="confirmed"></param>
/// <param name="typeFilter"></param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns>A list of <see cref="TransactionRecord"/>s</returns>
public async Task<IEnumerable<TransactionRecord>> GetTransactions(uint start, uint end, string? toAddress = null, string? sortKey = null, bool reverse = false, CancellationToken cancellationToken = default)
/// <returns>A list of <see cref="TransactionRecord"/></returns>
public async Task<IEnumerable<TransactionRecord>> GetTransactions(
string? toAddress = null,
TransactionTypeFilter? typeFilter = null,
bool reverse = false,
string? sortKey = null,
uint start = 0,
uint end = 50,
bool? confirmed = null,
CancellationToken cancellationToken = default)
{
dynamic data = CreateWalletDataObject();
data.start = start;
data.end = end;
data.to_address = toAddress;
data.sort_key = sortKey;
data.reverse = reverse;

if (toAddress is not null)
{
data.to_address = toAddress;
}
if (sortKey is not null)
{
data.sort_key = sortKey;
}
if (typeFilter is not null)
{
data.type_filter = typeFilter;
}
if (confirmed is not null)
{
data.confirmed = confirmed;
}
return await WalletProxy.SendMessage<IEnumerable<TransactionRecord>>("get_transactions", data, "transactions", cancellationToken).ConfigureAwait(false);
}


/// <summary>
/// Get the list of spendable coins
/// </summary>
Expand Down Expand Up @@ -223,9 +230,14 @@ public async Task<string> GetNextAddress(bool newAddress, CancellationToken canc
/// </summary>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns>The number of transactions</returns>
public async Task<uint> GetTransactionCount(CancellationToken cancellationToken = default)
public async Task<uint> GetTransactionCount(TransactionTypeFilter? typeFilter = null, CancellationToken cancellationToken = default)
{
var response = await WalletProxy.SendMessage("get_transaction_count", CreateWalletDataObject(), cancellationToken).ConfigureAwait(false);
dynamic data = CreateWalletDataObject();
if (typeFilter is not null)
{
data.type_filter = typeFilter;
}
var response = await WalletProxy.SendMessage("get_transaction_count", data, cancellationToken).ConfigureAwait(false);

return response.count;
}
Expand All @@ -247,9 +259,23 @@ public async Task DeleteUnconfirmedTransactions(CancellationToken cancellationTo
/// <param name="amount">The amount to send (in units of mojos)</param>
/// <param name="fee">Fee amount (in units of mojos)</param>
/// <param name="memos">Memos to go along with the transaction</param>
/// <param name="excludeCoinAmounts">/param>
/// <param name="excludeCoinsIds">/param>
/// <param name="minCoinAmount">/param>
/// <param name="minCoinAmount">/param>
/// <param name="resusePuzHash">/param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns>The <see cref="TransactionRecord"/></returns>
public async Task<TransactionRecord> SendTransaction(string address, ulong amount, ulong fee, IEnumerable<string>? memos = null, CancellationToken cancellationToken = default)
public async Task<TransactionRecord> SendTransaction(string address,
ulong amount,
IEnumerable<string>? memos = null,
IEnumerable<ulong>? excludeCoinAmounts = null,
IEnumerable<string>? excludeCoinsIds = null,
ulong minCoinAmount = 0,
ulong maxCoinAmount = 0,
bool resusePuzHash = false,
ulong fee = 0,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(address))
{
Expand All @@ -259,7 +285,18 @@ public async Task<TransactionRecord> SendTransaction(string address, ulong amoun
dynamic data = CreateWalletDataObject();
data.address = address;
data.amount = amount;
data.min_coin_amount = minCoinAmount;
data.max_coin_amount = maxCoinAmount;
data.fee = fee;
data.reuse_puzhash = resusePuzHash;
if (excludeCoinAmounts is not null)
{
data.exclude_coin_amounts = excludeCoinAmounts.ToList();
}
if (excludeCoinsIds is not null)
{
data.exclude_coin_ids = excludeCoinsIds.ToList();
}
if (memos is not null)
{
data.memos = memos.ToList();
Expand Down
90 changes: 78 additions & 12 deletions src/chia-dotnet/WalletProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -621,16 +621,30 @@ public static async Task<PoolInfo> GetPoolInfo(Uri poolUri, CancellationToken ca
}

/// <summary>
/// Create but do not send a transaction
/// </summary>
/// <param name="additions">Additions to the block chain</param>
/// <param name="fee">Fee amount (in units of mojos)</param>
/// <param name="coins">Coins to include</param>
/// <param name="coinAnnouncements">Coins to announce</param>
/// <param name="puzzleAnnouncements">Puzzles to announce</param>
/// Creates and signs a transaction.
/// </summary>
/// <param name="excludeCoinAmounts"></param>
/// <param name="excludeCoins"></param>
/// <param name="maxCoinAmount"></param>
/// <param name="minCoinAmount"></param>
/// <param name="puzzleAnnouncements"></param>
/// <param name="coinAnnouncements"></param>
/// <param name="coins"></param>
/// <param name="additions"></param>
/// <param name="fee"></param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns>The signed <see cref="TransactionRecord"/></returns>
public async Task<TransactionRecord> CreateSignedTransaction(IEnumerable<Coin> additions, ulong fee, IEnumerable<Coin>? coins = null, IEnumerable<CoinAnnouncement>? coinAnnouncements = null, IEnumerable<PuzzleAnnouncement>? puzzleAnnouncements = null, CancellationToken cancellationToken = default)
public async Task<(TransactionRecord SignedTx, IEnumerable<TransactionRecord> SignedTxs)> CreateSignedTransaction(
IEnumerable<AmountWithPuzzlehash> additions,
IEnumerable<ulong>? excludeCoinAmounts = null,
IEnumerable<Coin>? excludeCoins = null,
IEnumerable<PuzzleAnnouncement>? puzzleAnnouncements = null,
IEnumerable<CoinAnnouncement>? coinAnnouncements = null,
IEnumerable<Coin>? coins = null,
ulong minCoinAmount = 0,
ulong maxCoinAmount = 0,
ulong fee = 0,
CancellationToken cancellationToken = default)
{
if (additions is null)
{
Expand All @@ -640,19 +654,34 @@ public async Task<TransactionRecord> CreateSignedTransaction(IEnumerable<Coin> a
dynamic data = new ExpandoObject();
data.additions = additions.ToList();
data.fee = fee;
if (coins is not null) // coins are optional
data.min_coin_amount = minCoinAmount;
data.max_coin_amount = maxCoinAmount;
if (excludeCoins is not null)
{
data.exclude_coins = excludeCoins.ToList();
}
if (excludeCoinAmounts is not null)
{
data.exclude_coin_amounts = excludeCoinAmounts.ToList();
}
if (coins is not null)
{
data.coins = coins.ToList();
}
if (coinAnnouncements is not null) // coins are optional
if (coinAnnouncements is not null)
{
data.coin_announcements = coinAnnouncements.ToList();
}
if (puzzleAnnouncements is not null) // coins are optional
if (puzzleAnnouncements is not null)
{
data.puzzle_announcements = puzzleAnnouncements.ToList();
}
return await SendMessage<TransactionRecord>("create_signed_transaction", data, "signed_tx", cancellationToken).ConfigureAwait(false);
var response = await SendMessage("create_signed_transaction", data, cancellationToken).ConfigureAwait(false);

return (
Converters.ToObject<TransactionRecord>(response.signed_tx),
Converters.ToEnumerable<TransactionRecord>(response.signed_txs)
);
}

/// <summary>
Expand Down Expand Up @@ -800,5 +829,42 @@ public async Task<string> DidFindLostDid(string coinId, CancellationToken cancel
data.coin_id = coinId;
return await SendMessage<string>("did_find_lost_did", data, "latest_coin_id", cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Gets the current derivation index.
/// </summary>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns><see cref="uint"/></returns>
public async Task<uint> GetCurrentDerivationIndex(CancellationToken cancellationToken = default)
{
return await SendMessage<uint>("get_current_derivation_index", null, "index", cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Extends the current derivation index.
/// </summary>
/// <param name="index"></param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns><see cref="uint"/></returns>
public async Task<uint> ExtendDerivationIndex(uint index, CancellationToken cancellationToken = default)
{
dynamic data = new ExpandoObject();
data.index = index;
return await SendMessage<uint>("extend_derivation_index", data, "index", cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Retrieves the memo from a transaction.
/// </summary>
/// <param name="transactionId"></param>
/// <param name="cancellationToken">A token to allow the call to be cancelled</param>
/// <returns><see cref=""/></returns>
public async Task<IDictionary<string, IDictionary<string, IEnumerable<string>>>> GetTransactionMemo(string transactionId, CancellationToken cancellationToken = default)
{
dynamic data = new ExpandoObject();
data.transaction_id = transactionId;
var response = await SendMessage<IDictionary<string, IDictionary<string, IEnumerable<string>>>>("get_transaction_memo", data, cancellationToken).ConfigureAwait(false);

return response;
}
}
}