Skip to content

Commit f6b25d5

Browse files
committed
Add GetTransactions ThirdwebInsight API
Closes TOOL-3501
1 parent 5beb93e commit f6b25d5

File tree

3 files changed

+200
-3
lines changed

3 files changed

+200
-3
lines changed

Thirdweb.Console/Program.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343

4444
#region Indexer
4545

46-
// // Create a ThirdwebInsight instance
47-
// var insight = await ThirdwebInsight.Create(client);
46+
// Create a ThirdwebInsight instance
47+
var insight = await ThirdwebInsight.Create(client);
4848

4949
// // Setup some filters
5050
// var address = await Utils.GetAddressFromENS(client, "vitalik.eth");
@@ -78,6 +78,17 @@
7878
// );
7979
// Console.WriteLine($"Events: {JsonConvert.SerializeObject(events, Formatting.Indented)}");
8080

81+
// // Fetch transactions (great amount of optional filters available)
82+
// var transactions = await insight.GetTransactions(
83+
// chainIds: new BigInteger[] { 1 }, // ethereum
84+
// contractAddress: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d", // bored apes
85+
// fromTimestamp: Utils.GetUnixTimeStampNow() - 3600, // last hour
86+
// sortBy: SortBy.TransactionIndex, // block number, block timestamp or transaction index
87+
// sortOrder: SortOrder.Desc, // latest first
88+
// limit: 5 // last 5 transactions
89+
// );
90+
// Console.WriteLine($"Transactions: {JsonConvert.SerializeObject(transactions, Formatting.Indented)}");
91+
8192
#endregion
8293

8394
#region AI

Thirdweb/Thirdweb.Indexer/ThirdwebInsight.Types.cs

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ public class Token
3737

3838
public class Token_ERC20 : Token { }
3939

40-
public class Token_ERC721 : Token { }
40+
public class Token_ERC721 : Token
41+
{
42+
[JsonProperty("tokenId", Required = Required.Always)]
43+
public BigInteger TokenId { get; set; }
44+
}
4145

4246
public class Token_ERC1155 : Token
4347
{
@@ -81,6 +85,96 @@ public class Event
8185
public Decoded Decoded { get; set; } = null!;
8286
}
8387

88+
public class Transaction
89+
{
90+
[JsonProperty("chain_id", Required = Required.Always)]
91+
public BigInteger ChainId { get; set; }
92+
93+
[JsonProperty("block_number", Required = Required.Always)]
94+
public string BlockNumber { get; set; } = null!;
95+
96+
[JsonProperty("block_hash", Required = Required.Always)]
97+
public string BlockHash { get; set; } = null!;
98+
99+
[JsonProperty("block_timestamp", Required = Required.Always)]
100+
public string BlockTimestamp { get; set; } = null!;
101+
102+
[JsonProperty("hash", Required = Required.Always)]
103+
public string Hash { get; set; } = null!;
104+
105+
[JsonProperty("nonce", Required = Required.Always)]
106+
public BigInteger Nonce { get; set; }
107+
108+
[JsonProperty("transaction_index", Required = Required.Always)]
109+
public BigInteger TransactionIndex { get; set; }
110+
111+
[JsonProperty("from_address", Required = Required.Always)]
112+
public string FromAddress { get; set; } = null!;
113+
114+
[JsonProperty("to_address", Required = Required.Always)]
115+
public string ToAddress { get; set; } = null!;
116+
117+
[JsonProperty("value", Required = Required.Always)]
118+
public BigInteger Value { get; set; }
119+
120+
[JsonProperty("gas_price", Required = Required.Always)]
121+
public BigInteger GasPrice { get; set; }
122+
123+
[JsonProperty("gas", Required = Required.Always)]
124+
public BigInteger Gas { get; set; }
125+
126+
[JsonProperty("function_selector", Required = Required.Always)]
127+
public string FunctionSelector { get; set; } = null!;
128+
129+
[JsonProperty("data", Required = Required.Always)]
130+
public string Data { get; set; } = null!;
131+
132+
[JsonProperty("max_fee_per_gas", Required = Required.Always)]
133+
public BigInteger MaxFeePerGas { get; set; }
134+
135+
[JsonProperty("max_priority_fee_per_gas", Required = Required.Always)]
136+
public BigInteger MaxPriorityFeePerGas { get; set; }
137+
138+
[JsonProperty("transaction_type", Required = Required.Always)]
139+
public BigInteger TransactionType { get; set; }
140+
141+
[JsonProperty("r", Required = Required.Always)]
142+
public BigInteger R { get; set; }
143+
144+
[JsonProperty("s", Required = Required.Always)]
145+
public BigInteger S { get; set; }
146+
147+
[JsonProperty("v", Required = Required.Always)]
148+
public BigInteger V { get; set; }
149+
150+
[JsonProperty("access_list_json")]
151+
public string AccessListJson { get; set; }
152+
153+
[JsonProperty("contract_address")]
154+
public string ContractAddress { get; set; }
155+
156+
[JsonProperty("gas_used")]
157+
public BigInteger? GasUsed { get; set; }
158+
159+
[JsonProperty("cumulative_gas_used")]
160+
public BigInteger? CumulativeGasUsed { get; set; }
161+
162+
[JsonProperty("effective_gas_price")]
163+
public BigInteger? EffectiveGasPrice { get; set; }
164+
165+
[JsonProperty("blob_gas_used")]
166+
public BigInteger? BlobGasUsed { get; set; }
167+
168+
[JsonProperty("blob_gas_price")]
169+
public BigInteger? BlobGasPrice { get; set; }
170+
171+
[JsonProperty("logs_bloom")]
172+
public string LogsBloom { get; set; }
173+
174+
[JsonProperty("status")]
175+
public BigInteger? Status { get; set; }
176+
}
177+
84178
public class Decoded
85179
{
86180
[JsonProperty("name")]

Thirdweb/Thirdweb.Indexer/ThirdwebInsight.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ public class InsightEvents
2222
public Meta Meta { get; set; }
2323
}
2424

