Migrating Oracle To Postgres Data Access Code
github/awesome-copilot
Migrates .NET/C data access code from Oracle to PostgreSQL (Npgsql).
Index blockchain data (blocks, transactions, logs, tokens) to PostgreSQL/SqlServer/SQLite with progress tracking, reorg handling, and hosted services (.NET/C).
$ npx skills add Nethereum/Nethereum --skill blockchain-indexing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Nethereum/Nethereum blockchain-indexing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Nethereum/Nethereum.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/nethereum-skills/skills/blockchain-indexing .claude/skills/blockchain-indexing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "blockchain-indexing" agent skill from https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexing into .claude/skills/blockchain-indexing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blockchain-indexing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Nethereum/Nethereum --skill blockchain-indexing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Nethereum/Nethereum blockchain-indexing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Nethereum/Nethereum.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/nethereum-skills/skills/blockchain-indexing .agents/skills/blockchain-indexing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "blockchain-indexing" agent skill from https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexing into .agents/skills/blockchain-indexing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blockchain-indexing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Nethereum/Nethereum --skill blockchain-indexing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Nethereum/Nethereum blockchain-indexing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Nethereum/Nethereum.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/nethereum-skills/skills/blockchain-indexing .cursor/skills/blockchain-indexing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "blockchain-indexing" agent skill from https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexing into .cursor/skills/blockchain-indexing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blockchain-indexing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Nethereum/Nethereum.git --path plugins/nethereum-skills/skills/blockchain-indexing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Nethereum/Nethereum --skill blockchain-indexing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Nethereum/Nethereum blockchain-indexing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Nethereum/Nethereum.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/nethereum-skills/skills/blockchain-indexing .gemini/skills/blockchain-indexing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "blockchain-indexing" agent skill from https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexing into .gemini/skills/blockchain-indexing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blockchain-indexing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Nethereum/Nethereum blockchain-indexingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Nethereum/Nethereum --skill blockchain-indexing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Nethereum/Nethereum.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/nethereum-skills/skills/blockchain-indexing .github/skills/blockchain-indexing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "blockchain-indexing" agent skill from https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexing into .github/skills/blockchain-indexing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blockchain-indexing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Nethereum/Nethereum --skill blockchain-indexing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Nethereum/Nethereum blockchain-indexing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Nethereum/Nethereum.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/nethereum-skills/skills/blockchain-indexing .opencode/skills/blockchain-indexing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "blockchain-indexing" agent skill from https://github.com/Nethereum/Nethereum/tree/master/plugins/nethereum-skills/skills/blockchain-indexing into .opencode/skills/blockchain-indexing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "blockchain-indexing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
blockchain-indexingIndex blockchain data (blocks, transactions, logs, tokens) to PostgreSQL/SqlServer/SQLite with progress tracking, reorg handling, and hosted services (.NET/C).
Blockchain Indexing is an agent skill from Nethereum/Nethereum. Index blockchain data (blocks, transactions, logs, tokens) to PostgreSQL/SqlServer/SQLite with progress tracking, reorg handling, and hosted services (.NET/C). Use this skill when the user asks about blockchain indexing, block processing, event log crawling, database storage for blockchain data, token transfer indexing, balance aggregation, or chain reorganisation handling.
Its SKILL.md is about 4.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Databases. It works with PostgreSQL, SQLite, .NET and C#. The repository describes itself as: Ethereum .Net cross platform integration library. The licence is MIT.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 229f278. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are csharp and json).
From the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
eth.llamarpc.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Blockchain Indexing loads about 4.8k tokens when it runs. Until then it costs about 99 tokens; SKILL.md has 499 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Nethereum/Nethereum at commit 229f278, republished under its MIT licence (© Nethereum). 499 words, ~4,847 tokens.
.claude/skills/blockchain-indexing/SKILL.md (or your agent's skills folder).Nethereum provides a full block/log processing pipeline that crawls an Ethereum-compatible chain, stores blocks, transactions, logs, and token data into a relational database (Postgres, SQL Server, or SQLite via EF Core), tracks progress, handles chain reorgs, and runs as a .NET hosted service.
| Package | Purpose |
|---|---|
Nethereum.BlockchainProcessing | Core pipeline: crawlers, processors, progress repos, entity models |
Nethereum.BlockchainStore.EFCore | EF Core base context and repository factory |
Nethereum.BlockchainStore.Postgres | Postgres EF Core provider |
Nethereum.BlockchainStore.SqlServer | SQL Server EF Core provider |
Nethereum.BlockchainStore.Sqlite | SQLite EF Core provider |
Nethereum.BlockchainStorage.Processors | Hosted service, options, DI extensions |
Nethereum.BlockchainStorage.Processors.Postgres | One-call Postgres DI setup |
Nethereum.BlockchainStorage.Processors.SqlServer | One-call SQL Server DI setup |
Nethereum.BlockchainStorage.Processors.Sqlite | One-call SQLite DI setup |
using Nethereum.BlockchainStorage.Processors.Postgres;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddPostgresBlockchainProcessor(
builder.Configuration,
connectionString: "Host=localhost;Database=blockchain;Username=postgres;Password=secret");
var host = builder.Build();
await host.RunAsync();appsettings.json:
{
"BlockchainProcessing": {
"BlockchainUrl": "https://eth.llamarpc.com",
"FromBlock": 20000000,
"MinimumBlockConfirmations": 12,
"ReorgBuffer": 20,
"NumberOfBlocksToProcessPerRequest": 1000,
"UseBatchReceipts": true,
"ProcessBlockTransactionsInParallel": true,
"RetryWeight": 50
}
}This registers BlockchainProcessingHostedService (a BackgroundService) that continuously crawls blocks, persists them to Postgres, and auto-retries with exponential backoff on failure.
// Postgres
services.AddPostgresBlockchainProcessor(configuration, connectionString);
// SQL Server (optional schema)
services.AddSqlServerBlockchainProcessor(configuration, connectionString, schema: "eth");
// SQLite
services.AddSqliteBlockchainProcessor(configuration, connectionString);Each extension method wires up the EF Core context, BlockchainProcessingOptions, and the hosted service in one call. Connection string resolution order: explicit parameter, ConnectionStrings:PostgresConnection (or SqlServerConnection/SqliteConnection), ConnectionStrings:BlockchainDbStorage.
public sealed class BlockchainProcessingOptions
{
public string? BlockchainUrl { get; set; }
public string? Name { get; set; }
public BigInteger? FromBlock { get; set; }
public BigInteger? ToBlock { get; set; }
public uint? MinimumBlockConfirmations { get; set; }
public int ReorgBuffer { get; set; } = 0;
public int NumberOfBlocksToProcessPerRequest { get; set; } = 1000;
public int RetryWeight { get; set; } = 50;
public bool UseBatchReceipts { get; set; } = true;
public bool ProcessBlockTransactionsInParallel { get; set; } = true;
public bool PostVm { get; set; } = false;
}Bound from IConfiguration section "BlockchainProcessing" or root keys.
The processing pipeline has three layers:
public class BlockProcessingSteps
{
public IProcessor<BlockWithTransactions> BlockStep;
public IProcessor<TransactionVO> TransactionStep;
public IProcessor<TransactionReceiptVO> TransactionReceiptStep;
public IProcessor<FilterLogVO> FilterLogStep;
public IProcessor<ContractCreationVO> ContractCreationStep;
}Each step is a Processor<T> that holds a list of ProcessorHandler<T> instances. Add handlers to react to each entity type.
Use web3.Processing.Blocks to create a block processor with custom step handlers:
using Nethereum.BlockchainProcessing.BlockProcessing;
using Nethereum.BlockchainProcessing.ProgressRepositories;
using Nethereum.Web3;
var web3 = new Web3("https://eth.llamarpc.com");
var progressRepo = new JsonBlockProgressRepository(
jsonSourceExists: () => Task.FromResult(File.Exists("progress.json")),
jsonWriter: json => File.WriteAllTextAsync("progress.json", json),
jsonRetriever: () => File.ReadAllTextAsync("progress.json"));
var processor = web3.Processing.Blocks.CreateBlockProcessor(
progressRepo,
steps =>
{
steps.BlockStep.AddSynchronousProcessorHandler(block =>
Console.WriteLine($"Block {block.Number} with {block.Transactions.Length} txs"));
steps.TransactionStep.AddSynchronousProcessorHandler(tx =>
Console.WriteLine($" Tx {tx.Transaction.TransactionHash}"));
steps.TransactionReceiptStep.AddSynchronousProcessorHandler(receipt =>
Console.WriteLine($" Receipt status: {receipt.TransactionReceipt.Status}"));
steps.FilterLogStep.AddSynchronousProcessorHandler(log =>
Console.WriteLine($" Log {log.Log.Address} topic0={log.Log.EventSignature}"));
steps.ContractCreationStep.AddSynchronousProcessorHandler(contract =>
Console.WriteLine($" Contract created: {contract.ContractAddress}"));
},
minimumBlockConfirmations: 12);
var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
await processor.ExecuteAsync(cts.Token, startAtBlockNumberIfNotProcessed: 20000000);To store everything in a database automatically:
var repoFactory = new BlockchainStoreRepositoryFactory(dbContextFactory);
var processor = web3.Processing.Blocks.CreateBlockStorageProcessor(
repoFactory,
progressRepo,
minimumBlockConfirmations: 12);
await processor.ExecuteAsync(cancellationToken);Use web3.Processing.Logs for targeted event log crawling without full block processing:
using Nethereum.Contracts.Standards.ERC20.ContractDefinition;
var processor = web3.Processing.Logs.CreateProcessor<TransferEventDTO>(
action: transfer =>
Console.WriteLine($"Transfer {transfer.Event.From} -> {transfer.Event.To}: {transfer.Event.Value}"),
minimumBlockConfirmations: 12,
criteria: transfer => transfer.Event.Value > 0);
await processor.ExecuteAsync(cts.Token, startAtBlockNumberIfNotProcessed: 20000000);var usdcAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
var processor = web3.Processing.Logs.CreateProcessorForContract<TransferEventDTO>(
usdcAddress,
action: transfer =>
Console.WriteLine($"USDC Transfer: {transfer.Event.Value}"),
minimumBlockConfirmations: 12);
await processor.ExecuteAsync(cts.Token, startAtBlockNumberIfNotProcessed: 20000000);var processor = web3.Processing.Logs.CreateProcessorForContracts<TransferEventDTO>(
new[] { "0xA0b86991...", "0xdAC17F958..." },
action: transfer => { /* handle */ },
minimumBlockConfirmations: 12);var transfers = await web3.Processing.Logs.ERC20
.GetAllTransferEventsForContract(
usdcAddress, fromBlockNumber: 20000000, toBlockNumber: 20001000,
cancellationToken);
var accountTransfers = await web3.Processing.Logs.ERC20
.GetAllTransferEventsFromAndToAccount(
usdcAddress, "0xMyAddress...",
fromBlockNumber: 20000000, toBlockNumber: null,
cancellationToken);var processor = web3.Processing.Logs.CreateProcessor(
action: (FilterLog log) =>
Console.WriteLine($"Log from {log.Address}"),
minimumBlockConfirmations: 12,
filter: new NewFilterInput { Address = new[] { contractAddress } });var processor = web3.Processing.Logs.CreateProcessor(
logProcessors: handlers,
minimumBlockConfirmations: 12,
reorgBuffer: 20,
filter: filterInput,
blockProgressRepository: progressRepo);public interface IBlockProgressRepository
{
Task UpsertProgressAsync(BigInteger blockNumber);
Task<BigInteger?> GetLastBlockNumberProcessedAsync();
}JsonBlockProgressRepository -- persists to a JSON file:
var progressRepo = new JsonBlockProgressRepository(
jsonSourceExists: () => Task.FromResult(File.Exists("progress.json")),
jsonWriter: json => File.WriteAllTextAsync("progress.json", json),
jsonRetriever: () => File.ReadAllTextAsync("progress.json"),
lastBlockProcessed: 19999999);InMemoryBlockchainProgressRepository -- for testing or one-shot runs:
var progressRepo = new InMemoryBlockchainProgressRepository(startBlock);Database-backed -- BlockchainStoreRepositoryFactory.CreateBlockProgressRepository() stores progress in the same DB as block data.
Wraps any progress repository to subtract a reorg buffer from the last-processed block, causing re-processing of recent blocks:
var buffered = new ReorgBufferedBlockProgressRepository(innerRepo, reorgBuffer: 20);When GetLastBlockNumberProcessedAsync() returns 100, the buffered repo returns 80, so the processor re-crawls blocks 81-100 each cycle.
The pipeline supports chain reorganisation detection and recovery:
BlockchainProcessingOptions -- re-processes the last N blocks each cycle to catch shallow reorgs.ReorgDetectedException when a mismatch is found.RewindToBlockNumber, LastCanonicalBlockNumber, LastCanonicalBlockHash.Block, Transaction, and TransactionLog entities all have IsCanonical bool. Non-canonical data is marked via INonCanonicalBlockRepository, INonCanonicalTransactionRepository, INonCanonicalTransactionLogRepository.// Full reorg-aware processor with chain state validation
var processor = web3.Processing.Logs.CreateProcessor(
logProcessors: handlers,
minimumBlockConfirmations: 12,
reorgBuffer: 20,
chainStateRepository: repoFactory.CreateChainStateRepository(),
filter: filterInput,
blockProgressRepository: progressRepo);All entities inherit from TableRow (provides RowIndex, RowCreated, RowUpdated).
public class Block : TableRow, IBlockView
{
public long BlockNumber { get; set; }
public string Hash { get; set; }
public string ParentHash { get; set; }
public string Miner { get; set; }
public string GasLimit { get; set; }
public string GasUsed { get; set; }
public long Timestamp { get; set; }
public long TransactionCount { get; set; }
public string BaseFeePerGas { get; set; }
public string StateRoot { get; set; }
public bool IsCanonical { get; set; } = true;
public bool IsFinalized { get; set; }
public int? ChainId { get; set; }
// + Difficulty, TotalDifficulty, Nonce, ExtraData, Size,
// ReceiptsRoot, LogsBloom, WithdrawalsRoot, BlobGasUsed,
// ExcessBlobGas, ParentBeaconBlockRoot, RequestsHash, etc.
}public class TransactionBase : TableRow, ITransactionView
{
public string BlockHash { get; set; }
public long BlockNumber { get; set; }
public string Hash { get; set; }
public string AddressFrom { get; set; }
public string AddressTo { get; set; }
public string Value { get; set; }
public string Gas { get; set; }
public string GasPrice { get; set; }
public string GasUsed { get; set; }
public string Input { get; set; }
public long Nonce { get; set; }
public bool Failed { get; set; }
public string Error { get; set; }
public string NewContractAddress { get; set; }
public bool IsCanonical { get; set; } = true;
public string MaxFeePerGas { get; set; }
public string MaxPriorityFeePerGas { get; set; }
public long TransactionType { get; set; }
// + EffectiveGasPrice, CumulativeGasUsed, RevertReason,
// MaxFeePerBlobGas, BlobGasUsed, BlobGasPrice, etc.
}public class TransactionLog : TableRow, ITransactionLogView
{
public string TransactionHash { get; set; }
public long LogIndex { get; set; }
public string Address { get; set; }
public string EventHash { get; set; }
public string IndexVal1 { get; set; }
public string IndexVal2 { get; set; }
public string IndexVal3 { get; set; }
public string Data { get; set; }
public long BlockNumber { get; set; }
public string BlockHash { get; set; }
public bool IsCanonical { get; set; } = true;
}public class Contract : TableRow, IContractView
{
public string Address { get; set; }
public string Name { get; set; }
public string ABI { get; set; }
public string Code { get; set; }
public string Creator { get; set; }
public string TransactionHash { get; set; }
}public class TokenMetadata : TableRow, ITokenMetadataView
{
public string ContractAddress { get; set; }
public string Name { get; set; }
public string Symbol { get; set; }
public int Decimals { get; set; }
public string TokenType { get; set; }
}public class TokenBalance : TableRow, ITokenBalanceView
{
public string Address { get; set; }
public string ContractAddress { get; set; }
public string Balance { get; set; }
public string TokenType { get; set; }
public long LastUpdatedBlockNumber { get; set; }
}public interface IBlockchainStoreRepositoryFactory
{
IBlockRepository CreateBlockRepository();
ITransactionRepository CreateTransactionRepository();
ITransactionLogRepository CreateTransactionLogRepository();
IContractRepository CreateContractRepository();
IAddressTransactionRepository CreateAddressTransactionRepository();
ITransactionVMStackRepository CreateTransactionVmStackRepository();
}
public interface IBlockRepository
{
Task UpsertBlockAsync(Block source);
Task<IBlockView> FindByBlockNumberAsync(HexBigInteger blockNumber);
}
public interface ITransactionRepository
{
Task UpsertAsync(TransactionReceiptVO transactionReceiptVO);
Task UpsertAsync(TransactionReceiptVO transactionReceiptVO, string code, bool failedCreatingContract);
Task<ITransactionView> FindByBlockNumberAndHashAsync(HexBigInteger blockNumber, string hash);
}
public interface ITransactionLogRepository
{
Task UpsertAsync(FilterLogVO log);
Task<ITransactionLogView> FindByTransactionHashAndLogIndexAsync(string hash, BigInteger logIndex);
}public interface ITokenBalanceRepository
{
Task UpsertAsync(TokenBalance balance);
Task UpsertBatchAsync(IEnumerable<TokenBalance> balances);
Task<IEnumerable<ITokenBalanceView>> GetByAddressAsync(string address);
Task<IEnumerable<ITokenBalanceView>> GetByContractAsync(string contractAddress, int page, int pageSize);
Task DeleteByBlockNumberAsync(BigInteger blockNumber);
}
public interface INFTInventoryRepository
{
Task UpsertAsync(NFTInventory item);
Task UpsertBatchAsync(IEnumerable<NFTInventory> items);
Task<IEnumerable<INFTInventoryView>> GetByAddressAsync(string address);
Task<INFTInventoryView> GetByTokenAsync(string contractAddress, string tokenId);
}public interface INonCanonicalBlockRepository
{
Task MarkNonCanonicalAsync(BigInteger fromBlockNumber);
}
public interface INonCanonicalTransactionRepository
{
Task MarkNonCanonicalAsync(BigInteger fromBlockNumber);
}Built-in services for common token event crawling:
// Access via web3.Processing.Logs.ERC20 / web3.Processing.Logs.ERC721
// Get all ERC-20 Transfer events for a contract
var transfers = await web3.Processing.Logs.ERC20
.GetAllTransferEventsForContract(contractAddress, fromBlock, toBlock, cancellationToken);
// Get all transfers to/from a specific account (any contract)
var myTransfers = await web3.Processing.Logs.ERC20
.GetAllTransferEventsFromAndToAccount(account, fromBlock, toBlock, cancellationToken);
// Get all transfers to/from account for specific contracts
var filtered = await web3.Processing.Logs.ERC20
.GetAllTransferEventsFromAndToAccount(
new[] { usdcAddress, daiAddress }, account, fromBlock, toBlock, cancellationToken);The BlockchainProcessor supports two execution modes:
// Continuous: runs until cancellation, following the chain head
await processor.ExecuteAsync(
cancellationToken: cts.Token,
startAtBlockNumberIfNotProcessed: 20000000,
waitInterval: 1000);
// Bounded: runs from start to a specific block number, then stops
await processor.ExecuteAsync(
toBlockNumber: 20100000,
cancellationToken: cts.Token,
startAtBlockNumberIfNotProcessed: 20000000);// Register options
services.AddBlockchainProcessingOptions(configuration);
// Register EF Core storage (pick one)
services.AddPostgresBlockchainStorage(connectionString);
// or: services.AddSqlServerBlockchainStorage(connectionString, schema);
// or: services.AddSqliteBlockchainStorage(connectionString);
// Register processor + hosted service
services.AddBlockchainProcessor();
// Optional: internal transaction processor
services.AddInternalTransactionProcessor();Implement ILogProcessingObserver for custom metrics:
public interface ILogProcessingObserver
{
void SetChainHead(BigInteger blockNumber);
void OnBlockProgressUpdated(BigInteger blockNumber);
void OnReorgDetected(BigInteger rewindTo, BigInteger lastCanonical);
void OnError(string errorType);
}© Nethereum, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in plugins/nethereum-skills/skills/blockchain-indexing of Nethereum/Nethereum.
Open the folder on GitHubat commit 229f278
Blockchain Indexing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Blockchain Indexing this skillNethereum/Nethereum | 2.3k | — | ~4.8k | Automated safety check: Pass | MIT | |
| Migrating Oracle To Postgres Data Access Codegithub/awesome-copilot | 40k | — | ~2k | Automated safety check: Pass | MIT | |
| Matlab Use Databasematlab/matlab-agentic-toolkit | 1.1k | — | ~3.1k | Automated safety check: Pass | Custom licence | |
| Drizzle Orm Patternsgiuseppe-trisciuoglio/developer-kit | 356 | — | ~1.5k | Automated safety check: Notes | MIT | |
| SQL Expertaiskillstore/marketplace | 430 | — | ~3.4k | Automated safety check: Pass | None | |
| Dbcraftaiskillstore/marketplace | 430 | — | ~2.3k | Automated safety check: Pass | None |
github/awesome-copilot
Migrates .NET/C data access code from Oracle to PostgreSQL (Npgsql).
matlab/matlab-agentic-toolkit
Reads from, writes to, and manages relational databases using MATLAB Database Toolbox.
giuseppe-trisciuoglio/developer-kit
Provides comprehensive Drizzle ORM patterns for schema definition, CRUD operations, relations, queries, transactions, and migrations.
aiskillstore/marketplace
Expert SQL query writing, optimization, and database schema design with support for PostgreSQL, MySQL, SQLite, and SQL Server.
aiskillstore/marketplace
Open and operate the local DB Craft visual schema studio at D:\DBdesigner.
prest/prest
Guides classifying, gap-analyzing and scaffolding support for a new SQL database in pREST, from Postgres-compatible variants to entirely new dialects.
Nethereum/Nethereum
Help users batch multiple calls into a single UserOperation and sponsor gas with paymasters using Nethereum Account Abstraction.
Nethereum/Nethereum
Help users run an ERC-4337 bundler using Nethereum — set up in-process or standalone bundlers with mempool, validation, reputation, and JSON-RPC server.
Nethereum/Nethereum
Encode and decode Ethereum ABI data with Nethereum. An agent skill from Nethereum/Nethereum.
Nethereum/Nethereum
Fetch contract ABIs from Sourcify, Etherscan, and 4Byte Directory using the composite ABIInfoStorage pattern (.NET/C).
Nethereum/Nethereum
Help users implement ERC-4337 Account Abstraction with Nethereum — send UserOperations, use smart accounts, route contract calls through a bundler, enable gasless transactions, or work with AA in…
Nethereum/Nethereum
Validate and format Ethereum addresses with Nethereum. An agent skill from Nethereum/Nethereum.
Categories
Index blockchain data (blocks, transactions, logs, tokens) to PostgreSQL/SqlServer/SQLite with progress tracking, reorg handling, and hosted services (.NET/C). Blockchain Indexing is an agent skill from Nethereum/Nethereum.NET/C).
Blockchain Indexing fits situations like: the user asks about blockchain indexing; block processing; event log crawling; database storage for blockchain data.
Run `npx skills add Nethereum/Nethereum --skill blockchain-indexing -a claude-code`. Or copy the skill folder (plugins/nethereum-skills/skills/blockchain-indexing in Nethereum/Nethereum) into .claude/skills/blockchain-indexing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Nethereum/Nethereum --skill blockchain-indexing -a codex`. Or copy the skill folder (plugins/nethereum-skills/skills/blockchain-indexing in Nethereum/Nethereum) into .agents/skills/blockchain-indexing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Nethereum/Nethereum --skill blockchain-indexing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/blockchain-indexing, .gemini/skills/blockchain-indexing, .github/skills/blockchain-indexing and .opencode/skills/blockchain-indexing in your project.
SKILL.md names no scripts, command-line tools or credentials: Blockchain Indexing is instructions for the agent only.
SKILL.md names 1 domain. In commands or code: eth.llamarpc.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Blockchain Indexing is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.8k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Blockchain Indexing: Migrating Oracle To Postgres Data Access Code (github/awesome-copilot, 40k stars), Matlab Use Database (matlab/matlab-agentic-toolkit, 1.1k stars), Drizzle Orm Patterns (giuseppe-trisciuoglio/developer-kit, 356 stars) and SQL Expert (aiskillstore/marketplace, 430 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Nethereum (a GitHub organization) maintains it in Nethereum/Nethereum, which has 2,260 GitHub stars. The repository holds 71 skills in this directory. The repository was last updated on October 5, 2026.
Source: Nethereum/Nethereum on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.