dethcrypto / eth-sdk Goto Github PK
View Code? Open in Web Editor NEWType-safe, lightweight SDKs for Ethereum smart contracts
License: MIT License
Type-safe, lightweight SDKs for Ethereum smart contracts
License: MIT License
This should be an option in config.js
Hi! I want to dockerize an app that uses eth-sdk
but due to this magical process of placing generated types into node_modules
I'm failing to do so.
What I'm doing is building a multistage image to prevent devDependencies
getting into resulting image. Here is my Dockerfile:
FROM node:16.15.0-alpine3.15 AS base
FROM node:16.15.0-alpine3.15 AS build
WORKDIR /build
COPY ["package.json", "./"]
COPY ["yarn.lock", "./"]
RUN yarn install
COPY ["tsconfig.json", "./"]
COPY ./eth-sdk ./eth-sdk
COPY ./src ./src
RUN yarn eth-sdk
RUN yarn run build
FROM base AS final
WORKDIR /app
COPY ["package.json", "./"]
COPY ["yarn.lock", "./"]
COPY --from=build /build/node_modules/@dethcrypto ./node_modules/@dethcrypto
RUN yarn install --production
COPY --from=build /build/bin ./bin
ENTRYPOINT ["node", "bin"]
The problem here is it's failing with cryptic errors:
Error: Cannot find module '.dethcrypto/eth-sdk-client'
Require stack:
- /app/node_modules/@dethcrypto/eth-sdk-client/index.js
- /app/bin/utils.js
- /app/bin/index.js
I think some explanation about using eth-sdk
in non-dev environment would be nice. I think I'm back to fat image with all development dependencies but I hope there is some solution for this
P.S. My package.json looks like this:
{
"devDependencies": {
"@dethcrypto/eth-sdk": "^0.3.1",
"@types/node": "17.0.7",
"@types/node-fetch": "2.6.1",
"@typescript-eslint/eslint-plugin": "5.18.0",
"@typescript-eslint/parser": "5.18.0",
"eslint": "8.12.0",
"eslint-plugin-typescript": "0.14.0",
"ts-node": "^10.7.0",
"typescript": "4.5.4"
},
"dependencies": {
"@dethcrypto/eth-sdk-client": "^0.1.6",
"ethers": "5.6.4",
}
}
There is a proxy contract (https://etherscan.io/address/0x34460c0eb5074c29a9f6fe13b8e7e23a0d08af01) with implementation (https://etherscan.io/address/0x934ef5836e78d93125317034f5cf855a97b13f43). I'd like to use proxy contract methods in a type-safe way (in this case getTarget
and getMaster
). I would like to also use implementation methods in the same way. At this point, eth-sdk fetches only implementation abi, so I had to add missing proxy methods on my own.
This could be achieved if noFollowProxies
could be defined for every contract separately instead of once for the whole config - I could then define two contracts (one with proxy abi and the other one with implementation abi). The other solution would be to allow abi merging - not sure how this would work precisely though.
What is your take on this?
The CLI always generates files in node_modules/.dethcrypto/eth-sdk-client
relative to the package.json
But in a Monorepo the package where I use eth-sdk might be in packages/my-package
. So when I run the CLI it generates packages/my-package/node_modules/.dethcrypto/eth-sdk-client
but it's looking for the package in node_modules/.dethcrypto/eth-sdk-client
. This means eth-sdk doesn't work in Monorepos.
Also, the new version of Yarn doesn't encourage the use of node_modules
anymore (https://yarnpkg.com/features/pnp) Maybe eth-sdk should have the option to be run in a mode where it generates source files that should be included in source control instead of creating another package.
The inferred type of 'default' cannot be named without a reference to '.pnpm/@[email protected]/node_modules/@dethcrypto/eth-sdk/dist/config'. This is likely not portable. A type annotation is necessary.ts(2742)
Might it be possible to support the evm-compatible zkSync2 testnet?
Hey, (sorry it's me again).
I noticed one more problem with vite which cost me a lot of time understanding yesterday :D I think this should be added to the dev
task or at least to the vite-example-readme :)
When you change the eth-sdk config and re-generate types (via yarn eth-sdk
) the vite-dev-bundle doesn't notice the change – even when you restart the dev
-task (via yarn dev
or npx vite
). That's because on its first dev-build it caches a version of the eth-sdk-client
within node_modules/.vite
. You can change that behavior forcing vite to clear the cache folder every time when you restart the dev-server/-build with npx vite --force
.
My versions (if they make any difference):
➜ vite-react node --version
v16.13.0
➜ vite-react npm --version
8.1.4
➜ vite-react yarn --version
1.22.17
➜ vite-react npx vite --version
vite/2.6.14 darwin-arm64 node-v16.13.0
➜ vite-react npx eth-sdk --version
0.2.2
yarn dev
produces the following output after installing dependencies and running yarn eth-sdk
successfully.
[vite] src/App.tsx:1:30: note: The plugin "vite:dep-scan" was triggered by this import
[vite] 1 │ import { getMainnetSdk } from '@dethcrypto/eth-sdk-client'
[vite] ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[vite]
[vite] error when starting dev server:
[vite] Error: Build failed with 1 error:
[vite] node_modules/vite/dist/node/chunks/dep-e0fe87f8.js:30273:10: error: [plugin: vite:dep-scan] Failed to resolve entry for package "@dethcrypto/eth-sdk-client". The package may have incorrect main/module/exports specified in its package.json: Failed to resolve entry for package "@dethcrypto/eth-sdk-client". The package may have incorrect main/module/exports specified in its package.json.
[vite] at failureErrorWithLog (/Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:1493:15)
[vite] at /Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:1151:28
[vite] at runOnEndCallbacks (/Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:941:63)
[vite] at buildResponseToResult (/Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:1149:7)
[vite] at /Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:1258:14
[vite] at /Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:629:9
[vite] at handleIncomingPacket (/Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:726:9)
[vite] at Socket.readFromStdout (/Users/wottpal/Developer/eth-sdk-example-react/node_modules/esbuild/lib/main.js:596:7)
[vite] at Socket.emit (node:events:390:28)
[vite] at addChunk (node:internal/streams/readable:315:12)
The important part might be: The package may have incorrect main/module/exports specified in its package.json
.
When I delete line 22 ("module": "./index.mjs"
) from node_modules/@dethcrypto/eth-sdk-client/package.json
everything runs again without errors. I tried doing that because there is no index.mjs
existing in the eth-sdk-client
-folder.
Running on Node v16.13.0.
Thanks in advance 👋
When replacing an address on the config, if the name is unchanged, the ABIs don't get overriden, and new methods are not loaded.
Contracts are attached to new addresses, but ABIs should be refreshed.
Fetching ABIs from etherscan or sourcify is great but only works if the contracts are already deployed and verified. But how do you work with contracts that are not yet deployed?
Would like to build different frontend environments: local (npx hardhat node) / staging (e.g goerli) / production (e.g mainnet)
I'm working on some local smart contracts with hardhat and don't want to deploy them just yet, I just want to play around locally and have my frontend pick up all the right types. Seems like I can't do that at the moment (or haven't found a way by looking through the docs).
Something like that would improve DX by 100x
const config: EthSdkConfig = {
contracts: {
mainnet: {
dai: "0x4a436073552044D5f2f49B176853ad3Ad473d9d6",
},
goerli: {
dai: "0x3a436073552044D5f2f49B176853ad3Ad473d9d6",
},
local: {
dai: {address: "0x5a436073552044D5f2f49B176853ad3Ad473d9d6", abi: "../dai.json"},
},
},
networkIds: {
local: 1337
},
};
Basically allowing you to opt in to use a local abi for any contract. There is also the possibility of defining that all local contracts should fetch the abi from a local source and do some filename lookup but having a granular approach that lets you choose where the abi is coming from for each contract is better IMO because you might be working with some contract that is not verified for some reason but you still have the abi. So you could mix verified contracts on mainnet with unverified ones where you still have the abi for example. (Note: All contracts should be verified but this use case is still valid IMO)
For context, to use this in a frontend I'd probably create a custom hook that gets the current network name from an env file and returns the correct SDK.
Like this (pseudo-code):
function useSDK() {
const { library } = useWeb3React();
// if a signer is injected by web3-react via Metamask use that, if not, use a default provider
const signerOrProvider = library ? library : getDefaultProvider();
if (process.env.NEXT_PUBLIC_NETWORK === "mainnet") {
return getMainnetSDK(signerOrProvider);
}
if (process.env.NEXT_PUBLIC_NETWORK === "goerli") {
return getGoerliSDK(signerOrProvider);
}
if (process.env.NEXT_PUBLIC_NETWORK === "local") {
return getLocalSDK(signerOrProvider);
}
}
Let me know if I can help in any way to support this :)
Now we have TC 6 and new ethers target. It generates higher quality typings and doesn't require manual copying b/c it's all .ts
files (not .d.ts
).
Consider following config:
export default defineConfig({
contracts: {
mainnet: {
bancorCollection: '0xEC9596e0eB67228d61a12CfdB4b3608281F261b3',
},
},
})
Now If we call it it all compiles:
However, if we try to specify struct name it won't work:
The problem is type is not reexported so it cannot be accessed outside. It may be useful in cases when I want to write a function like
function processPoolData(data: PoolStructOutput) { ... }
P.S. for some reason generation doesn't work for all types. For example following config:
export default defineConfig({
contracts: {
mainnet: {
uniswapV3: '0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8'
},
},
})
Leads to
slot0(overrides?: CallOverrides): Promise<[
BigNumber,
number,
number,
number,
number,
number,
boolean
] & {
sqrtPriceX96: BigNumber;
tick: number;
observationIndex: number;
observationCardinality: number;
observationCardinalityNext: number;
feeProtocol: number;
unlocked: boolean;
}>;
snapshotCumulativesInside(tickLower: BigNumberish, tickUpper: BigNumberish, overrides?: CallOverrides): Promise<[
BigNumber,
BigNumber,
number
] & {
tickCumulativeInside: BigNumber;
secondsPerLiquidityInsideX128: BigNumber;
secondsInside: number;
}>;
Note that it didn't generate proper named struct for ABI.
Been playing around with eth-sdk and so far it has been pretty amazing. However, one thing on my wish-list is being able to narrow down types in the config.
I'm thinking of something like this:
moonriver: {
fraxBond: "0xE2F71c68db7ECC0c9A907AD2E40E2394c5CAc367",
frax: {
address: "0x1A93B23281CC1CDE4C4741353F3064709A16197d",
as: ["ERC20"],
},
},
my reasoning is that when you already know a contract is of type ERC20 for example, you could supply that information to eth-sdk which will then not only have it extend from BaseContract, but also extend from ERC20. This would then make it possible to iterate over a list of ERC20s because they have the same narrowed-down base.
I've created a sample repo: https://github.com/Pzixel/eth-sdk-test
What's happens there: I have a simple sdk:
import { defineConfig } from '@dethcrypto/eth-sdk'
export default defineConfig({
contracts: {
mainnet: {
curveRegistry3: '0xB9fC157394Af804a3578134A6585C0dc9cc990d4',
},
},
})
Then I'm running yarn eth-sdk
and check output json file https://github.com/Pzixel/eth-sdk-test/blob/master/eth-sdk/abis/mainnet/curveRegistry3.json
The problem is that it's unrelated to contract 0xB9fC157394Af804a3578134A6585C0dc9cc990d4
. For example, fetched JSON suggests that there is a function integrate_checkpoint which doesn't exist on real contract:
Meanwhile contract has a function metapool_implementations
which is missing in generated ABI:
Contract: https://etherscan.io/address/0xB9fC157394Af804a3578134A6585C0dc9cc990d4#code
Should check if all addresses specified in config files exist on given chains. This is useful b/c no check like this happens after ABI was cached which can mask some errors.
Consider following code:
import { getMainnetSdk } from '@dethcrypto/eth-sdk-client' // yay, our SDK! It's tailored especially for our needs
const sdk = getMainnetSdk(ethers.getDefaultProvider() as any);
console.log(`DAI supply is`, (await sdk.dai.totalSupply()).toString());
It works just fine but we need to disable typecheck here to make it happen, otherwise it complains that Provider != Signer.
Consider using signerOrProvider: Signer | Provider
as an argument here similarly to how typechain
handles this.
We can't fetch ABI from Polygon without an API key, and the config does not allow to specify multiple etherscan keys.
Error: Can't find mainnet abi for 0x7ceb23fd6bc0add59e62ac25578270cff1b9f619. Msg: {
"status": "0",
"message": "NOTOK",
}
Take a look at https://github.com/dethcrypto/eth-sdk/pull/83/files. (Run pnpm eth-sdk
in packages/throwaway
to see the error.)
esbuild-register, esbuild-runner etc
Am getting a ✘ [ERROR] Could not resolve ".dethcrypto/eth-sdk-client"
when trying to use eth-sdk
in a react app
This will allow eth-sdk config to pass flags into typechain
When calling getMainnetSdk it should be allowed to pass any ethers provider or signer. In our codebase we're using a custom useDapp-like library in conjunction with web3-react.
When no signer (e.g as injected by MetaMask) is available, it defaults to a StaticJsonRPCProvider.
This is very useful in combination with useSWR (or react-query) and suspense as it provides a great DX and UX:
It will actually show the data that only needs a provider and displays a fallback state if it can't fetch the data that needs a signer but will automatically show it when the user connects a wallet that injects a signer.
The Curve Gauge Factory at 0xB9fC157394Af804a3578134A6585C0dc9cc990d4
imports the typings of one of the child Gauges 0x99fb76F75501039089AAC8f20f487bf84E51d76F
Is missing deploy_gauge
function, and adds a add_reward
that's not in the factory contract
It would be nice to get a single contract from a given SDK and init it on any address and with any signer. Sample API:
getMainnetContract('maker.dai', 'address', signer) // returns properly typed, initialized contract
We don't really need Disregard this. Retries.got
— we don't use most of its features — I we'd be fine with node-fetch
instead.
When fetching a contract type like a standard ERC20, it'd be nice to be able to fetch only 1 contract, and then to reuse it with several addresses:
import { getMainnetSdk } from '@dethcrypto/eth-sdk-client';
let sdk = getMainnetSdk(ethers.provider);
let erc20 = sdk.erc20
let dai = erc20.at('0x6b175474e89094c44da98b954eedeac495271d0f')
let mim = erc20.at('0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3')
In this way, even though we're not fetching the actual ABI, we're allowed to treat those contracts with a common interface and reduce loading time when compiling eth-sdk.
Very useful when working with several UniV3Pools that come from the same factory!
Very useful when working with a contract that's not deployed on mainnet but just on our test environment!
Init should create eth-sdk dir with contracts.json
For now we can simply copy config from hardhat-etherscan
plugin. Later we should probably try to convenience hardhat-etherscan
to extract it to a separate package.
I wasn't able to create a MRE to bring any code that reproduces an issue but I hope it may be clear from the error itself:
❯ yarn eth-sdk
yarn run v1.22.17
Loaded sdk definition from /Users/pzixel/Documents/Repos/test/eth-sdk
✔ Getting ABIs
⠙ Generating client/var/folders/_w/s45kr_gx6q1f75q2p7ljft100000gn/T/eth-sdk-64037-gNxOCe0UMMR6/index.ts (16,117): Namespace '"/var/folders/_w/s45kr_gx6q1f75q2p7ljft100000gn/T/eth-sdk-64037-gNxOCe0UMMR6/types/index"' has no exported member 'mainnet'.
/var/folders/_w/s45kr_gx6q1f75q2p7ljft100000gn/T/eth-sdk-64037-gNxOCe0UMMR6/index.ts (16,117): Namespace '"/var/folders/_w/s45kr_gx6q1f75q2p7ljft100000gn/T/eth-sdk-64037-gNxOCe0UMMR6/types/index"' has no exported member 'mainnet'.
✖ Generating clientError: TypeScript compilation failed. at /Users/pzixel/Documents/Repos/test/node_modules/@dethcrypto/eth-sdk/src/client/transpileClient.ts:39:15 at Array.map (<anonymous>) at transpileClient (/Users/pzixel/Documents/Repos/test/node_modules/@dethcrypto/eth-sdk/src/client/transpileClient.ts:14:13) at async generateSdk (/Users/pzixel/Documents/Repos/test/node_modules/@dethcrypto/eth-sdk/src/client/index.ts:23:3)
I tried to downgrade packages version but it still returns this error.
As Originally reported by @johanneskares in #102 (comment), the generated package is not compatible with yarn workspaces:
Now I can include it as depdendency in my monorepo. Only problem is, I manually have to change the name of the generated package, because
yarn
doesn't like the name of the package.dethcrypto/eth-sdk-client
inpackage.json
. When I doyarn workspace my-package add .dethcrypto/eth-sdk-client
I get
Usage Error: The .dethcrypto/eth-sdk-client string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name?
When I manually edit it to
dethcrypto-eth-sdk-client-generated
, everything works fine.
Customizing the generated package name
in the config would solve this.
Also, to use it as a standalone package in a monorepo setup - which is great if you're going to use the sdk in both the backend and front-end - it needs a version
, which could either be included as a static field in the configuration, or initialized to a configurable value and then dynamically incremented in subsequent updates
The way it works today, I have to rewrite the sdk's package.json
every time I update it
I got stuck using eth-sdk
because I am currently working on something in Goerli network and I got the error: Error: Can't find network info for goerli
I believe it would be great to have networkToEndpoints
be a generic config. Maybe a file called eth-sdk/networks.json
could be created by the user and contain all the needed networks.
For example:
eth-sdk/networks.json
{
"helloworld": {
"apiURL": "https://api.etherscan.io/api",
"browserURL": "https://etherscan.io",
},
}
eth-sdk/contracts.json
{
"helloworld": {
"dai": "0x6B175474E89094C44Da98b954EedeAC495271d0F"
}
}
And as long as both network names match, I believe it should work. The downside is that it will affect the UX, making it a bit harder to start using this package, this may be possibly solved by providing an example json with the most popular networks...
Btw: great presentation at ETHGlobal!
The sdk reads JSON ABI from a relative filepath using fs
and __dirname
. It's not trivial to use it in a frontend project.
ESM support is also lacking.
We could inline the ABI or require it as a JavaScript module instead. (It's already inlined in factory generated by TypeChain generated.)
current eth-sdk-client/index.js
function getContract(address, abiPath, defaultSigner) {
const abi = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, '..\..\..\eth-sdk\abis', abiPath + '.json'), 'utf-8'));
return new ethers_1.Contract(address, abi, defaultSigner);``
}
exports.getContract = getContract;
function getMainnetSdk(defaultSigner) {
return {
"dai": getContract('0x6B175474E89094C44Da98b954EedeAC495271d0F', 'mainnet/dai', defaultSigner),
};
}
We could add a GHA that would compare deps on daily basis and create PRs when new, major typechain
or typechain/ethers-v5
version comes out.
Releated: #72
When adding the USDC address 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
it seems like etherscan doesn't accept it as a valid request. Changing the address to UniswapsV2router02 address and leaving the key as "usdc" yeilds a result and creates the ABI. I find that very odd.
I've reinstalled the packages and started from scratch with defaults, only adding DAI and USDC to the config. (Previously I had also tried my own Etherscan/RPC API's thinking that was the issue)
config.json
{
"contracts": {
"mainnet": {
"tokens": {
"COMP": "0xc00e94cb662c3520282e6f5717214004a7f26888",
"DAI": "0x6b175474e89094c44da98b954eedeac495271d0f",
"USDC": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
},
"compound": {
"comptroller": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
"comptrollerImpl": "0x374ABb8cE19A73f2c4EFAd642bda76c797f19233",
"treasury": "0x2775b1c75658be0f640272ccb8c72ac986009e38"
}
}
}
}
CLI error when running yarn eth-sdk
✖ Getting ABIs
Error: missing revert data in call exception (error={"reason":"processing response error","code":"SERVER_ERROR","body":"{\"jsonrpc\":\"2.0\",\"id\":44,\"error\":{\"code\":-32000,\"message\":\"execution reverted\"}}","error":{"code":-32000},"requestBody":"{\"method\":\"eth_call\",\"params\":[{\"to\":\"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48\",\"data\":\"0x5c60da1b\"},\"latest\"],\"id\":44,\"jsonrpc\":\"2.0\"}","requestMethod":"POST","url":"https://mainnet.infura.io/v3/0993a4f4500c4fff88649d28b331898c"}, data="0x", code=CALL_EXCEPTION, version=providers/5.5.0)
As per the title
We could just bump the dependencies
js
and ts
should be supported.
Currently, SDK generation for config like this will fail in the runtime:
import { defineConfig } from '@dethcrypto/eth-sdk'
export default defineConfig({
contracts: {
mainnet: {
daiBridge: {
Dai: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
},
},
optimism: {
daiBridge: {
Dai: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
},
},
},
})
error is:
Error: TypeScript compilation failed.
Duplicate identifier 'daiAbi'.
Duplicate identifier 'daiAbi'.
Problem is that there is symbols collision between different SDKs.
The problem exists even inside the same network like:
compound: {
token: "0x00"
},
maker: {
token: "0x0"
}
It seems that the best solution would be to alias all symbols (imports etc) with full path inside index.ts
file. So instead of:
import daiAbi from '../../../../eth-sdk/abis/mainnet/dai.json'
import daiAbi from '../../../../eth-sdk/abis/mainnet/tokens/dai.json'
it should be something like:
import mainnet_dai_abi from '../../../../eth-sdk/abis/mainnet/dai.json'
import mainnet_tokens_dai_abi from '../../../../eth-sdk/abis/mainnet/tokens/dai.json'
when you use ethsdk : yarn eth-sdk -p ./src/config
even if you specify the output folder, eth-sdk generates the abi folder in the same folder the file is located. I the output folder
is only used for types
.
ideally, I would like all generated files in a generated folder
that is specified in config
including
Thanks for the great lib! 🙇🏾
It would be great to get a package with typechain v7
Currently, client generation is fully sync which results in CLI animations being stuck. Making it async shouldn't be too difficult and should improve the visuals.
It's so nice to store everything in one place. It could be useful to enable arbitrary metadata stored for each contract.
I'm wondering if there's any special support for same contract & ABI deployed on many networks? Currently, many types are created that have are effectively duplicates. Not a big issue but I would imagine nowadays it's a common use-case where same contract is deployed to many networks.
Currently, we use eth-sdk/contracts.json
I think the better option would be .eth-sdk/config.json
Uses Awaited
but it's not needed anymore. Needs tests to prevent in future.
eth-sdk
should detect that it's reading ABI of a proxy and should query implementation ABI. Finally, both should be merged. Example contract: 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B
.
Steps:
implementation
or _implementation
gettersStorage slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc (obtained as bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)).
More info: https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies and https://eips.ethereum.org/EIPS/eip-1967eth-sdk
should query implementation for ABI and then either merge both ABIs or just use implementation proxy. (I think it might be better just to use implementation).To implement this properly we need to have web3 node connection setup in eth-sdk. I think it's fine for now just to hardcode dummy infura key and allow user to input custom one in config (similarly to etherscan key).
Disclaimer: I'm very new in this field of development. Sorry, if I have taken something completely wrong in advance :D
Wouldn't it be nice if the types generated by typechain/eth-sdk would also include the comments/documentation provided within the solidity contract files? So that if I hover over a function in VSCode the documentation pops up? I guess that task is not so easy as the comments are not included within the ABIs downloaded from etherscan, right?
Since you, @krzkaczor , mentioned that you would like to retrieve the ABI directly from the metadata as well instead of from etherscan, I just want to quickly explain the steps. We are working on an npm package to maybe do part of this, but it's really not complicated (pseudocode):
code = eth.getCodeAt(addr).hexToBytes()
metadataSize = code[-2] * 0x100 + code[-1]
metadataCBOR = cbor.decode(code[-metadataSize - 2:-2])
ipfsLink = metadataCBOR['ipfs']
// the link is binary-encoded, you might have to base58-encode it, depending on the
// way you access ipfs
metadata = ipfs.retrieve(ipfsLink)
abi = metadata['output']['abi']
This is the recommended decentralized way to do it. You can either use ipfs "directly" or through an http gateway. My experience with http gateways (at least the cloudfront one) is that they will also pin data that is retrieved through them, which is nice.
The access via ipfs only works if contracts are fully verified on sourcify (including the correct metadata hash). This guarantees that neither the source nor the ABI have been modified after deployment.
There is a centralized http interface to sourcify that also allows you to access partially verified contract's abis: https://github.com/ethereum/sourcify/blob/master/docs/api/server/getByChainAndAddress.md
If you have further questions, you can also come to our gitter / matrix channel: https://gitter.im/ethereum/source-verify
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.