25+
public class InsightTransactions
26+
{
27+
public Transaction[] Transactions { get; set; }
28+
public Meta Meta { get; set; }
29+
}
30+
2531
public class ThirdwebInsight
2632
{
2733
private readonly IThirdwebHttpClient _httpClient;
@@ -234,6 +240,92 @@ public async Task<InsightEvents> GetEvents(
234240
return new InsightEvents { Events = result.Data, Meta = result.Meta, };
235241
}
236242

243+
/// <summary>
244+
/// Get transactions, optionally filtered by contract address, signature, and more.
245+
/// </summary>
246+
/// <param name="chainIds">The chain IDs to get the transactions from.</param>
247+
/// <param name="contractAddress">The contract address to get the transactions from. (Optional)</param>
248+
/// <param name="signature">The signature to filter transactions by. (Optional)</param>
249+
/// <param name="fromBlock">The starting block number to get the transactions from. (Optional, if provided, said block is included in query)</param>
250+
/// <param name="toBlock">The ending block number to get the transactions from. (Optional, if provided, said block is included in query)</param>
251+
/// <param name="fromTimestamp">The starting block timestamp to get the transactions from. (Optional, if provided, said block is included in query)</param>
252+
/// <param name="toTimestamp">The ending block timestamp to get the transactions from. (Optional, if provided, said block is included in query)</param>
253+
/// <param name="sortBy">The field to sort the transactions by. (Default: BlockNumber)</param>
254+
/// <param name="sortOrder">The order to sort the transactions by. (Default: Desc)</param>
255+
/// <param name="limit">The number of transactions to return. (Default: 20)</param>
256+
/// <param name="page">The page number to return. (Default: 0)</param>
257+
/// <param name="decode">Whether to decode the transactions. (Default: true)</param>
258+
/// <returns>The transactions and metadata as an instance of <see cref="InsightTransactions"/>.</returns>
259+
/// <exception cref="ArgumentException">Thrown when a signature is provided without a contract address.</exception>
260+
/// /// <exception cref="ArgumentException">Thrown when no chain IDs are provided.</exception>
261+
public async Task<InsightTransactions> GetTransactions(
262+
BigInteger[] chainIds,
263+
string contractAddress = null,
264+
string signature = null,
265+
BigInteger? fromBlock = null,
266+
BigInteger? toBlock = null,
267+
BigInteger? fromTimestamp = null,
268+
BigInteger? toTimestamp = null,
269+
SortBy sortBy = SortBy.BlockNumber,
270+
SortOrder sortOrder = SortOrder.Desc,
271+
int limit = 20,
272+
int page = 0,
273+
bool decode = true
274+
)
275+
{
276+
if (!string.IsNullOrEmpty(signature) && string.IsNullOrEmpty(contractAddress))
277+
{
278+
throw new ArgumentException("Contract address must be provided when signature is provided.");
279+
}
280+
281+
if (chainIds.Length == 0)
282+
{
283+
throw new ArgumentException("At least one chain ID must be provided.", nameof(chainIds));
284+
}
285+
286+
var baseUrl = $"{Constants.INSIGHT_API_URL}/v1/transactions";
287+
var url = AppendChains(
288+
!string.IsNullOrEmpty(contractAddress)
289+
? !string.IsNullOrEmpty(signature)
290+
? $"{baseUrl}/{contractAddress}/{signature}"
291+
: $"{baseUrl}/{contractAddress}"
292+
: baseUrl,
293+
chainIds
294+
);
295+
296+
url += $"&sort_by={SortByToString(sortBy)}";
297+
url += $"&sort_order={SortOrderToString(sortOrder)}";
298+
url += $"&limit={limit}";
299+
url += $"&page={page}";
300+
url += $"&decode={decode}";
301+
302+
if (fromBlock.HasValue)
303+
{
304+
url += $"&filter_block_number_gte={fromBlock}";
305+
}
306+
307+
if (toBlock.HasValue)
308+
{
309+
url += $"&filter_block_number_lte={toBlock}";
310+
}
311+
312+
if (fromTimestamp.HasValue)
313+
{
314+
url += $"&filter_block_timestamp_gte={fromTimestamp}";
315+
}
316+
317+
if (toTimestamp.HasValue)
318+
{
319+
url += $"&filter_block_timestamp_lte={toTimestamp}";
320+
}
321+
322+
var response = await this._httpClient.GetAsync(url).ConfigureAwait(false);
323+
_ = response.EnsureSuccessStatusCode();
324+
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
325+
var result = JsonConvert.DeserializeObject<ResponseModel<Transaction>>(responseContent);
326+
return new InsightTransactions { Transactions = result.Data, Meta = result.Meta, };
327+
}
328+
237329
private static string AppendChains(string url, BigInteger[] chainIds)
238330
{
239331
return $"{url}?chain={string.Join("&chain=", chainIds)}";

0 commit comments

Comments
 (0)