ByAUJay
Blockchain API Tutorial for Product Teams: From cURL to Production SDKs
A Practical Guide for Decision-Makers: Transitioning from Raw JSON-RPC Calls to Robust Multi-Chain SDKs
Are you excited to upgrade from plain old JSON-RPC calls to something way more reliable, like multi-chain SDKs? Awesome, you’ve come to the right spot! In this guide, we’re going to dive into some handy requests you can use to get started with cURL and start prototyping. Let’s jump in! Next up, we’ll jump into some great tips on how to beef up those production environment requests for both Ethereum--covering things like blobs and account abstraction--and Solana. On top of that, we're going to dive into some cool wallet integrations and discuss how to keep an eye on everything with observability patterns. This way, we can make sure everything runs like a well-oiled machine.
Let’s get started!
Who this guide is for
Hey there! If you’re a leader in product, platform, or engineering at a startup or a larger company and you're thinking about getting into blockchain integrations, then you’re in the right place! If you’re part of a team that’s already dabbled with RPC calls or SDKs, then you’ll definitely want to check this out. It’s perfect for those of you looking for a solid, observable, and scalable method to take your projects live.
What you’ll build by the end
Here’s a handy set of cURL “smoke tests” that you can quickly run on any RPC. They’re super easy to use! We've got a super smooth and ready-to-use SDK structure tailored for Node/TypeScript! Plus, if you’re into Python or Go, we’ve thrown in some handy tips for you too. Here are some solid strategies for tackling fees, retries, websockets, wallet discovery, and account abstraction (like ERC‑4337) on the Solana network, plus a bit about managing priority fees.
- A plan for observability that tracks JSON-RPC with OpenTelemetry, which is way more than just basic logging.
1) Know your RPC surface area (2025 reality)
Every EVM execution client basically offers the JSON-RPC methods you’re probably already familiar with. This includes things like making read calls (eth_call), sending transactions (eth_sendRawTransaction), checking out gas estimates (eth_estimateGas/eth_feeHistory), and even subscribing to updates through WebSocket (eth_subscribe). It's pretty standard across the board! If you’re on the hunt for a reliable reference, definitely take a look at Ethereum.org’s JSON-RPC page. It’s pretty much the go-to resource that your team should stick with as a standard. Trust me, it’ll come in handy! You can check it out here!
So, what’s been going on since those old “legacy gasPrice days”? Well, there's been quite a bit of change!
So, with EIP-1559, they've added some fresh fee fields for type-2 transactions. Now, you'll see maxFeePerGas and maxPriorityFeePerGas hanging around. Oh, and you'll notice that effectiveGasPrice will be included in your receipts, too! Just double-check that your API is all set up to handle these things consistently. You'll want to make sure everything runs smoothly! Take a look at this: eips.ethereum.org. You might find it interesting!
So, EIP-4844 rolled out these cool "blob" transactions, which come packed with some new stuff like maxFeePerBlobGas and blobVersionedHashes. Plus, they made a few updates to the block headers too, including blob_gas_used and excess_blob_gas. Pretty interesting changes, right? If you're working on indexing or submitting L2 data-availability posts, you'll want to make sure your API objects and signing processes can handle blobs. It's an important detail to keep in mind! If you want more details, just check this out: eips.ethereum.org. There’s plenty of info waiting for you!
Just a heads up, when you're diving into pub/sub, think of it as all about WebSockets. You’ll want to use eth_subscribe to keep tabs on new heads, logs, and any pending transactions. It's a pretty cool way to stay updated in real-time! Don’t forget to keep WS URLs in mind when you’re planning! Also, think about how you’ll handle auto-reconnects and what your game plan is for resubscribing. It’s all about making things seamless, right? You can find all the details you need right here: (alchemy.com).
If you’re diving into Solana, the primary way you’ll interact with it is through HTTP+WebSocket JSON-RPC. It's pretty much your go-to interface!
When it comes to managing your fees, it's super important to pay attention to the Compute Budget instructions. Basically, you need to set a cap on your Compute Units (CUs) and figure out how much each CU will cost you in micro-lamports. It’s all about keeping those costs in check!
Hey, if you're looking to stay on top of your pricing game, you should definitely check out getRecentPrioritizationFees to help you adjust things on the fly. It’s a smart move!
Hey, just a heads-up! It’s super important to know the different levels of commitment--like processed, confirmed, and finalized. Staying on top of these helps keep everything consistent and clear.
If you want to dive deeper into all the details, just hop on over to solana.com. You'll find everything you need there!
2) Prototype with cURL: your “RPC smoke tests”
Here are four sample requests you can easily plug into any environment (just swap out the URL/keys):
- GET Request:
GET https://your-api-url.com/endpoint?api_key=YOUR_API_KEY - POST Request:
POST https://your-api-url.com/endpoint Content-Type: application/json { "key1": "value1", "key2": "value2" } - PUT Request:
PUT https://your-api-url.com/endpoint/123?api_key=YOUR_API_KEY Content-Type: application/json { "key1": "new_value1", "key2": "new_value2" } - DELETE Request:
DELETE https://your-api-url.com/endpoint/123?api_key=YOUR_API_KEY
- Let's snag the latest block number, just to be on the safe side.
curl -s "$RPC_URL" -H "content-type: application/json" \
--data '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
- This is a read-only call for checking the balance of an ERC-20 token using
balanceOf.
curl -s "$RPC_URL" -H "content-type: application/json" \
--data '{
"jsonrpc":"2.0","id":2,"method":"eth_call",
"params":[{"to":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","data":"0x70a08231000000000000000000000000<ADDRESS_40_HEX>"},"finalized"]
}'
Hey, just a quick reminder--when you’re pulling in data that affects user balances and dashboards, make sure to stick with the block parameter throughout. Consistency is key! You’ve got a few options to pick from: “finalized,” “safe,” or “latest.” If you want to dive deeper, take a look at the docs over on ethereum.org. You’ll find all the info you need!
- EIP-1559 Fee Envelope
curl -s "$RPC_URL" -H "content-type: application/json" \
--data '{"jsonrpc":"2.0","id":3,"method":"eth_feeHistory","params":[5,"latest",[25,50,95]]}'
Hey, make sure to take a look at the fee history before you decide on the maxPriorityFeePerGas and maxFeePerGas values. It's really important not to just throw in some random numbers! If you want to dive deeper into this, you can check out the EIP-1559 documentation for more info.
- So, we're talking about WebSocket subscriptions here, which basically means you can set up real-time connections between your app and a server. Think of it like chatting with someone instantly instead of waiting for emails. You can use a tool called wscat for this - it's super handy for testing these connections out!
wscat -c "$WS_URL"
# then send
{"id":1,"jsonrpc":"2.0","method":"eth_subscribe","params":["newHeads"]}
Your production WebSocket client is set up to automatically reconnect, resubscribe, and make up for any missed ranges using eth_getLogs. So, no worries--it's got you covered!
Feel free to dive into more info at alchemy.com. There’s a bunch of details waiting for you!
Solana Fee Probe (Optional During POC)
curl -s https://api.mainnet-beta.solana.com -H "content-type: application/json" \
--data '{"jsonrpc":"2.0","id":1,"method":"getRecentPrioritizationFees","params":[]}'
Make sure you check out the samples we got back to figure out the microLamports per CU. Don’t just take a guess at it! If you want to dive deeper into the details, just hop over to solana.com. You'll find all the info you need!
3) From cURL to an SDK you can ship
Here’s a straightforward TypeScript shape that's super easy to scale!
We've got a straightforward interface for every chain, whether it's EVM or Solana. It comes with a typed request pipeline that makes things super easy to navigate. So, when we talk about policy middlewares, we're looking at a few key things: there are retries with jitter, which help when things aren't going smoothly; circuit breakers to prevent total meltdowns; request IDs for keeping track of what’s what; and timeouts to make sure we don’t get stuck waiting forever.
- You can track what's happening with OpenTelemetry spans for every JSON-RPC call (rpc.system=jsonrpc).
- We’ve got two ways to get things done: use HTTP for reading and batching info, and go with WebSocket for managing subscriptions.
Example: EVM Client with Batching, Backoff, OTel, and Fee Helpers
You could go with either Viem or Ethers v6 for this setup, but let's dive into how it all works with Viem as our example.
import { createPublicClient, http } from 'viem';
import { batch, getEthFeeHistory } from 'viem/clients';
import { getTokenMetrics } from 'some-metrics-library';
import { backoff } from 'backoff-helper';
import { trace } from 'opentelemetry-api';
// Create a new EVM client
const client = createPublicClient({
transport: http(),
});
// Function to fetch gas fees with retries
async function fetchGasFees() {
const fees = await backoff(async () => {
return await getEthFeeHistory(client);
});
return fees;
}
// Function to send batch transactions
async function sendBatchTransactions(transactions) {
const batchResponse = await batch(client, transactions);
return batchResponse;
}
// Example of using OTel for tracing
trace('fetchGasFees', async () => {
const fees = await fetchGasFees();
console.log('Gas fees:', fees);
});
// Metrics helper for tokens
const tokenMetrics = getTokenMetrics(client);
This little code snippet is a great way to get you started with interacting with the EVM and keeping your transaction management on point. You’ll love the perks of batching your requests, plus there's this handy automatic backoff feature for retries. And if you’re into monitoring, it even comes with built-in OpenTelemetry to help you trace those performance metrics.
// pkg/evmClient.ts
import { createPublicClient, http, webSocket } from 'viem'
import { mainnet } from 'viem/chains'
import pRetry from 'p-retry'
import { context, trace, SpanStatusCode } from '@opentelemetry/api'
const httpUrls = [process.env.RPC1!, process.env.RPC2!]
const wsUrl = process.env.RPC_WS!
export function makeEvmClient() {
// Simple endpoint rotation
let i = 0
const transport = http({
url: () => new URL(httpUrls[i = (i+1) % httpUrls.length]),
timeout: 10_000, // ms
batch: { batchSize: 20, wait: 10 }, // JSON-RPC batch for read fanout
})
const client = createPublicClient({ chain: mainnet, transport })
const wsClient = createPublicClient({ chain: mainnet, transport: webSocket(wsUrl) })
async function withSpan<T>(method: string, fn: () => Promise<T>) {
return await trace.getTracer('rpc').startActiveSpan(method, async (span) => {
span.setAttribute('rpc.system', 'jsonrpc')
span.setAttribute('rpc.method', method)
try {
const res = await pRetry(fn, { retries: 3, factor: 1.7, minTimeout: 200, maxTimeout: 1500, randomize: true })
span.setStatus({ code: SpanStatusCode.OK })
return res
} catch (e: any) {
span.setStatus({ code: SpanStatusCode.ERROR, message: e?.message })
// If provider returns JSON-RPC error, record code/message
if (e?.code) span.setAttribute('rpc.jsonrpc.error_code', e.code)
if (e?.message) span.setAttribute('rpc.jsonrpc.error_message', e.message)
throw e
} finally {
span.end()
}
})
}
return {
feeHistory: (blocks = 5) =>
withSpan('eth_feeHistory', () => client.request({ method: 'eth_feeHistory', params: [blocks, 'latest', [25, 50, 95]] })),
call: (tx: any, tag: string = 'latest') =>
withSpan('eth_call', () => client.request({ method: 'eth_call', params: [tx, tag] })),
sendRawTx: (raw: `0x${string}`) =>
withSpan('eth_sendRawTransaction', () => client.request({ method: 'eth_sendRawTransaction', params: [raw] })),
onNewHeads: (cb: (header: any) => void) =>
wsClient.transport.subscribe({ method: 'eth_subscribe', params: ['newHeads'] }, cb),
}
}
Hey, I've got some great news for you! The OTel attributes fit really well with the JSON-RPC semantic conventions. What does that mean for you? Well, you’ll get method-level histograms, error codes, and endpoint tags in your APM right from the start. Pretty awesome, right? Take a look at this link: opentelemetry.io. You'll find some interesting stuff there!
- If you’re working with batch reads for lists or index pages, no worries--geth has your back with JSON-RPC batching! This is an awesome way to reduce latency! Learn more here: (geth.ethereum.org).
If you're working with Python, you can totally pull this off by using httpx in combination with tenacity and opentelemetry-instrumentation-httpx. It's a great little setup!
When it comes to the Go side of things, teams have the option to use http. You’re working with the Clientfrom the standard library, and you’ve got it paired up with a transport wrapper andgo-otel`.
4) Fees that won’t page you at 3 a.m.
EVM (EIP-1559):
EIP-1559 is definitely one of the hottest topics buzzing around the Ethereum community right now. The goal here is to make transactions easier to anticipate and lower those pesky gas fees. Alright, let’s take a closer look at it.
What’s the Deal with EIP-1559?
Before EIP-1559 came along, people had to compete with each other by bidding on gas prices. This often resulted in some wild fees, especially during those busy times when everyone was trying to make a transaction. With this latest upgrade, Ethereum is rolling out a base fee that adjusts based on how busy the network gets. Instead of trying to guess what prices might be, you'll have a much smoother experience when you're sending transactions.
Why It Matters
- Predictable Costs: You'll have a clear idea of what those fees will look like, which makes budgeting for your transactions a whole lot easier.
- Fee Burn Mechanism: So, here’s how it works: when you make a transaction, a portion of the fee gets burned away. This process gradually lowers the total supply of Ethereum over time. Pretty cool, right? This could really boost ETH’s value down the line.
- Better User Experience: At the end of the day, it’s really about making Ethereum a more enjoyable and seamless experience for everyone!
How It Works
Let me break down how EIP-1559 works in a straightforward way:
1.
Base Fee: This is basically the lowest amount you'll need to spend on gas.
It changes depending on how crowded the network is.
2.
Tip: If you’d like to speed up your transaction, consider adding a little extra as a tip beyond the base fee. It can help get things moving along faster!
3.
Dynamic Adjustments: So, here’s the deal--the base fee gets tweaked after every block, depending on how packed the previous block was.
In Practice
So, let’s say you want to send some ETH, right? Forget about hunting down the best gas prices on a million different apps or websites. Now, you can just check out the base fee, toss in a tip if you need it done quickly, and you’re all set! Easy peasy!
If you're curious to dive deeper into the nitty-gritty, you can take a look at the official Ethereum Improvement Proposal, EIP-1559. Just head over to this link: EIP-1559.
Conclusion
EIP-1559 is really going to change the game when it comes to how we understand gas fees on Ethereum. With more stable pricing and a fee burn mechanism in place, it brings a refreshing level of clarity and efficiency to the network. It's nice to see things getting a bit more straightforward! As Ethereum keeps growing and changing, upgrades like this one are super important for making sure it gets better for everyone using it.
Hey there! Just a quick reminder: always remember to set both maxPriorityFeePerGas and maxFeePerGas. Trust me, it’ll save you a lot of hassle down the road!
You can definitely work this out by looking at the recent fee history and adjusting it to match your budget. It's a good idea not to just rely on the "auto" values set by the provider.
Don’t forget to include effectiveGasPrice in your receipts! It’s super helpful for tracking what you really spent.
(eips.ethereum.org).
- If you're dealing with replace‑by‑fee, just make sure you do it safely! If you find yourself with a transaction that's stuck, all you need to do is resubmit it. Just use the same nonce, but bump up that
maxFeePerGas(and it's a good idea to increase yourmaxPriorityFeePerGasas well). Instead of using hash to keep tabs on your transactions, try using nonce. It might make things a bit easier for you in your store.
EVM Blobs (EIP-4844)
EVM blobs are a really cool addition to the Ethereum scene! Let’s break it down real quick--here’s what they are and why they matter!
What Are EVM Blobs?
EVM blobs are really just big chunks of data that you can toss into transactions on the Ethereum network. So, these are part of the Ethereum Improvement Proposal (EIP) 4844. The idea behind it is to boost scalability by using these blobs to hold more data without overloading the main Ethereum chain. Pretty clever, right?
Why They Matter
1. Higher Throughput: EVM blobs can boost how much data gets processed in each transaction, which means the network can handle more at once. This really speeds things up and makes everything run more smoothly!
2. Lower Costs: Thanks to better scalability, we might see transaction fees drop, which means it could be a lot cheaper for folks to use the Ethereum blockchain.
3. Better User Experience: When the network runs smoother and faster, everyone wins--developers and users both! This boost in performance makes it way more enticing for people to dive into creating and using decentralized applications (dApps).
How EVM Blobs Work
EVM blobs basically let users add these bigger chunks of data to their transactions. It's a handy feature that makes things a lot more flexible! These are set up to be super easy to access and parse, so apps can manage the extra data without putting too much pressure on the network.
Key Takeaways
So, EVM blobs are actually a component of EIP-4844.
- They allow for storing a lot more data during transactions. They guarantee quicker and cheaper transactions, plus an overall better experience on the Ethereum network.
If you're looking to dive deeper into EIP-4844, you can head over to the official Ethereum Improvement Proposals page. It’s a great resource for getting all the nitty-gritty details!
Hey, just a quick reminder to include maxFeePerBlobGas and blobVersionedHashes when you’re putting together your transaction payload. It’s super important to have those covered!
Just a quick reminder: the address can't be nil because blob transactions aren't designed for creating contracts.
Just a heads up--if you're thinking about archiving or indexing, remember that blobs get pruned after roughly two weeks. So, if there's any data you want to hang onto, make sure to have some external storage options lined up. Better safe than sorry!
(eips.ethereum.org).
Solana (Priority Fees):
Solana is really starting to grab some attention in the blockchain space, especially for its lightning-fast transactions and super low fees. Just like in a lively city, there are times when you might have to fork over a bit more cash to jump ahead in the queue for your transaction. That's where priority fees come in handy.
What are Priority Fees?
So, think of priority fees as a little extra something you give to miners (or validators if you're on Solana) to speed up your transaction. It’s kind of like tipping to make sure your order gets bumped to the front of the line! Imagine it like finding a faster lane when there’s a bunch of congestion on the blockchain. When you toss in a priority fee, it’s like saying, “Hey, could you give me a hand with this?”
Why Use Priority Fees?
1. Faster Transactions: Got somewhere to be and need your transaction to go through quickly? Simply adding a priority fee can help you jump the queue and speed things up. 2. Network Congestion: When things get really busy, you might notice that transaction fees can change a bit. Priority fees help make sure your transaction gets confirmed quickly, so you don't have to wait around. 3. Flexibility: You get to decide how much to pay depending on how quickly you need to get things done. More urgency? Higher fee.
How to Set Priority Fees on Solana
Using priority fees on Solana is super easy! Alright, here’s a simple guide to help you kick things off:
1. Pick Your Wallet: Make sure you've got a wallet that can handle Solana and lets you set priority fees. 2. Set the Fee: Once you're all set to send your transaction, don't forget to check out the option to tweak the fee. Usually, you'll see a slider or an input box where you can adjust your preferred priority fee. 3. Confirm the Transaction: After you’ve decided on your fee and double-checked everything, just hit that send button and watch your transaction fly through!
Things to Keep in Mind
- Dynamic Fees: Just a heads up! The market can shift pretty fast, so keep in mind that fees might fluctuate depending on how busy the network is at any given moment.
- Budgeting: If you find yourself often using priority fees, it’s a good idea to keep track of how much you’re spending. If you're not careful, those little things can really pile up over time.
- Performance: So, priority fees can definitely help you get things moving faster, but don’t count on them to get your transaction confirmed right away, especially when there’s a lot of activity going on.
If you’re looking for more in-depth info about Solana transactions and fees, definitely take a look at their official documentation. It’s super helpful and packed with all the details you’ll need!
If you want to figure out the total prioritization fee, just use this simple formula: take your CU limit and multiply it by the microLamports per CU. It’s pretty straightforward!
Don't forget to use ComputeBudgetProgram.setComputeUnitLimit and setComputeUnitPrice. Also, make sure to size everything based on your simulation and throw in a bit of extra headroom just to be safe!
When it comes to pricing, just grab the info from getRecentPrioritizationFees, and don’t forget to consider the commitment for reads!
(solana.com).
5) Real‑time without chaos: WebSockets done right
Just a heads up: remember to use different WebSocket URLs and keys because they often don’t match the HTTP endpoints on most providers. It's a little quirk you might run into! Alright, here’s the game plan: You’ll want to set up heartbeat pings to keep things in sync. Don’t forget to add some exponential backoff with a dash of jitter for those pesky connection drops. When you reconnect, make sure you resubscribe to get back on track. And lastly, use eth_getLogs or newHeads to fill in any gaps starting from the last block you caught. Got it? So, when you're dealing with subscriptions, I’d suggest keeping it simple with logs for those app-level events. But if you're looking to kick off pipelines or index streams, definitely use newHeads. It just makes things smoother! Just a quick reminder: eth_subscribe works exclusively with WebSocket. So, think of HTTP as your backup plan, and you'll want to use polling for that. Take a look at this link: alchemy.com. You won’t regret it!
6) Wallet connectivity: modern discovery and sessioning
EIP‑6963 (Multi-Wallet Discovery)
EIP-6963 is all about helping you find multiple wallets that are tied to one Ethereum account. Pretty neat, right? So, instead of digging through all your wallets to find what you need, you can easily access them all in one spot. How convenient is that? Alright, let me break it down for you:
Purpose
This EIP aims to make it easier for users to manage their wallets. The goal here is to make the Ethereum ecosystem easier to navigate by simplifying how we manage wallets.
Key Features
- Simple to Find: Users can effortlessly locate all the wallets tied to their Ethereum account, making the whole process a breeze.
- Better Privacy: You get to manage your wallets however you like and decide which ones you want to show off.
- Better User Experience: This feature is really focused on simplifying things for users when it comes to managing their wallets. We're all about making life a little easier!
Benefits
- Saves you time: Forget about spending ages hunting down all those different wallets. Now, you can keep everything together in one handy place!
- Easier Management: You can effortlessly monitor all your assets spread out over different wallets.
- Privacy Control: You get to decide which wallets you share, so you can relax knowing your info is safe.
Conclusion
EIP-6963 is a really exciting update that makes juggling multiple wallets so much easier! It’s all about keeping things simple and protecting your privacy, which really helps make the whole Ethereum experience better for everyone.
- Nowadays, browser dapps shouldn't just depend on that one
window.ethereumanymore. You can totally take advantage of EIP-6963’s event-based discovery feature to easily spot multiple injected providers. This way, users get to pick and choose what works best for them! With this change, we finally say goodbye to that annoying “last extension wins” situation. (eips.ethereum.org).
Of course! Just share the text you'd like me to rework, and I'll get started on it.
type ProviderDetail = { info: { uuid:string; name:string; icon:string; rdns:string }, provider: any }
const wallets: ProviderDetail[] = []
window.addEventListener('eip6963:announceProvider', (event: any) => {
wallets.push(event.detail)
})
window.dispatchEvent(new CustomEvent('eip6963:requestProvider'))
// Now render a modal from `wallets` and connect to the chosen EIP-1193 provider
WalletConnect v2 (namespaces):
WalletConnect v2 has rolled out some pretty cool updates, and one of the highlights is the new namespaces feature. Alright, let’s take a closer look at what that actually means for you! Here’s the scoop.
What are Namespaces?
With WalletConnect v2, namespaces let you neatly group different DApps (Decentralized Applications) together. This way, managing your connections becomes a breeze! Imagine it’s like organizing your files into different folders. It just makes everything neater and way easier to find what you need!
How Does it Work?
When you connect your wallet, you get to choose which namespace you want to work with. What this means is that your wallet can hook up to a bunch of different DApps at the same time, all without any confusion or mix-ups. Pretty handy, right?
Here’s a quick example:
{
"namespace": "eip155",
"chains": ["1", "3", "4"],
"methods": ["eth_sendTransaction", "eth_signMessage"],
"events": ["chainChanged", "accountsChanged"]
}
In this little section, you'll notice how to set up the chain you want to connect to, such as Ethereum, along with the different methods you can use. It’s pretty straightforward!
Benefits of Using Namespaces
1. Stay Organized: Make your DApps easier to manage by sorting them into relevant namespaces. It just helps keep everything tidy and makes it simpler to find what you need!
2. Better User Experience: It's super easy for users to hop between different DApps without feeling lost or overwhelmed.
3. Boosted Security: With each namespace being separate, it really helps to strengthen security by reducing the chances of any unwanted interactions between different DApps.
Implementing Namespaces
If you want to use namespaces in your DApp, here’s a simple guide to help you out:
1. Define Your Namespace: Think about how you’d like to set up your namespaces. What structure feels right for you? 2. Time to Update Your WalletConnect Client: Just a quick reminder to check that your client is all set to work with namespaces. 3. Connect as Usual: Just a heads up, when you connect, don’t forget to add the namespace to your request!
Using namespaces can really enhance your DApp experience, so definitely give this awesome feature a try! Looking to learn more? Take a look at the WalletConnect documentation for all the details you need!
When you’re working on your session proposals, don’t forget to add the necessary namespaces, such as methods, chains, and events. It’s super important to have those in there!
Hey there! So, if your app works across multiple blockchains, make sure you remember to request eip155 along with any other ones you might need, like solana. Just a little heads-up!
Wallets will send you a list of session namespaces that shows the specific accounts (CAIP-10).
If there's a problem with your proposal, the wallets will reject it with error code 1006.
Just a little reminder to keep this in mind while you’re working on your session UX design!
(specs.walletconnect.com).
Example Proposal Snippet
Introduction
Hey! We're really excited to share our proposal with you! We’re here to help you reach [insert goal] with our one-of-a-kind approach.
Project Overview
Here’s a little peek into what’s been on our minds:
- Goal: To make sure you have a smooth experience that really caters to what you're looking for.
- Timeline: We're planning to get started on [insert start date] and finish things up by [insert end date]. Can't wait to dive in!
- Budget: We’re looking at an estimated budget of [insert budget] for this project.
Deliverables
We're excited to share that we’ll be rolling out a few important updates!
1. [Deliverable 1]: A thorough rundown of [details]. 2. [Deliverable 2]: A detailed report that highlights [details]. 3. [Deliverable 3]: An easy-to-use interface for [details].
Conclusion
We’re super excited about the chance to team up and make this project a hit! If you have any questions or want more info, don’t hesitate to get in touch! I'm here to help!
Best,
[Your Name]
[Your Title]
[Your Contact Information]
[Your Company]
{
"requiredNamespaces": {
"eip155": {
"methods":["eth_sendTransaction","eth_signTypedData","personal_sign"],
"chains":["eip155:1","eip155:8453"],
"events":["accountsChanged","chainChanged"]
},
"solana": {
"methods":["solana_signTransaction","solana_signMessage"],
"chains":["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"],
"events":[]
}
}
}
7) Account Abstraction (ERC‑4337) without surprises
Hey there! If you’re diving into “gasless” or passkey wallets, it’s a good idea to expand your API options beyond just using eth_sendRawTransaction.
So, when users want to interact with the bundler, they whip up these things called UserOperation objects and send them off using the eth_sendUserOperation command.
So, what happens next is that the bundler runs a quick check using simulateValidation. After that, it gets right to it and submits handleOps to the EntryPoint contract.
On top of that, Paymasters can either take care of gas fees themselves or they can accept ERC-20 tokens to cover those costs.
(eips.ethereum.org).
Practical Guidance:
Jumping into a new project or facing a challenge? Having a few handy tips up your sleeve can really change the game. Just a few things to remember:
1. Take It Easy: Seriously, don’t feel like you have to tackle everything all at the same time. Break your tasks down into smaller, more manageable chunks. It'll make things a whole lot easier and less overwhelming! That makes things so much easier, right?
2. Set Clear Goals: Figure out what you're aiming for. Setting clear and measurable goals can make a big difference in staying focused and pumped up. When you know exactly what you’re aiming for, it’s way easier to stay motivated!
3. Stay Organized: Make sure to keep your workspace and digital files neat and tidy. A clean space can really help you focus! Just a bit of organization can really help you get more done.
4. Focus on What Matters: Remember, not everything on your to-do list carries the same weight. Some tasks are definitely more important than others! One great way to figure out what really needs your attention right now is by using the Eisenhower Matrix. It’s a handy tool that helps you sort tasks based on their urgency and importance, so you can focus on what matters most. Give it a try! You might find it really helps clear up your to-do list.
5. Learn to Say No: Look, sometimes you've just gotta put your foot down and guard your time. It's important! If something doesn’t really fit with what you’re aiming for or what’s important to you, feel free to say no.
6.
Ask for Feedback: Don't hesitate to reach out and get some input!
Sometimes, just getting a fresh pair of eyes on things can really open up your mind to new ideas you hadn’t thought about before.
7. Take Breaks: Don't forget to take a little time for yourself. It's important to hit pause every now and then! Taking short breaks is a great way to refresh yourself and return with a sharper mindset.
8. Go with the Flow: Life is full of surprises, and that’s totally fine! Just stay open to change when things don’t turn out quite how you imagined.
If you keep these tips in mind, you'll find it a bit easier and more confident to tackle your projects. Happy working!.
Hey there! Just a friendly reminder to lock in your EntryPoint version for every network you’re working with--like making sure it's set to v0. 6 or v0. Make sure to save the addresses in your configuration. Before you dive into building something from scratch, why not take a look at what provider ecosystems like Infura and MetaMask have to offer? Their bundler JSON-RPC might have just what you need! If you want more details, just click here!
If you’re working with a verifying paymaster, think of its signer as a crucial part of your production setup. It's really important to treat it with care! If you're looking to get a good grasp of the basics, check out Coinbase's reference contracts. They really lay down a solid foundation for you to build on. Feel free to check them out here!
- Make sure to keep tabs on alt-mempool results by checking out a few important metrics. You’ll want to watch the simulation fail rates sorted by class--think things like signature, paymaster, and initCode. Also, pay attention to inclusion latency and how those refunds are stacking up. So, your SDK has the ability to wrap bundler calls just like it does with the eth_ methods, and you can totally reuse the same OTel spans for that. If you want to dive deeper into the details, just take a look at this link: docs.erc4337.io. Happy reading!
8) Networks and testnets (2025‑2026 planning)
If you're diving into app and tool development, Sepolia is definitely the testnet to check out. It's still leading the pack!
If you’re into validators, staking, or just messing around with protocol testing, Hoodi is definitely the way to go! It’s got everything you need to dive right in.
Hey, just a quick heads up! Holešky is set to retire in September 2025, so it’s a good idea to start planning your migrations. Also, if you were thinking about kicking off any new projects there, it might be best to hold off.
Oh, and just a heads up--there’s a new testnet on the way that’s going to replace Sepolia in March 2026. Exciting times ahead!
Just a friendly reminder to keep these timelines in mind as you’re working on your release plans and putting together the developer documentation. It'll help keep everything on track!
(ethereum.org).
9) Production patterns that prevent fire drills
Reliability and Rate Limits
- Horizontal provider failover: It’s a good idea to have at least two RPCs set up for each chain. This way, you’ll have a backup ready to go if one of them runs into issues! Whenever you get a request, switch things up a bit. And if things don't go as planned, take a step back and ease into it--basically, try checking things out first before jumping into tougher write operations.
- Backoff strategies: Make sure to utilize backoff with a bit of jitter and throw in some circuit breaking to handle those annoying 429 and 5xx errors. Hey, just a quick reminder to make sure you've got the provider status displayed on your dashboards. It's super helpful for everyone to stay in the loop about what's happening!
- Batch read fanouts: Rather than sending out 50 calls individually, it’s way more efficient to group them together in batches. Hey, if you're looking for some info, you can find all the details right here: geth.ethereum.org. It's a good resource!
Idempotency and Nonce Discipline (EVM)
- So, when you're handling write requests, the go-to thing to rely on is the combination of the sender and the nonce. That's your trusty source! So, if you accidentally send the same nonce more than once, don’t worry! The network’s got your back and will just filter out any duplicates for you. To avoid any accidental duplicates, it's a good idea to set up a nonce lock for each sender. Also, make sure to use a replacement strategy that only accepts transactions with higher fees. This way, you can keep things running smoothly!
Websocket Robustness
Don’t forget to set up that ping/pong thing to keep the connection nice and alive! It’s a great way to ensure everything stays connected. Also, adding a little jittered reconnect can really help you deal with any bumps in the road. It’ll make the experience a lot smoother!
Hey, just a quick reminder! When you're working on re-establishing those connections, don't skip over the resubscribe part. And make sure to handle the block-range reconciliation when you're resuming. This means you'll want to pull up those logs and use the fromBlock feature too. It'll help keep everything in sync!
When it comes to events, it's best to use WS (WebSocket) for getting those real-time updates. But for backfills, I recommend using HTTP batching. It’s a smarter way to handle those requests and keeps everything running smoothly.
Observability You Can Actually Use
Hey there! So, when you're working with JSON-RPC methods, make sure to track those OTel spans for each one. You'll want to include some key parameters like rpc.system=jsonrpc, the rpc.method, server.address, and request_id. And just a heads-up: if something goes wrong, don't forget to add in the rpc.jsonrpc.error_code and error_message. It'll really help you troubleshoot!
Oh, and don’t forget to create some histograms for rpc.client.duration, breaking it down by method and endpoint!
That way, you can really back up those "provider vs app" debates with solid proof.
Take a look at this link: opentelemetry.io. You’ll find some pretty cool info there!
Security and Key Management
Think of API keys as super sensitive passwords. It's really important to limit their access by IP or origin, switch them out regularly, and definitely don’t pack them into your web apps. Keep them safe! Hey there! When it comes to signing, it’s super smart to either centralize your Hardware Security Module (HSM) or secure enclaves if you're looking at custodial options. On the flip side, if you're leaning towards non-custodial, you might want to check out EIP-4337 smart accounts--they come with well-defined scopes that can really help. So, when you're diving into Solana, you'll find that hot keys are pretty much the norm. To play it safe, it’s a good idea to keep their blast radius as small as possible. And for those big transactions, think about using fee-payer vaults. They can really help!
10) A thin internal SDK that ages well
Resist Writing a Monolith
Rather than building one huge, all-in-one application, it’s way more effective to set up a simple contract that your app teams can rely on. Here’s a friendly way to tackle it:
So, you've got these typed method wrappers that are designed to deal with certain inputs and outputs. For instance, there’s getErc20Balance for checking your ERC20 token balance, sendEip1559Tx for sending transactions using the EIP-1559 standard, and subscribeLogs for keeping tabs on logs. They're pretty handy for making things smoother!
You’ve got a reliable transport layer that comes packed with handy features like retries, metrics, and feature flags. This means you can effortlessly switch between providers and easily toggle WebSocket connections on or off whenever you need to. How cool is that?
We've got dedicated modules just for the fee policies and chain configurations, specifically designed for both EVM and Solana.
- We've included OpenRPC schemas right in your SDK so you can easily generate documentation and code without any hassle.
It could be really helpful to open up
rpc.discoverinternally. This way, our downstream teams can use it for easier validation and testing. Take a look at spec.open-rpc.org! You don’t want to miss it!
Example OpenRPC Doc Fragment for Your Internal “evm-ops” Service:
Hey there! Here’s a little sneak peek at how you could go about laying out your OpenRPC documentation for the "evm-ops" service. This little piece here is a great place to kick things off!
{
"openrpc":"1.2.3",
"info": {
"title": "EVM Operations Service",
"description": "This service provides operations related to Ethereum Virtual Machine.",
"version": "1.0.0"
},
"methods": [
{
"name": "getBalance",
"params": [
{
"name": "address",
"required": true,
"schema": {
"type": "string",
"description": "The Ethereum address to query."
}
}
],
"result": {
"schema": {
"type": "string",
"description": "The balance of the queried address in wei."
}
},
"description": "Fetch the balance of the specified Ethereum address."
},
{
"name": "sendTransaction",
"params": [
{
"name": "from",
"required": true,
"schema": {
"type": "string",
"description": "The sender's Ethereum address."
}
},
{
"name": "to",
"required": true,
"schema": {
"type": "string",
"description": "The recipient's Ethereum address."
}
},
{
"name": "value",
"required": true,
"schema": {
"type": "string",
"description": "The amount of wei to send."
}
}
],
"result": {
"schema": {
"type": "string",
"description": "The transaction hash for the sent transaction."
}
},
"description": "Send a transaction from one Ethereum address to another."
}
]
}
Don't hesitate to adjust this example however you like so it fits your service perfectly!
{
"openrpc": "1.3.2",
"info": { "title": "EVM Ops RPC", "version": "0.1.0" },
"methods": [
{
"name": "evm.sendRawTransaction",
"params": [{ "name": "raw", "schema": { "type": "string", "pattern": "^0x[0-9a-fA-F]+$" } }],
"result": { "name": "txHash", "schema": { "type": "string" } }
},
{
"name": "evm.subscribeLogs",
"params": [{ "name": "filter", "schema": { "$ref": "#/components/schemas/LogFilter" } }],
"result": { "name": "subscriptionId", "schema": { "type": "string" } }
}
]
}
11) Chain‑specific gotchas we see in audits
- EVM Log Filters: When you're diving into log filters, just remember to keep it focused on either an address or topic0. It'll make things way simpler! If you decide to use unbounded filters, just a heads up--you might hit some timeouts or even find yourself getting rate-limited.
- EIP-4844: Just a quick note--I've noticed that various providers have their own ways of dealing with blob gossip. It's smart to plan for retries and give yourself a little extra time on those blob submissions. If you're looking to rehydrate your data, you might want to think about using out-of-band DA mirrors. They could really help with that! If you want to dive deeper into this, you can check it out here: (eips.ethereum.org). It’s definitely worth a look!
- Solana: Just a quick heads-up--when you're working with ComputeBudget instructions, the order really matters! Be sure to call
setComputeUnitLimitbefore you dive into any instructions that actually consume those compute units. It can make a big difference! Oh, and hey, just a quick reminder about commitment: it's super important that user-visible balances are confirmed and finalized, not just processed. You really want to make sure everything matches up! If you're looking for more details, you can check it out here: solana.com. It’s got everything you need!
12) A short, end‑to‑end example: from cURL to SDK to AA
- How about we whip up a prototype that covers both reading and writing?
- eth_call → Alright, first things first, let’s make sure we can access the contract ABI.
- eth_feeHistory → Now, let’s pick the fee envelope that suits our needs perfectly.
- eth_sendRawTransaction → Alright, let’s go ahead and send off that signed type-2 transaction! Just remember to keep track of the nonce while we’re at it.
- Get real-time updates:
- To keep an eye on events from your contract, go ahead and use
eth_subscribewith the event topic. So, you’re looking to set up a WebSocket client that automatically reconnects and manages backfill? Great choice! Here’s a quick guide on how to do that.
First up, you’ll want to ensure that your client can handle reconnections smoothly. This means you’ll need to implement some logic to detect when the connection drops and trigger a reconnect. It can be super helpful to add a little delay between reconnection attempts to avoid overwhelming the server.
Next, let’s talk about backfill. This is where things can get a bit tricky, but it’s crucial. You’ll want your client to request any missed messages or data when it reconnects. Make sure to keep track of the last message or data point you received so you can request everything that came in after that.
By combining these elements, you’ll have a WebSocket client that stays connected and ensures you never miss a beat. Happy coding!
3) Upgrade Wallets:
We've rolled out EIP‑6963 wallet discovery to help make your browsing experience a lot smoother! Hey team! Let's get WalletConnect v2 out there. We need to make sure we include the requiredNamespaces for both EVM and Solana.
4) Add AA Milestones:
Just shoot a UserOperation over to a managed bundler like Infura, MetaMask, or Pimlico.
- Create a paymaster to handle gas fees when bringing new users on board.
You'll automatically get OTel spans for
eth_sendUserOperation, plus it'll keep track of simulation failure categories without any extra setup needed. Pretty convenient, right? Check it out here!.
- Deploy to the testnet, but make sure you’ve got a backup plan just in case! If you're testing your app, go ahead and use Sepolia. But if you need to test out a validator or a protocol, Hoodi is the way to go! Hey, just a heads up--try to avoid kicking off any new projects on Holešky since it's scheduled to wrap up in September 2025. Hey, make sure to write down these defaults for your teams! (ethereum.org).
13) “Copy‑paste‑able” snippets your team can reuse
- Ethers v6: How to Send a Type-2 Transaction with Fee Caps.
Hey there! So, if you're getting into Ethers v6 and want to send a type-2 transaction with those cool fee caps, you’ve come to the right spot! Let’s walk through the steps together.
Prerequisites
Before you dive in, just double-check that you’ve got everything you need:
- It’s good to have a simple grasp of how Ethereum transactions work.
- Check out the newest version of Ethers.js!
- Make sure you've got some Ether in your wallet to cover those gas fees.
Sending a Type-2 Transaction
Hey there! If you're looking to send a type-2 transaction with fee caps using Ethers v6, I've got a straightforward guide for you. Let’s dive in!
1. Get your wallet ready: To kick things off, go ahead and set up your wallet.
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("YOUR_JSON_RPC_PROVIDER_URL");
const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY", provider);
2. Let’s kick off your transaction: Alright, now it's time to set up the details for your transaction. Here’s where you can set the limits for the fees.
const tx = {
to: "RECIPIENT_ADDRESS",
value: ethers.parseUnits("0.1", "ether"),
gasLimit: 21000,
type: 2, // Indicates a type-2 transaction
maxFeePerGas: ethers.parseUnits("50", "gwei"),
maxPriorityFeePerGas: ethers.parseUnits("2", "gwei"),
};
3.
Go ahead and send your transaction: Now it’s time to send your transaction! Just use the sendTransaction method to get it done.
async function sendTx() {
const transactionResponse = await wallet.sendTransaction(tx);
console.log(`Transaction sent! Hash: ${transactionResponse.hash}`);
// Wait for the transaction to be confirmed
await transactionResponse.wait();
console.log("Transaction confirmed!");
}
sendTx().catch(console.error);
Conclusion
And there you have it! You've successfully sent a type-2 transaction with fee caps using Ethers v6. Nice job! This should definitely help you keep your transaction costs in check. If you're curious about transactions or want to dive into Ethers.js, definitely take a look at the documentation. It’s a great resource that can help you out! Happy coding!.
import { ethers } from 'ethers'
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL!)
const wallet = new ethers.Wallet(process.env.PRIVKEY!, provider)
const fee = await provider.send('eth_feeHistory', [5, 'latest', [50]])
const base = BigInt(fee.baseFeePerGas.slice(-1)[0])
const maxPriorityFeePerGas = 2_000_000_000n
const maxFeePerGas = base * 2n + maxPriorityFeePerGas
const tx = await wallet.sendTransaction({
to: '0x...', value: 0n, data: '0x',
maxPriorityFeePerGas, maxFeePerGas
})
await tx.wait()
- Solana web3.js: How to Properly Set Priority Fees
import { Connection, Keypair, SystemProgram, Transaction, ComputeBudgetProgram } from '@solana/web3.js'
const conn = new Connection('https://api.mainnet-beta.solana.com', 'confirmed')
const payer = Keypair.fromSecretKey(/* ... */)
const cuPrice = 15000 // microLamports per CU, from getRecentPrioritizationFees
const cuLimit = 300_000
const ixLimit = ComputeBudgetProgram.setComputeUnitLimit({ units: cuLimit })
const ixPrice = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: cuPrice })
const ix = SystemProgram.transfer({ fromPubkey: payer.publicKey, toPubkey: payer.publicKey, lamports: 1 })
const tx = new Transaction().add(ixLimit, ixPrice, ix)
const sig = await conn.sendTransaction(tx, [payer])
await conn.confirmTransaction(sig, 'confirmed')
Hey, take a look at getRecentPrioritizationFees. You can adjust the cuPrice depending on how busy things are and what time it is. It’s pretty handy!
If you're looking for more info, just check out the documentation here. It’s all laid out for you!
14) Launch checklist (print this)
- RPC We've got two providers lined up for each chain, and they’re all set with rotation and health checks in place. We've done a really good job testing out the WebSocket reconnection and resubscription features. Everything's working smoothly!
- Hey, guess what? Batching is turned on for read fanouts, and that’s awesome for boosting efficiency!
- Fees So, we're working with EIP-1559 caps, looking at the fee history to guide our decisions. We're also putting blob fee caps in place wherever it makes sense to do so. So, the limits on Solana's compute units and pricing are actually determined by something called ComputeBudget. They take a look at the latest fees to set those prices.
- Wallets We've got EIP-6963 discovery all set up, and we've double-checked that WalletConnect v2 namespaces are good to go.
- AA (if used) We've got our bundler endpoint SLAs all set up, locked down the EntryPoint version, and made our paymaster keys even stronger for added security.
- Observability
We're keeping tabs on OTel spans for all our JSON-RPC calls, and we’re logging the rpc.method and error_code to gain some valuable insights.
We’ve got Service Level Objectives (SLOs) in place for
rpc.client.duration, specifically aiming for the p95 level for every method and endpoint. - Testnets Right now, we’re set up to use Sepolia for app development and Hoodi for handling validator and protocol tasks. Hey there! Just a quick heads-up--there aren’t any new dependencies on Holešky. You can check out more details over at ethereum.org.
Where 7Block Labs helps
We help your teams ace their blockchain integrations by focusing on key areas like setting up API baselines, designing and reviewing SDKs, creating fee policies, rolling out AA, and making sure production observability is on point. Hey there! If you're up for a project that runs for about 2 to 4 weeks, we can help you transition from cURL to a full SDK. And the best part? You get to keep all the code! If that sounds good to you, let’s chat!
Sources and further reading
Hey! If you're diving into Ethereum, definitely take a look at the overview of JSON-RPC. It covers all the basics, like the block parameters and a handy catalog of methods. It's a great resource to get you familiar with how things work! (ethereum.org).
- Check out EIP-1559! It explains type-2 fees and the effectiveGasPrice you'll see in receipts. (eips.ethereum.org). Hey there! If you want to make your interactions more efficient, check out JSON-RPC batching in Geth. It’s a great way to streamline things! (geth.ethereum.org).
- Check out EIP‑4844 for all the juicy details on blob transactions, header fields, and fee fields. (eips.ethereum.org).
- Let’s dive into WebSocket subscriptions and chat about how to make the most out of eth_subscribe! (alchemy.com). Get to know the OpenTelemetry JSON-RPC semantic conventions. It'll really help you boost your observability game! (opentelemetry.io). Hey, have a look at EIP-6963! It dives into the whole idea of multi-injected provider discovery. It’s pretty interesting stuff! (eips.ethereum.org). Hey there! If you want to boost your app's connectivity, definitely check out WalletConnect v2. It’s got these cool namespaces and session proposals that can really make a difference. Dive into the details and see how they can upgrade your app! (specs.walletconnect.com). Take a deep dive into ERC-4337! This includes everything from the specifications to the docs on bundlers and paymasters. Plus, don’t miss the handy reference for Infura and MetaMask bundlers. It's all there for you to explore! (eips.ethereum.org).
- Dive into the scoop on Solana fees, how to prioritize them, and check out the RPC documentation. It’s everything you need to know to manage those fees and make the most of your transactions! (solana.com). Hey there! Just a quick reminder to check out the testnet guidance for Sepolia and Hoodi before you miss it. Oh, and don’t forget that Holešky is wrapping up soon too! (ethereum.org).
Like what you're reading? Let's build together.
Get a free 30-minute consultation with our engineering team.
Related Posts
ByAUJay
Building a Donation-Based Crowdfunding Platform That Gives Tax Receipts
**Summary:** Donation-based crowdfunding that includes tax receipts has become quite the complex puzzle across different regions. You've got to navigate IRS Pub 1771/526 rules, UK Gift Aid declarations, Canada’s CRA receipting, and the new eIDAS/OpenID4VCI wallets--all while keeping everything running smoothly.
ByAUJay
Why 'Full-Lifecycle Advisory' Beats Just Coding
**Summary:** Engineering teams that focus solely on “writing Solidity” often find themselves caught off guard by shifts in protocols, the need for composable security, and the procurement hurdles that are now impacting real ROI. Our full-lifecycle advisory service bridges the gap by connecting EIP-7702 smart accounts, modular decentralized applications (DA), and ZK-based compliance solutions.
ByAUJay
Why Your Project Could Really Use a 'Protocol Economist
Summary: A lot of Web3 teams are missing a crucial player: the “protocol economist.” And you can really see the impact--value slips away through MEV routing, token incentives that are all out of whack, and those sneaky changes to wallets after Pectra that end up messing with the unit economics. In this playbook, we’ll explore what a protocol economist can do to tackle these issues head-on.

