Skip to content

Sam/evm rpc scan address #5

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- added: Added support for `scanAddress` API for EvmRpc plugin by using etherscan services.

## 0.1.1 (2025-04-29)

- fixed: Fix subscribe method spec for change protocol.
Expand Down
4 changes: 3 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
forceExit: true
forceExit: true,
setupFiles: ['./jest.setup.ts'],
testTimeout: 10000
}
11 changes: 11 additions & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { jest } from '@jest/globals'

// Mock the serviceKeys object to be empty:
jest.mock('./src/serverConfig', () => ({
serverConfig: {
serviceKeys: {
'api.etherscan.io': ['JYMB141VYKJ2KPVMYJUZC8PXGWKUFVFX8N'],
'eth.blockscout.com': []
}
}
}))
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"fix": "eslint . --fix",
"lint": "eslint .",
"precommit": "lint-staged && npm-run-all types test prepare",
"prepare": "husky install && npm-run-all clean configure build",
"prepare": "husky install && patch-package && npm-run-all clean configure build",
"start": "node -r sucrase/register src/index.ts",
"test": "jest",
"types": "tsc",
Expand Down Expand Up @@ -61,7 +61,10 @@
"husky": "^8.0.3",
"jest": "^29.7.0",
"lint-staged": "^10.5.3",
"msw": "^2.8.2",
"msw-snapshot": "^5.2.0",
"npm-run-all": "^4.1.5",
"patch-package": "^8.0.0",
"prettier": "^2.2.0",
"rimraf": "^3.0.0",
"sucrase": "^3.16.0",
Expand Down
39 changes: 39 additions & 0 deletions patches/msw-snapshot+5.2.0.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
diff --git a/node_modules/msw-snapshot/dist/cjs/index.js b/node_modules/msw-snapshot/dist/cjs/index.js
index b8ffec4..e7ce6c0 100644
--- a/node_modules/msw-snapshot/dist/cjs/index.js
+++ b/node_modules/msw-snapshot/dist/cjs/index.js
@@ -108,9 +108,15 @@ var snapshot = function (config) {
if (!config.ignoreSnapshots && (0, node_fs_1.existsSync)(snapshotPath)) {
try {
snapshot_1 = JSON.parse((0, node_fs_1.readFileSync)(snapshotPath).toString('utf8'));
+ // Filter out compression-related headers since we're manually handling the body
+ const filteredHeaders = snapshot_1.response.headers.filter(
+ ([key, _]) =>
+ !key.toLowerCase().includes('content-encoding') &&
+ !key.toLowerCase().includes('transfer-encoding')
+ );
(_k = config.onFetchFromSnapshot) === null || _k === void 0 ? void 0 : _k.call(config, clonedInfo(), snapshot_1);
- return [2 /*return*/, new Response(new TextEncoder().encode(snapshot_1.response.body), {
- headers: new Headers(snapshot_1.response.headers),
+ return [2 /*return*/, new Response(snapshot_1.response.body, {
+ headers: new Headers(filteredHeaders),
status: snapshot_1.response.status,
statusText: snapshot_1.response.statusText,
})];
@@ -155,8 +161,14 @@ var snapshot = function (config) {
(0, node_fs_1.writeFileSync)(snapshotPath, JSON.stringify(snapshot, undefined, 2));
(_m = config.onSnapshotUpdated) === null || _m === void 0 ? void 0 : _m.call(config, clonedInfo(), snapshot);
}
- return [2 /*return*/, new Response(new TextEncoder().encode(snapshot.response.body), {
- headers: new Headers(snapshot.response.headers),
+ // Filter out compression-related headers since we're manually handling the body
+ const filteredHeaders = snapshot.response.headers.filter(
+ ([key, _]) =>
+ !key.toLowerCase().includes('content-encoding') &&
+ !key.toLowerCase().includes('transfer-encoding')
+ )
+ return [2 /*return*/, new Response(snapshot.response.body, {
+ headers: new Headers(filteredHeaders),
status: snapshot.response.status,
statusText: snapshot.response.statusText,
})];
167 changes: 149 additions & 18 deletions src/plugins/allPlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,51 +38,126 @@ export const allPlugins = [
// Ethereum family:
makeEvmRpc({
pluginId: 'abstract',
url: 'https://api.mainnet.abs.xyz'
url: 'https://api.mainnet.abs.xyz',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api.abscan.org'] },
{
type: 'etherscan-v2',
chainId: 2741,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'amoy',
url: 'https://polygon-amoy-bor-rpc.publicnode.com'
}),
makeEvmRpc({
pluginId: 'arbitrum',
url: 'https://arbitrum-one-rpc.publicnode.com'
url: 'https://arbitrum-one-rpc.publicnode.com',
scanAdapters: [
{
type: 'etherscan-v1',
urls: ['https://api.etherscan.io', 'https://api.arbiscan.io']
},
{
type: 'etherscan-v2',
chainId: 42161,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'avalanche',
url: 'https://avalanche-c-chain-rpc.publicnode.com'
url: 'https://avalanche-c-chain-rpc.publicnode.com',
scanAdapters: [
{
type: 'etherscan-v1',
urls: [
'https://api.avascan.info/v2/network/mainnet/evm/43114/etherscan',
'https://api.snowscan.xyz'
]
},
{
type: 'etherscan-v2',
chainId: 43114,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'base',
url: 'https://base-rpc.publicnode.com'
url: 'https://base-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api.basescan.org'] },
{
type: 'etherscan-v2',
chainId: 8453,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'binancesmartchain',
url: 'https://bsc-rpc.publicnode.com'
url: 'https://bsc-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api.bscscan.com'] },
{
type: 'etherscan-v2',
chainId: 56,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'bobevm',
url: 'https://bob.drpc.org'
url: 'https://bob.drpc.org',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://explorer.gobob.xyz'] }
]
}),
makeEvmRpc({
pluginId: 'celo',
url: 'https://celo-rpc.publicnode.com'
url: 'https://celo-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://explorer.celo.org/mainnet'] },
{
type: 'etherscan-v2',
chainId: 42220,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'ethereum',
url: 'https://ethereum-rpc.publicnode.com'
url: 'https://ethereum-rpc.publicnode.com',
scanAdapters: [
{
type: 'etherscan-v1',
urls: ['https://api.etherscan.io', 'https://eth.blockscout.com/']
},
{
type: 'etherscan-v2',
chainId: 1,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'ethereumclassic',
url: 'https://geth-at.etc-network.info'
url: 'https://geth-at.etc-network.info',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://etc.blockscout.com'] }
]
}),
makeEvmRpc({
pluginId: 'ethereumpow',
url: 'https://mainnet.ethereumpow.org'
}),
makeEvmRpc({
pluginId: 'fantom',
url: 'https://rpc.fantom.network'
url: 'https://rpc.fantom.network',
scanAdapters: [{ type: 'etherscan-v1', urls: ['https://ftmscout.com/'] }]
}),
makeEvmRpc({
pluginId: 'filecoinfevm',
Expand All @@ -94,35 +169,91 @@ export const allPlugins = [
}),
makeEvmRpc({
pluginId: 'holesky',
url: 'https://ethereum-holesky-rpc.publicnode.com'
url: 'https://ethereum-holesky-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api-holesky.etherscan.io'] },
{
type: 'etherscan-v2',
chainId: 11155111,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'optimism',
url: 'https://optimism-rpc.publicnode.com'
url: 'https://optimism-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api-optimistic.etherscan.io'] },
{
type: 'etherscan-v2',
chainId: 10,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'polygon',
url: 'https://polygon-bor-rpc.publicnode.com'
url: 'https://polygon-bor-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api.polygonscan.com'] },
{
type: 'etherscan-v2',
chainId: 137,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'pulsechain',
url: 'https://pulsechain-rpc.publicnode.com'
url: 'https://pulsechain-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api.scan.pulsechain.com'] }
]
}),
makeEvmRpc({
pluginId: 'rsk',
url: 'https://public-node.rsk.co'
url: 'https://public-node.rsk.co',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://rootstock.blockscout.com/'] }
]
}),
makeEvmRpc({
pluginId: 'sepolia',
url: 'https://ethereum-sepolia-rpc.publicnode.com'
url: 'https://ethereum-sepolia-rpc.publicnode.com',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api-sepolia.etherscan.io'] }
]
}),
makeEvmRpc({
pluginId: 'sonic',
url: 'https://sonic.drpc.org'
url: 'https://sonic.drpc.org',
scanAdapters: [
{ type: 'etherscan-v1', urls: ['https://api.sonicscan.org'] },
{
type: 'etherscan-v2',
chainId: 146,
urls: ['https://api.etherscan.io']
}
]
}),
makeEvmRpc({
pluginId: 'zksync',
url: 'https://1rpc.io/zksync2-era'
url: 'https://1rpc.io/zksync2-era',
scanAdapters: [
{
type: 'etherscan-v1',
urls: [
'https://block-explorer-api.mainnet.zksync.io',
'https://api-era.zksync.network',
'https://zksync.blockscout.com/api'
]
},
{
type: 'etherscan-v2',
chainId: 324,
urls: ['https://api.etherscan.io']
}
]
}),

// Testing:
Expand Down
Loading
Loading