-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
📝 Blog: Eip 1193 the standard (#1487)
## Description _Concise description of proposed changes_ ## Testing Explain the quality checks that have been done on the code changes ## Additional Information - [ ] I read the [contributing docs](../docs/contributing.md) (if this is your first contribution) Your ENS/address: <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a comprehensive overview of EIP-1193, enhancing interoperability for Ethereum development. - Added practical examples for implementing EIP-1193 and creating a custom optimistic transport. - **Documentation** - Updated documentation for the `getBlockFromRpc` function, clarifying parameters and return types. - Removed the file exploring Layer 2 scaling solutions and the "VM Wars" in Ethereum. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
1 parent
dc52267
commit e605859
Showing
4 changed files
with
209 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
```typescript | ||
import {createMemoryClient, http} from 'tevm' | ||
import {numberToHex} from 'tevm/utils' | ||
import MyContract from '<chain-id>:<contract-address>?rpcUrl=https://my.rpc.url' | ||
|
||
main() | ||
|
||
async function main() { | ||
const client = createMemoryClient({ | ||
fork: { transport: http('https://my.rpc.url') }, | ||
}) | ||
setupDebugger() | ||
await client.contract({ | ||
abi: MyContract.abi, | ||
functionName: 'someMethod', | ||
args: ['method', 'args'], | ||
}) | ||
} | ||
|
||
// registers a debugger on the evm | ||
function setupDebugger() { | ||
const vm = await client.getVm() | ||
|
||
vm.evm.events.on('step', async (step, next) => { | ||
console.log({ | ||
pc: step.pc, | ||
op: step.opcode.name, | ||
gasCost: BigInt(step.opcode.fee) + (step.opcode.dynamicFee ?? 0n), | ||
gas: step.gasLeft, | ||
depth: step.depth, | ||
stack: step.stack.map((code) => numberToHex(code)), | ||
}) | ||
// here we would track things like stack depth etc. | ||
await stopForDebuggerOrBreakpoint() | ||
}) | ||
} | ||
|
||
// here is where we plug in the ui to stop execution for the debugger | ||
// for now just use a javascript debugger | ||
async function stopForDebuggerOrBreakpoint () { | ||
debugger | ||
} | ||
``` | ||
|
164 changes: 164 additions & 0 deletions
164
docs/src/content/docs/blog/0_eip-1193-the-unsung-hero.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
--- | ||
title: "EIP-1193: The Unsung Hero of Ethereum Development" | ||
description: "Discover how EIP-1193 is revolutionizing JavaScript libraries in the Ethereum ecosystem, with practical examples and a vision for the future." | ||
date: 2024-10-20 | ||
author: "fucory" | ||
--- | ||
|
||
### The Power of Standards in Ethereum Development | ||
|
||
In the ever-evolving world of blockchain technology, standards are the unsung heroes that keep our digital universe from descending into chaos. They're the silent guardians of interoperability, the champions of frictionless development, and the backbone of seamless integration. Among these standards, one stands out as a beacon of hope for JavaScript libraries interacting with Ethereum: EIP-1193. | ||
|
||
If you're developing JavaScript libraries for Ethereum and you're not leveraging EIP-1193 at every turn, you might be missing out on a revolutionary approach to blockchain interaction. Let's dive into why this standard is not just important, but essential for the future of Ethereum development. | ||
|
||
#### Demystifying EIP-1193: The Swiss Army Knife of Ethereum Providers | ||
|
||
At its core, EIP-1193 is a standardized interface for Ethereum providers in JavaScript applications. Think of it as a universal language that allows your code to communicate with Ethereum nodes, regardless of the underlying implementation. It's like having a Swiss Army knife for blockchain interactions – versatile, reliable, and always ready for action. | ||
|
||
The heart of EIP-1193 is a simple yet powerful `request` function. This function is your gateway to the Ethereum blockchain, allowing you to send JSON-RPC requests and listen for critical events like network changes or new blocks. | ||
|
||
Let's see EIP-1193 in action with a practical example: | ||
|
||
```typescript | ||
import { createMemoryClient } from 'tevm'; | ||
import { http } from 'viem'; | ||
|
||
// Create an EIP-1193 compatible transport | ||
const eip1193ForkTransport = http('https://mainnet.optimism.io')({}); | ||
|
||
// Initialize a Tevm client with our transport | ||
const tevmClient = createMemoryClient({ | ||
fork: { transport: eip1193ForkTransport } | ||
}) satisfies EIP1193Provider; | ||
|
||
// Listen for blockchain events | ||
tevmClient.on('connect', () => { | ||
console.log('Blockchain connection established. Ready for action!'); | ||
}); | ||
|
||
// Fetch an account balance | ||
const balance = await tevmClient.request({ | ||
method: 'eth_getBalance', | ||
params: ['0x1234567890abcdef1234567890abcdef12345678', 'latest'], | ||
}); | ||
console.log('Account balance:', balance); | ||
|
||
// Set a balance (using a custom method) | ||
await tevmClient.request({ | ||
method: 'anvil_setBalance', | ||
params: ['0x1234567890abcdef1234567890abcdef12345678', '0xDE0B6B3A7640000'], // 1 ETH | ||
}); | ||
console.log('Balance updated. Time to make it rain!'); | ||
``` | ||
|
||
In this example, we're not just making API calls; we're orchestrating a symphony of blockchain interactions. We're setting up an HTTP transport, initializing a Tevm client, listening for network events, fetching balances, and even manipulating the blockchain state – all through the elegant simplicity of EIP-1193. | ||
|
||
#### The EIP-1193 Advantage: Flexibility, Composability, and Future-Proofing | ||
|
||
You might be wondering, "Why go through all this trouble? Can't I just use a simple RPC URL and call it a day?" Well, you could, but you'd be missing out on a world of possibilities. Here's why EIP-1193 is the secret sauce to superior Ethereum development: | ||
|
||
1. **Unparalleled Flexibility**: With EIP-1193, you're not tied to a single node or network. You can seamlessly switch between different transports – be it WebSocket, HTTP, or even an in-memory client – without rewriting your core logic. | ||
|
||
2. **Composability at Its Finest**: EIP-1193 providers are the LEGO blocks of Ethereum development. You can mix and match different tools and libraries with ease. Imagine using a Viem client as a transport for Tevm, or vice versa. The possibilities are endless! | ||
|
||
3. **Future-Proof Your Code**: As the Ethereum ecosystem evolves, EIP-1193 ensures your code won't be left behind. New features? No problem. Just update your provider, and you're good to go. | ||
|
||
Let's contrast this with a more traditional approach: | ||
|
||
```typescript | ||
class LegacySDK { | ||
constructor(rpcUrl) { | ||
this.rpcUrl = rpcUrl; | ||
} | ||
|
||
async getBalance(address) { | ||
const response = await fetch(this.rpcUrl, { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ | ||
jsonrpc: '2.0', | ||
method: 'eth_getBalance', | ||
params: [address, 'latest'], | ||
id: 1, | ||
}), | ||
}); | ||
return await response.json(); | ||
} | ||
|
||
// ... other methods | ||
} | ||
|
||
const sdk = new LegacySDK('https://mainnet.infura.io/v3/YOUR_API_KEY'); | ||
const balance = await sdk.getBalance('0x1234567890abcdef1234567890abcdef12345678'); | ||
``` | ||
|
||
This approach, while simple, is a relic of the past. It's inflexible, hard to extend, and ties you to a specific node. It's like trying to build a skyscraper with a hammer and nails – it might work, but it's far from optimal. | ||
|
||
#### Embracing the Future: Building an Optimistic Transport | ||
|
||
To truly appreciate the power of EIP-1193, let's push the boundaries and create a custom transport that handles optimistic updates. This isn't just a theoretical exercise – it's a glimpse into the future of Ethereum development: | ||
|
||
```typescript | ||
import { custom, http, loadBalance, rateLimit } from 'viem'; | ||
import { createMemoryClient } from 'tevm'; | ||
|
||
// Set up a load-balanced and rate-limited HTTP transport | ||
const httpTransport = loadBalance([ | ||
rateLimit(http('https://cloudflare-eth.com'), { requestsPerSecond: 75 }), | ||
rateLimit(http('https://eth-mainnet.public.blastapi.io'), { requestsPerSecond: 75 }), | ||
]); | ||
|
||
let pendingTxs = []; | ||
|
||
// Create our optimistic transport | ||
const optimisticTransport = custom({ | ||
request: async (request) => { | ||
const { method, params } = request; | ||
|
||
if (method === 'eth_sendRawTransaction') { | ||
pendingTxs.push(params[0]); | ||
return '0xFakeTxHashForPending'; | ||
} | ||
|
||
if (method === 'eth_getTransactionReceipt') { | ||
const pendingIndex = pendingTxs.indexOf(params[0]); | ||
if (pendingIndex > -1) { | ||
const receipt = await httpTransport.request(request); | ||
if (receipt) pendingTxs.splice(pendingIndex, 1); | ||
return receipt; | ||
} | ||
} | ||
|
||
if (method === 'eth_call' && params[1] === 'pending') { | ||
const tevmClient = createMemoryClient({ | ||
fork: { transport: httpTransport }, | ||
}); | ||
return tevmClient.request(request); | ||
} | ||
|
||
return httpTransport.request(request); | ||
} | ||
}); | ||
|
||
// Use our optimistic transport with a Viem client | ||
const viemClient = createPublicClient({ | ||
chain: mainnet, | ||
transport: optimisticTransport, | ||
}); | ||
``` | ||
|
||
This isn't just code – it's a masterpiece of Ethereum interaction. We're load balancing, rate limiting, handling pending transactions, and even simulating blockchain state – all through the power of EIP-1193. It's like conducting an orchestra where every instrument is a different blockchain operation. | ||
|
||
#### The Road Ahead: EIP-1193 and the Future of Ethereum Tooling | ||
|
||
As we stand on the cusp of a new era in blockchain technology, EIP-1193 is poised to play a pivotal role. Imagine a world where light client transports seamlessly integrate with Tevm, enabling trustless execution at unprecedented speeds. Picture Tevm providing lightning-fast local execution transports to Viem, revolutionizing the way we interact with the blockchain. | ||
|
||
This isn't just a dream – it's the future that EIP-1193 is helping to build. By embracing this standard, we're not just writing better code; we're shaping the future of decentralized applications. | ||
|
||
#### Conclusion: Embrace the EIP-1193 Revolution | ||
|
||
EIP-1193 isn't just another technical standard – it's a paradigm shift in Ethereum development. It's the key to unlocking a world of composable, flexible, and future-proof blockchain interactions. Whether you're building the next DeFi revolution or just dipping your toes into Web3, EIP-1193 is your ticket to the cutting edge of Ethereum development. | ||
|
||
So, the next time you're reaching for that RPC URL, pause for a moment. Ask yourself: "Am I ready to embrace the future?" Because with EIP-1193, the future of Ethereum development is not just bright – it's dazzling. | ||
|
||
Remember, in the world of blockchain, standards aren't just guidelines – they're superpowers. And EIP-1193? It might just be the most powerful superpower in JavaScript-Ethereum. |
Oops, something went wrong.