Title: EIP_4804__Web3_URL_to_EVM_Call_Message_Translation
Category: EIPs

Author: qizhou
Date: 2022-02-14T22:11:31.046Z

A translation of an HTTP-style Web3 URL to an EVM call message
Motivation
Currently, reading data from Web3 generally relies on a translation done by a Web2 proxy to Web3 blockchain. The translation is mostly done by the proxies such as dApp websites/node service provider/etherscan, which are out of the control of users. The standard here aims to provide a simple way for Web2 users to directly access the content of Web3.  Moreover, this standard enables interoperability with other standards already compatible with URIs, like SVG.


github.com/ethereum/EIPs








Create EIP-4804


master ← qizhou:qizhou-4804



          opened 09:18PM - 13 Apr 22 UTC




            qizhou
          



+160
-0






When opening a pull request to submit a new EIP, please use the suggested templa…te: https://github.com/ethereum/EIPs/blob/master/eip-template.md

We have a GitHub bot that automatically merges some PRs. It will merge yours immediately if certain criteria are met:

 - The PR edits only existing draft PRs.
 - The build passes.
 - Your GitHub username or email address is listed in the 'author' header of all affected PRs, inside <triangular brackets>.
 - If matching on email address, the email address is the one publicly listed on your GitHub profile.

Author: wart
Date: 2022-02-15T02:24:50.416Z

nice proposal. and it would be greatly beneficial when eth tps improves a lot

Author: liushooter
Date: 2022-02-18T05:04:20.391Z

awsl

974×180 5.92 KB
https://web3q.io/quickcreation.w3q/LogWeb3

Author: SamWilsn
Date: 2022-04-14T21:53:08.147Z

Hey! I’m pretty interested in this, would you be interested in a co-author?

Author: qizhou
Date: 2022-04-14T22:14:07.193Z

Of course!  The standard is at an early stage and we welcome any contribution from the community.

Author: qizhou
Date: 2022-04-14T22:29:30.660Z

BTW: Nice article about on-chain PNG rendering Rendering a PNG on Ethereum: face.png - this something we are looking for and optimize for

Author: SamWilsn
Date: 2022-04-14T23:51:11.312Z

So a couple of non-formatting related comments:

In the motivation section, it might be nice to add something like this comment. Perhaps: interoperability with other standards already compatible with URIs, like SVG.
Personally, I think the web3 term is a bit too vague/broad for us to co-opt. Maybe evm://, since we use Solidity’s ABI, or just maybe just eth?
The return types are strictly client-side, so perhaps using the anchor notation for that ...#uint256,(string,bytes32)?
In the example web3://wusdt.eth:4->(uint256)/balanceOf/charles.eth, balanceOf doesn’t match the given grammar earlier in the proposal (as far as I could tell.)
How would you feel if the types were mandatory? Asking implementers to figure out how to retrieve ABI definitions might be a bit heavy.

Author: qizhou
Date: 2022-04-15T01:15:02.716Z

Many thanks for your comments.  A couple of my responses:



 SamWilsn:

In the motivation section, it might be nice to add something like this comment. Perhaps: interoperability with other standards already compatible with URIs, like SVG.


Nice!  I have added the sentence Moreover, this standard enables interoperability with other standards already compatible with URIs, like SVG. in the motivation part.



 SamWilsn:

Personally, I think the web3 term is a bit too vague/broad for us to co-opt. Maybe evm://, since we use Solidity’s ABI, or just maybe just eth?


Thanks for the comment.  I feel that eth:// may be a bit narrow because the protocol itself can support any EVM blockchains such as Polygon/BSC or even testnets.  For evm://, I feel it is a bit technical because a lot of Web2 people may not have an idea what EVM is.
I have been struggling to choose the best scheme name.  I finally choose web3:// because the major goal of the protocol is to be the counterpart of http:// in Web2.  Further, given the fact that Ethereum/EVM has been the de-facto Web3 technical stack, using web3:// could strengthen the position of Ethereum/EVM in Web3 without creating confusion.  Feel free to let me know if you have other thoughts.



 SamWilsn:

The return types are strictly client-side, so perhaps using the anchor notation for that ...#uint256,(string,bytes32)?


Thanks for the comment.  The hashtag will be pre-processed by the browser so that the type info may not be passed to the gateway or web extension.   If we want to process them on the client side, we need to return an HTML that processes the type info, which may be complicated.  Instead, if we could process them on server side, then the user can browse the formatted result either in browser or curl/wget or programs easily.



 SamWilsn:

In the example web3://wusdt.eth:4->(uint256)/balanceOf/charles.eth, balanceOf doesn’t match the given grammar earlier in the proposal (as far as I could tell.)


Thanks for the comment.  balanceOf should match method in the grammar:
Web3URL = "web3://" [userinfo "@"] contractName [":" chainid] ["->(" returnTypes ")"] path [? query]
contractName = address | name "." nsProvider
path = ["/" method ["/" argument_0 ["/" argument_1 ... ]]]
argument = [type "!"] value

As the result, the protocol will call “balanceOf(address)” with charles.eth’s address from NS.   Please let me know if I miss anything.



 SamWilsn:

How would you feel if the types were mandatory? Asking implementers to figure out how to retrieve ABI definitions might be a bit heavy.


I agree that retrieving ABI definition is not easy in this case.  Actually, mandating the types in the link still needs ABI definitions for implementers.  So the cost should be the same no matter whether the types are mandatory or not.
The reason for providing auto-type detection is to make the URL as simple and natural as possible.  Further, in our current gateway implementation, we will return web3-calldata, web3-method-siganture, and web3-return-type in HTTP response headers for better debuggability.  The following is an example of
https://web3q.io/wusdt.eth:4->(uint256)/balanceOf/charles.eth
image619×118 17.8 KB

Author: SamWilsn
Date: 2022-04-15T02:32:45.387Z

qizhou:

For evm://, I feel it is a bit technical because a lot of Web2 people may not have an idea what EVM is.


I would argue that http is pretty technical  I don’t feel too strongly about the actual prefix though.



 qizhou:

The hashtag will be pre-processed by the browser so that the type info may not be passed to the gateway or web extension. If we want to process them on the client side, we need to return an HTML that processes the type info, which may be complicated. Instead, if we could process them on server side, then the user can browse the formatted result either in browser or curl/wget or programs easily.


Is the intent to resolve the URIs through a browser? Although it’s possible to return HTML directly from a contract, I don’t expect that to be too normal (or gas efficient.) If the anchor is stripped before passing to a web extension, then yeah, it wouldn’t make sense to put it there.
The only non-binary data I’m familiar with on-chain today would be NFT metadata/image data.



 qizhou:

Thanks for the comment. balanceOf should match method in the grammar


Ha, can’t believe I missed that… Obviously that makes sense.



 qizhou:

Actually, mandating the types in the link still needs ABI definitions for implementers.


I think if you had a URI like web3://foo.eth/balanceOf/address!bar.eth that would be sufficient to call the function. Actually, you could even do web3://foo.eth/balanceOf(address):uint256/bar.eth. What am I missing?
Are the types in the current EIP are there to disambiguate between overrides?

On an unrelated note:

In the second case, nsProvider will be the short name of name service providers such as “ens”, “w3q”, etc.

This seems to imply that an ENS lookup would have to be web3://foo.eth.ens/... or web3://example.com.ens/...? The examples later in the EIP don’t match that pattern.

Author: qizhou
Date: 2022-04-15T06:05:31.371Z

SamWilsn:

Is the intent to resolve the URIs through a browser? Although it’s possible to return HTML directly from a contract, I don’t expect that to be too normal (or gas efficient.) If the anchor is stripped before passing to a web extension, then yeah, it wouldn’t make sense to put it there.


Thanks for the comment.  The intention is to resolve the URIs via a gateway (like ipfs.io) or a web browser extension.  The browser just passes the full Web3 URI to the gateway/extension, and the gateway/extension would have full knowledge to parse the URIs to EVM call message and format the returned data back to the browser via HTTP protocol.  This requires minimal changes on browsers so that we can use any browser (Chrome/Firefox/IE/etc) to browse Web3 URIs easily.
The standard would perfectly fit into NFT metadata/image data like SVG (I am also a big fan of it  ).  Meanwhile, we are exploring other non-binary data such as dWeb or even dynamic Web page generation (decentralized social network?).  There are a lot of possibilities here enabled by Ethereum and ERC-4804!



 SamWilsn:

I think if you had a URI like web3://foo.eth/balanceOf/address!bar.eth that would be sufficient to call the function. Actually, you could even do web3://foo.eth/balanceOf(address):uint256/bar.eth. What am I missing?
Are the types in the current EIP are there to disambiguate between overrides?


Many thanks for the comment.  A couple of great design questions for the standard.  Let me list them one-by-one:
Q1: For address from name service, should we use name type or address type? E.g.,

web3://foo.eth/balanceOf/address!bar.eth ; or
web3://foo.eth/balanceOf/name!bar.eth?

Using address type for both conventional 0x-20-bytes-hex ETH address space and name from NS should work as ETH address will never have “.”, but should we separate these types for better clarification?
Q2: Do we need type auto-detection, i.e., do we need the simpler URI at the price of potential ambiguity?  E.g.,

web3://foo.eth/balanceOf/address!bar.eth
web3://foo.eth/balanceOf/bar.eth
where the first is with mandatory type and the second’s type is auto-detected.

Actually, auto-detection may coexist with manual resolve mode better.  Taking a dWeb as an example, the user may type (myhome.eth is in manual resolve mode)

web3://myhome.eth/aaa.svg,

which will pass /aaa.svg as the calldata so that the contract can display the file directly.  As a comparison, using the mandatory typed link in auto resolve mode will look like

web3://myhome.eth/showFile/string!aaa.svg
which is more verbose.

Q3: If types are supplied, where to put the input argument types and return types (which can be a tuple)? E.g.,

web3://foo.eth/balanceOf(address):(uint256)/bar.eth
web3://foo.eth/balanceOf(address)->(uint256)/bar.eth
web3://foo.eth/balanceOf->(uint256)/address!bar.eth
web3://foo.eth->(uint256)/balanceOf/address!bar.eth

I personally prefer “->” to prepend return types as it is clear to understand.  In addition, current standard puts “->(outputTypes)” after the contract name (Option 4) so that the path part of the link looks almost the same as that of the Web2 HTTP link.  Admittedly, Option 1 or 2 is closer to what current Solidity has, but seems to be incompatible with auto-detection for types.



 SamWilsn:

This seems to imply that an ENS lookup would have to be web3://foo.eth.ens/... or web3://example.com.ens/...? The examples later in the EIP don’t match that pattern.


Nice find!  I have changed the sentence to

In the second case, nsProviderSuffix will be the suffix from name service providers such as “eth”, “w3q”, etc.

Author: SamWilsn
Date: 2022-04-15T07:10:17.104Z

qizhou:

resolve the URIs via a gateway (like ipfs.io)


If you’re using a gateway (like foo.test), I’m guessing the full URL would look something like https://example.eth.foo.test/balanceOf/bar.eth#uint256? If the gateway is returning the raw data, it wouldn’t be able to access the anchor… So it makes sense to put it in the path component.
If we want everything to be symmetric, then it makes sense to put it in the path for extensions and direct requests too. You’ve convinced me 



 qizhou:

Using address type for both conventional 0x-20-bytes-hex ETH address space and name from NS should work as ETH address will never have “.”, but should we separate these types for better clarification?


I guess the reverse question is also important: will there ever be a NS provider without a .? I have a slight preference for just using address, but that mandates a dot in the name. Small trade-off, in my opinion.



 qizhou:

Q2: Do we need type auto-detection, i.e., do we need the simpler URI at the price of potential ambiguity?


I totally overlooked the section on auto-detection. I don’t think the contract being queried should be able to affect the interpretation of the URI. That would mean I’d need to know what mode the contract is in to correctly construct a URI, which would make autogeneration of URIs (say in on-chain SVGs) difficult.
I’d most prefer an explicitly typed URI, but it might be possible to make some unambiguous rules to infer types.



 qizhou:

Q3: If types are supplied, where to put the input argument types and return types (which can be a tuple)?


Yeah, looking at your examples, I like -> more too. Doing name(type arg0)->(type,type) will be pretty familiar to Rust devs 
I definitely don’t think it should come before the first /. If it does, it looks like part of the “host”.



 qizhou:

Admittedly, Option 1 or 2 is closer to what current Solidity has, but seems to be incompatible with auto-detection for types.


Just kinda throwing the idea out, but what if there were some implied defaults, if not specified? For example web3://foo.eth/->/aaa.svg could mean “call a function with the signature index(string) -> (string)”.

How would you handle resolving ENS names that use DNSSEC? For example supersaiyan.xyz is a valid ENS name.

Author: qizhou
Date: 2022-04-15T09:09:28.856Z

SamWilsn:

I guess the reverse question is also important: will there ever be a NS provider without a .? I have a slight preference for just using address, but that mandates a dot in the name. Small trade-off, in my opinion.


We also had an internal discussion on which one is better, but no strong preference.  I think we could choose address now by assuming that all NS providers must have “.”.



 SamWilsn:

I don’t think the contract being queried should be able to affect the interpretation of the URI. That would mean I’d need to know what mode the contract is in to correctly construct a URI, which would make autogeneration of URIs (say in on-chain SVGs) difficult.


Thanks for the comment.  I would argue a potential huge application with “manual” mode for on-chain Web content generation.  To be more specific, the current standard serves two major purposes:
Purpose 1: Call a contract for JSON-formated result
If the returned types are specified, the protocol will
1. call the contract;
2. get the call result in raw bytes;
3. parse the raw bytes into ABI-encoded types as specified by returned types;
4. format the ABI-encoded types to JSON and return the JSON response to the client.
This can be viewed as a complement to the existing JSON-RPC protocol.
Purpose 2: Call a contract for on-chain Web content
If the returned types are not specified, the protocol will assume that an on-chain web content (e.g., HTML/SVG/CSS/etc) will be returned to the client.  This is perhaps the most attractive application of the standard.
My original design for this purpose comes from common gateway interface (CGI) - the famous interface for Web servers.  In CGI,  the web server allows its owner to configure which URLs should be handled by which CGI scripts.  For example,
http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=string
this will ask web server to call printenv.pl script with /with/additional/path?and=a&query=string as argument.
With manual resolve mode, the smart contract can work as CGI script similar to Web2.  This brings the following unique benefits:

Support Web3 URI with HTTP-URL-style path and query, which existing Web2 users are most familiar with;
Be compatible with existing HTTP-URL pathing, such as relative path.  This means a HTML/XML can reference their relative resources easily (e.g., web3://aaa.eth/a.svg referencing ./layers/0.svg will be translated to web3://aaa.eth/layers/0.svg by browser);
Default web index (e.g., web3://aaa.eth/ could reference to web3://aaa.eth/index.html as configured by the contract).

I think that these features should greatly bridge the gap between Web2 users to Web3 dApps.
Admittedly that the users need to know what mode the contract is in to correctly construct a URI.  However, the manual mode only works to CGI contracts that serve special web content needs, while 99+% of existing contracts are not affected.  As a result, we could safely assume that the implementers (most likely the CGI contract developers) have the full knowledge of how to interact with CGI contracts in manual model.
What do you think?



 SamWilsn:

Just kinda throwing the idea out, but what if there were some implied defaults, if not specified? For example web3://foo.eth/->/aaa.svg could mean “call a function with the signature index(string) -> (string)”


I think if we enable manual mode, the implied defaults may be implemented by the contract themselves?  Similar to setting directory index in Web servers (Web server directory index)



 SamWilsn:

How would you handle resolving ENS names that use DNSSEC? For example supersaiyan.xyz is a valid ENS name.


Thanks for the comment.  Do not have a plan right now.  But we could create an extension EIP for supporting DNSSEC after finalizing this one?

Author: qizhou
Date: 2022-04-18T18:35:52.387Z

Some updates on EIP-4804

name type is replaced by address type
add a principle to highlight that EIP-4804 should be maximum compatible with the HTTP-URL standard so that existing Web2 users can migrate to Web3 easily with minimal knowledge of this standard.

The second one is inspired by our discussion of interoperability with SVG (or more generally, any on-chain Web content), which is one of the most applications we want to support.  Please take a look.



 SamWilsn:

If you’re using a gateway (like foo.test), I’m guessing the full URL would look something like https://example.eth.foo.test/balanceOf/bar.eth#uint256? If the gateway is returning the raw data, it wouldn’t be able to access the anchor… So it makes sense to put it in the path component.


Yes, the URL may look like
https://example.eth.foo.test/balanceOf/bar.eth#uint256 or
https://foo.test/example.eth/balanceOf/bar.eth#uint256
where the ipfs’s gateway has similar link to resolve ipfs resources.



 qizhou:

Q3: If types are supplied, where to put the input argument types and return types (which can be a tuple)? E.g.,

web3://foo.eth/balanceOf(address):(uint256)/bar.eth
web3://foo.eth/balanceOf(address)->(uint256)/bar.eth
web3://foo.eth/balanceOf->(uint256)/address!bar.eth
web3://foo.eth->(uint256)/balanceOf/address!bar.eth



Given the principle that we want to maximize compatibility with HTTP-URL, we the 5th option may be
5. web3://foo.eth/balanceOf/address!bar.eth?returnType=(uint256)
which is more like a standard HTTP-URL.

Author: qizhou
Date: 2022-04-25T18:15:56.361Z

An illustration of auto mode and manual mode for resolving web3 URLs
image1930×640 75.4 KB

Author: sbacha
Date: 2022-05-24T19:25:25.688Z

EIP has been merged yesterday Create EIP-4804 (#4995) · ethereum/EIPs@49fc53b · GitHub

Author: monkeyontheloose
Date: 2022-06-26T22:50:47.405Z

hey sers, i’m thinking about implementing this as a web2.0 service, would love to dm and talk about it. my telegram is @monkeyontheloose

Author: TimDaub
Date: 2022-06-27T10:22:44.273Z

Hey peeps, I believe I found a similar technique and proposed it to standardize in CASA: eth_call signature combined with block number is a unique identifier · Issue #87 · ChainAgnostic/CAIPs · GitHub

Author: qizhou
Date: 2022-06-27T16:28:28.025Z

Thanks for pointing this out.  Looks like there are a couple of overlaps, but it seems the target applications are quite different? E.g., ERC-4804 serves as an HTTP-style resource locator, which is designed with some unique features

MIME detection
Auto-type detection to simplify the links
CGI-style resolve model to allow “smart contract as CGI script”
Do not ask for the block number (but we could add it if we really need this)

A couple of applications are

on-chain SVG generating: web3://cyberbrokers-meta.eth/renderBroker/2349

on-chain blogger (using Vitalik’s as example): web3://vitalikblog.eth/


BTW: Our extension for supporting web3:// links is available at Firefox Web3Q: Fully Decentralized Web3 – Get this Extension for 🦊 Firefox (en-US)

Author: TimDaub
Date: 2022-06-30T15:52:44.811Z

We discussed this proposal in today’s CASA meeting:

According to RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax, the URI scheme namespace is managed by https://www.iana.org/ and so we think it is out of the scope of this proposal to use “web3://” (unless you’re planning to register it there or we’ve missed something).
As Ethereum is just one chain within “web3,” we noted that a potentially better scheme identifier for this EIP would be “eth://” or e.g. “evm://”
From what I understood, CASA would be happy to welcome this EIP on their side as to e.g. generalize the scheme towards “web3://” (multi-chain)

Author: sbacha
Date: 2022-07-01T04:34:40.181Z

Similar discussion wrt the uri identifier is being discussed by @SamWilsn and the in draft webRTC connection for web3 providers.
Chrome blocks non standard uri identifiers as well

Author: qizhou
Date: 2022-07-02T05:50:20.397Z

TimDaub:

According to RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax, the URI scheme namespace is managed by https://www.iana.org/ and so we think it is out of the scope of this proposal to use “web3://” (unless you’re planning to register it there or we’ve missed something).


Many thanks for the information.  The assignment information is very helpful.  I just send a request for assigning web3:// schema of URI for EIP-4804 to iana and wait for their response  I will update the info if I get any response.



 TimDaub:

As Ethereum is just one chain within “web3,” we noted that a potentially better scheme identifier for this EIP would be “eth://” or e.g. “evm://”


Thanks for the comment.  EIP-4804 natively supports multiple EVM chains (i.e., rinkeby/kovan/arbi/optim/bsc by replacing port to chain id) so I feel using eth:// may be too narrow.  Further, one major application of EIP-4804 is to provide a web3 resource locator that can be dynamically generated on-chain, especially web resources such as SVG/HTML, therefore I feel that web3:// may better serve the purpose.



 TimDaub:

From what I understood, CASA would be happy to welcome this EIP on their side as to e.g. generalize the scheme towards “web3://” (multi-chain)


Many thanks for the invitation.  I am very glad to explore the applications of web3:// for non-EVM blockchains, and I am open to collaborating on the generalization and improving EIP-4804 accordingly. For the next step, one thing I would like to do is to give a presentation of the motivation, design thoughts, and applications of EIP-4804 at the next CASA meeting?  Then we could collect some consensus and move to future steps.  What do you think?

Author: qizhou
Date: 2022-07-06T00:28:22.428Z

Just let everyone know that we have registered web3:// URI scheme at IANA.  Anyone can find the assignment at  Uniform Resource Identifier (URI) Schemes

Author: mango
Date: 2022-07-06T14:51:57.991Z

How does gateway resolution work if I don’t specify a gateway like foo.test?
Is there any proof returned in the response to make sure that my gateway is not lying to me?

Author: high_byte
Date: 2022-07-06T15:49:00.899Z

nice EIP.
what I would suggest is to encode the entire signature at once like so:
web3://.../balanceOf(address)/...
since the entire canonical signature is used to encode the function selector. an error in parsing arguments (e.g. confusing bytes32/uint256, or bool/uint8/uint256 or bytes/strings, etc.) could lead to incorrect function called.
if there’s a fallback that behaves differently it would be unintuitive to debug.
by specifying the exact function signature then you don’t have ambiguities with params and can leave params out as defaults. (e.g. balanceOf(address) with no param would be balanceOf(0x0))
once you have the function 4bytes selector you can fetch the return type from a db such as 4bytes.directory.
edit: if I may suggest it can be useful to pass an optional block number too, eg. in case you want to fetch balance in a previous block.

Author: qizhou
Date: 2022-07-06T16:42:16.074Z

Generally, to avoid lying to the users, the browser needs to

become a light client of the blockchain (in the Ethereum PoW chain case, that means all headers, which need some time to download.)
show the proof of data visited.  This is mostly the Merkle proof of the data in the state trie.

Note that asking the gateway to return these data for each web3:// request (especially all headers) may be over-burdened.
To achieve a fully trustless web, one direction is to have a browser extension that

becomes a light client of the blockchain, which downloads the headers in the background (can from the gateway or p2p network); and
ask the gateway to respond with the proof (or the extension itself can directly access p2p network). With the light client data, we can tell whether the gateway lies or not.

There are a lot of interesting things that need to be done, but I think the web3 URL will serve as a good starting point to enable a fully-decentralized web3!

Author: qizhou
Date: 2022-07-06T17:30:58.806Z

high_byte:

what I would suggest is to encode the entire signature at once like so:
web3://.../balanceOf(address)/...
since the entire canonical signature is used to encode the function selector. an error in parsing arguments (e.g. confusing bytes32/uint256, or bool/uint8/uint256 or bytes/strings, etc.) could lead to incorrect function called.
if there’s a fallback that behaves differently it would be unintuitive to debug.


We have a discussion on where to put the argument types in the standard here EIP-4804: Web3 URL to EVM Call Message Translation - #13 by qizhou, where I think your suggestion is close to option 2
image688×212 28.1 KB
We have a regular URI/URL meeting every two weeks.  In the last meeting, we reached the agreement to use returnTypes attribute to specify the return types. I could include the topic of where to specify the input types in the next meeting (see here for more info URL/URI standard working group - HackMD)



 high_byte:

once you have the function 4bytes selector you can fetch the return type from a db such as 4bytes.directory.


This seems to introduce the dependency on 3rd party db. I think we should avoid this because the standard is a decentralized resource locator that should not depend on any 3rd component.



 high_byte:

edit: if I may suggest it can be useful to pass an optional block number too, eg. in case you want to fetch balance in a previous block.


This can be done by setting an optional block attribute in the attribute-value list.  However, we may not expect the gateway or browser to fully support it because calling a contract on a historical block requires running an archive node.

Author: TimDaub
Date: 2022-07-07T17:53:46.831Z

Hey, I’ve added the block number tag to CAIP-19:

CAIP-19: Add block number tag by TimDaub · Pull Request #119 · ChainAgnostic/CAIPs · GitHub
Add blockNumberTag by TimDaub · Pull Request #25 · ChainAgnostic/caip-js · GitHub

Would be cool if this EIP also included it such that we can link to any historical chain state.

Author: qizhou
Date: 2023-02-03T03:06:25.257Z

Hi everyone.  We have launched two gateways w3eth.io and w3link.io to support the standard.
We have uploaded all @VitalikButerin’s blog (40MB) on Arbitrum Nova mainnet permanently with only 0.13 ETH!  Using the standard and gateway, you can browse the unstoppable website at https://0xe4ba0e245436b737468c206ab5c8f4950597ab7f.arb-nova.w3link.io/ or with ENS https://vitalikblog.w3eth.io (or web3://vitalikblog.eth/) !

Author: nand
Date: 2023-03-17T10:27:14.519Z

Hi!
Just discovered this EIP, nice!
I’ve been developping a electron-based proof-of-concept browser implementing a evm:// protocol I made up (&& refined with frolic), so I am happy to migrate to this EIP.
https://github.com/nand2/evm-browser
I have several questions :

Auto mode: If I have a method that returns 3 strings, and I want the second one returned as string, not JSON, how do I do it? For example, a method that return a token representation in HTML, SVG, TXT(ascii art) that I put in . For tuples and non-bytes/string results, I feel there should be a way to say that we want the result either as raw or as json?
Auto mode: If I have a method that returns a string and I want to return this string cast as a specific MIME type (e.g. image/svg+xml), how do I do it?
Auto mode: If I have a mathod that returns returns 2 variables, and I want the second one cast as image/svg+xml ?
Auto mode: Autodetection of the type of argument : I can see an issue with the autodetection of bytes : if the contract expect bytes, and we put bytes in the URL and don’t explicitely set the type, and by bad luck it has 20 or 32 length, then autodetection switch to bytes32/address type and the call signature changes, and it breaks the call. So maybe, for the bytes type, the type must always be explicitely present, it should not be autodetectable, like string?
Manual mode: how do you specify the return data types and MIME type, since the full path?query is sent to the smartcontract?

Thanks!

Author: qizhou
Date: 2023-03-23T20:31:16.049Z

nand:

Auto mode: If I have a method that returns 3 strings, and I want the second one returned as string, not JSON, how do I do it? For example, a method that return a token representation in HTML, SVG, TXT(ascii art) that I put in . For tuples and non-bytes/string results, I feel there should be a way to say that we want the result either as raw or as json?


If my understanding is correct, you can put returns=(string, string, string) in the query, and the standard will return the JSON like [s0, s1, s2], and then you can retrieve the second one by getting s1 in the JSON data.  E.g.,
curl web3://contractAddr/method?returns=(string,string,string) | jq '.[1]'
(you may replace web3:// with a gateway)
Then it should return the second string as you need.



 nand:

Auto mode: If I have a method that returns a string and I want to return this string cast as a specific MIME type (e.g. image/svg+xml), how do I do it?


Thanks for the comment.  The easiest way is to allow the contract to accept the argument as string + “.” + suffix, where the suffix will decide the MIME return type.  You can check the description of the standard here:
image2130×262 62.6 KB
An example of such a link is here
https://0x804a6B66b071e7E6494AE0e03768a536ded64262.w3q-g.w3link.io/compose/string!111.svg



 nand:

Auto mode: If I have a mathod that returns returns 2 variables, and I want the second one cast as image/svg+xml ?


Thanks for the comment.  I don’t think you can do that as MIME can be only applied to one web3:// response (and it should also apply to an HTTP:// response).  In such a case, you should separate the returned variables into two different methods.



 nand:

Auto mode: Autodetection of the type of argument : I can see an issue with the autodetection of bytes : if the contract expect bytes, and we put bytes in the URL and don’t explicitely set the type, and by bad luck it has 20 or 32 length, then autodetection switch to bytes32/address type and the call signature changes, and it breaks the call. So maybe, for the bytes type, the type must always be explicitely present, it should not be autodetectable, like string?


Thanks for the comment.  The reason to support autodetection for address and bytes32 is that they are much more frequently used vs other non-20-or-32 bytes on contracts.  I do see a potential problem that a developer/user may put a bytes with auto-detection but it was mistakenly parsed to address or bytes32.  One way is that we can remove the auto-detection for non-20-or-32 bytes so that for bytes input, we always ask for explicit bytes type. We can collect more consensus from the community on this part.



 nand:

Manual mode: how do you specify the return data types and MIME type, since the full path?query is sent to the smartcontract?


Thanks for the comment.  It will be determined by the last argument of the full path.  See below copied from the standard.
image2170×346 75.9 KB
It is a bit confusing that the MIME detection only applies to “auto” model, but it actually applies to both “auto” and “manual” modes.
Hope this could explain.  Thank you!

Author: nand
Date: 2023-03-24T09:26:34.549Z

Thank you for your answers!



 qizhou:




 nand:

Auto mode: If I have a method that returns 3 strings, and I want the second one returned as string, not JSON, how do I do it? For example, a method that return a token representation in HTML, SVG, TXT(ascii art) that I put in . For tuples and non-bytes/string results, I feel there should be a way to say that we want the result either as raw or as json?


If my understanding is correct, you can put returns=(string, string, string) in the query, and the standard will return the JSON like [s0, s1, s2], and then you can retrieve the second one by getting s1 in the JSON data. E.g.,
curl web3://contractAddr/method?returns=(string,string,string) | jq '.[1]'
(you may replace web3:// with a gateway)
Then it should return the second string as you need.


Ok, yes the usecase I had in mind was, what if I want to directly access the value because I am using for example <img src="web3://..." />,…
But yes this usecase should be very very rare, and if it happens, one can always write a method proxying this. So I drop this.



 qizhou:




 nand:

Auto mode: If I have a method that returns a string and I want to return this string cast as a specific MIME type (e.g. image/svg+xml), how do I do it?


Thanks for the comment. The easiest way is to allow the contract to accept the argument as string + “.” + suffix, where the suffix will decide the MIME return type. You can check the description of the standard here:
image2130×262 62.6 KB
An example of such a link is here
https://0x804a6B66b071e7E6494AE0e03768a536ded64262.w3q-g.w3link.io/compose/string!111.svg


Ok so if I understand correctly, in your example, the actual web3 url would be :  web3://0x804a6b66b071e7e6494ae0e03768a536ded64262/compose/string!111.svg
I can see a problem : Let’s take
web3://0xxxxxx/method/string!bla.svg
What if I wanted to send the string “bla.svg” as argument to the method? So here I don’t want to cast the result as SVG, I just want to send the string “bla.svg”.
So if a method ask for a string, and by bad luck, there is at the end of the string a dot and some letters, and the browser recognized these letters as a mime type, then the browser would remove the dot and the letters from the argument given to the method, and the browser would wrongly cast the output as something not planned.
Maybe an idea would be to put the (still optional) mime suffix to the method, web3://<contract>/<method>[.<suffix>]/<arg1>... such as web3://0xxxxxx/method.html/string!bla.svg ?



 qizhou:




 nand:

Manual mode: how do you specify the return data types and MIME type, since the full path?query is sent to the smartcontract?


Thanks for the comment. It will be determined by the last argument of the full path. See below copied from the standard.
[removed because new users can only post 1 pic!]
It is a bit confusing that the MIME detection only applies to “auto” model, but it actually applies to both “auto” and “manual” modes.


Ok for mime type.
Regarding the return data types, is it mandatory on the manual mode that a method must return only one value, or can it returns multiple values, and we have to declare it with returns=() ?
Thank you for your answers

Author: qizhou
Date: 2023-03-25T07:43:13.434Z

nand:

Ok so if I understand correctly, in your example, the actual web3 url would be :  web3://0x804a6b66b071e7e6494ae0e03768a536ded64262/compose/string!111.svg
I can see a problem : Let’s take
web3://0xxxxxx/method/string!bla.svg
What if I wanted to send the string “bla.svg” as argument to the method? So here I don’t want to cast the result as SVG, I just want to send the string “bla.svg”.
So if a method ask for a string, and by bad luck, there is at the end of the string a dot and some letters, and the browser recognized these letters as a mime type, then the browser would remove the dot and the letters from the argument given to the method, and the browser would wrongly cast the output as something not planned.
Maybe an idea would be to put the (still optional) mime suffix to the method, web3://<contract>/<method>[.<suffix>]/<arg1>... such as web3://0xxxxxx/method.html/string!bla.svg ?


Thanks for the comments.  If the string happens to be the last argument with a suffix, it may return an undesired MIME.  However, I would guess such a situation will be rare for auto mode.  In the manual mode, since the contract developer already knows EIP-4804, the MIME with the last argument with a suffix should fall into the contract design expectation (i.e., the developer should avoid passing “.svg” as the last argument to a non-svg data).
The key thing is that the auto mode is designed to be compatible with existing contracts, which are not aware of EIP-4804, and thus we should not rely on any assumption on the method name.  If the contract uses manual mode, then the contract developer should be aware of EIP-4804, and thus the developer could design the way to work with MIME detection correctly.  What do you think?
In the long term, we may add the third mode (or an option to manual mode) to support the MIME return by contracts.  That means each contract method in this method will return (bytes32, bytes32), where the first one is the MIME type, and the second one is the data. Or we may even support a mode that each method will return (httpResponseHeader, bytes32).  However, this seems to be a rather big change, we need to collect more comments from the community, especially experts from HTTP or browsers.



 nand:

Ok for mime type.
Regarding the return data types, is it mandatory on the manual mode that a method must return only one value, or can it returns multiple values, and we have to declare it with returns=() ?


Thanks for the comment.  The manual mode is designed for the contracts designed for the frontend, so it only returns one value (bytes32) and declares it with returns=() will just pass the data to calldata.
In the future, we may add the reserved queries that may be prefixed by __ (double underscore) if we want to pass more other info such as gasLimit, but we may need to collect more consensus from the community to see if it is the best way.

Author: nand
Date: 2023-03-25T10:13:17.760Z

qizhou:

Thanks for the comments. If the string happens to be the last argument with a suffix, it may return an undesired MIME. However, I would guess such a situation will be rare for auto mode. In the manual mode, since the contract developer already knows EIP-4804, the MIME with the last argument with a suffix should fall into the contract design expectation (i.e., the developer should avoid passing “.svg” as the last argument to a non-svg data).
The key thing is that the auto mode is designed to be compatible with existing contracts, which are not aware of EIP-4804, and thus we should not rely on any assumption on the method name. If the contract uses manual mode, then the contract developer should be aware of EIP-4804, and thus the developer could design the way to work with MIME detection correctly. What do you think?


Thank for the answer.
Ok for auto mode : we can say that when we develop a website, and we want to call a external third-party method that could trigger this bug, we can write a wrapper around it.
So I will focus on manual mode :
I think it is too bad that, when I develop an onchain website, I will always need to think that there should be not dots in the last argument of my URLs.
My string arguments would either need to not be the last argument of URLs, or need to not contains dots. If the string is provided by user, I would need to replace dots by another placeholder.
And I just realized that even float numbers have this issue :
web3://xxxx/method_using_gps_coordinautes/36.214/23.123
(unfortunately “.123” is a valid mime type of application/vnd.lotus-1-2-3)
So if I want to make a method that takes as input only a float, I would need to add a dummy argument at the end, or replace dots by a placeholder, or scale them by 10^n to avoid the dot.
Would it not be better to do it in a way that does not add constraints on the contents of your arguments when you develop a onchain website?
If you think it is not a problem, I will say no more and I will implement the browser using the current EIP-4804 definition.



 qizhou:

In the long term, we may add the third mode (or an option to manual mode) to support the MIME return by contracts. That means each contract method in this method will return (bytes32, bytes32), where the first one is the MIME type, and the second one is the data. Or we may even support a mode that each method will return (httpResponseHeader, bytes32). However, this seems to be a rather big change, we need to collect more comments from the community, especially experts from HTTP or browsers.


That’s great to hear  I also have some ideas for a third mode, but yeah let’s keep that for later.

Author: qizhou
Date: 2023-03-27T08:43:08.885Z

nand:

My string arguments would either need to not be the last argument of URLs, or need to not contains dots. If the string is provided by user, I would need to replace dots by another placeholder.
And I just realized that even float numbers have this issue :
web3://xxxx/method_using_gps_coordinautes/36.214/23.123
(unfortunately “.123” is a valid mime type of application/vnd.lotus-1-2-3)
So if I want to make a method that takes as input only a float, I would need to add a dummy argument at the end, or replace dots by a placeholder, or scale them by 10^n to avoid the dot.
Would it not be better to do it in a way that does not add constraints on the contents of your arguments when you develop a onchain website?
If you think it is not a problem, I will say no more and I will implement the browser using the current EIP-4804 definition.


Thanks for the comment.  With the float or with dots in argument, I think an easy is to add the suffix to tell what type it is.  E.g., for web3://xxxx/method_using_gps_coordinautes/36.214/23.123, if you want to return an SVG file, then you can have the URL as
web3://xxxx/method_using_gps_coordinautes/36.214/23.123.svg
This will allow the system to quickly identify the MIME to return.
Note that, in manual mode, we may not expect to have method in the path (while auto mode will always have) since all path+query will be sent to the contract as the calldata.  Taking Vitalik’s blog as an example, the following is a valid web3:// URL
web3://vitalikblog.eth/index.html
where index.html is just the path of the file (i.e., calldata=‘/index.hml’).
Hope this could explain.  Thank you!

Author: nand
Date: 2023-03-27T09:03:03.540Z

qizhou:

Thanks for the comment. With the float or with dots in argument, I think an easy is to add the suffix to tell what type it is. E.g., for web3://xxxx/method_using_gps_coordinautes/36.214/23.123, if you want to return an SVG file, then you can have the URL as
web3://xxxx/method_using_gps_coordinautes/36.214/23.123.svg
This will allow the system to quickly identify the MIME to return.
Note that, in manual mode, we may not expect to have method in the path (while auto mode will always have) since all path+query will be sent to the contract as the calldata. Taking Vitalik’s blog as an example, the following is a valid web3:// URL
web3://vitalikblog.eth/index.html
where index.html is just the path of the file (i.e., calldata=‘/index.hml’).
Hope this could explain. Thank you!


Thanks for the reply!
Ok got it: if there is the possibility of a dot in the last argument, always add the extension.
I will now work to implement web3:// on the evm-browser.

Author: nand
Date: 2023-04-21T08:18:41.750Z

I think I should post it here too :
Here is an proof of concept implementation of eip-4804, with support of proposed EIP-6821 for domain name resolution:
https://github.com/nand2/evm-browser
Only limitation : web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies) are disabled (very indirectly due to chromium URL parser not liking hexadecimal numbers as a host of an URL)

Author: qizhou
Date: 2023-04-24T05:24:40.511Z

Fantastic work!  Looking forward to the full support!

Author: poojaranjan
Date: 2023-05-02T17:51:04.915Z

ERC-4804: Web3 URL to EVM Call Message Translation with @qizhou

Author: qizhou
Date: 2023-05-03T01:39:07.745Z

Many thanks for organizing and hosting the interview!

Author: MidnightLightning
Date: 2023-05-12T13:05:59.066Z

I’m happy to have found this EIP; it’s an idea I was thinking should be created, and glad to see that it’s had great progress made!
As an artist and developer, I’m keenly interested in the image/SVG handling. Sounds like handling of URLs ending in .svg is in progress but not quite implemented yet? From my experience exploring existing smart contracts that do on-chain image-generation, for string or bytes returns, there’s a few ways they format the results:


Raw String (e.g. MoonCatRescue: web3://0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14/accessorizedImageOf/1289): a string that starts with “<svg”


Data URL-style: “data:[<mediatype>][;base64],” prefix in front of the string (e.g. SVG string starts with “data:image/svg+xml,<svg”)


Token URI embed (e.g. Loot: web3://0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7/tokenURI/100): JSON blob (possibly with application/json data URL prefix, possibly base64-encoded) that contains an image property that is an SVG string (possibly with image/svg+xml data URL prefix, possibly base64-encoded).


The “Raw String” style would need a suffix on it in the Web3 URL, or would have to use some form of “magic bytes” processing to guess at the file format (which would likely have varying levels of success being automatic). Data-URL-formatted strings could be automatically unwound by the gateway server and have a good level of confidence in what format the output is supposed to be (for standard mediatypes). This would help many different output types, including text formats (e.g. Autoglyphs web3://0xd4e4078ca3495de5b1d4db434bebc5a986197782/draw/100)
The “Token URI” format is a special case that I’m not sure if the Web3 URL gateway wants to be able to support? In general it’s a question of if the gateway structure wants to be able to unwind JSON-structured results programmatically? If the request ends in “/100.json”, it’s clear the request is desiring JSON as a response. But if the request ends with “/100.svg”, but the smart contract returns a string that has a data URL prefix indicating it’s JSON, the gateway could parse the JSON, and return just the image property of the JSON object?
Or, to be more specific, the Web3 URL format could create a specific way to indicate a specific property of a JSON result is desired? Some possible URL formats for “sending argument ‘100’ results in a string output that is JSON-encoded. Grab the ‘image’ property of that JSON object and return it, formatted as an SVG”:

.../100.json/image.svg
.../100.json#image.svg
.../100.json?result=(image:image/svg+xml)

That first format treats JSON files as if they were folders in a file hierarchy, which seems to fit with the other goals of this initiative?
One other thing to consider is using the Accept HTTP header as a way to deduce the request’s intent, and also as a way to determine desired failback methods. A request that comes with a header of
Accept: image/svg+xml, application/json;q=0.9, text/html;q=0.8, */*;q=0.5
is then very clear that it desires SVG data primarily, but if the gateway cannot serve that, JSON is second-choice, followed by HTML, and it failing all that, it would accept any other format the gateway can serve. That behavior is less to do with the URL itself, so not sure if that should be part of this standard, or a different standard on gateway behavior? The “Accept HTTP Header” is usually described as part of how the http:// schema is defined, so in that case it would fit that it should be called out in this standard that defines the web3:// schema how it handles request headers, and not just the URL itself?

A method of string encoding that is promoted by the IPFS ecosystem (which many Ethereum projects use, but I haven’t seen any smart contracts use this style of string encoding in their output) is using a “Multibase” identifier.
Multibase as a protocol allows for specifying Base-64-encoding (“m” prefix), as well as JSON-formatted payload (Multicodec 0x0200 prefix), so could be another text format to auto-detect and parse.

Author: MidnightLightning
Date: 2023-05-12T13:50:44.455Z

Regarding the “resolve modes” for this standard, it currently looks to the resolveMode function to determine what the contract is capable of. Has there been any consideration done to include ERC165 as part of how a gateway determines what the contract is capable of? For widely-used standards like ERC20, ERC721, and ERC1155, if a contract presents an ERC165 interface that advertises it supports one of those standards, that could help make more robust “default” responses?
For example, if a request is made for a contract with no function call in the path, and the gateway tries calling a resolveMode function and it returns “auto”, it could then try calling a supportsInterface function on that contract, and if it returns true for ERC20, then the gateway could return an HTML “card” representation of that contract’s name, symbol, and total supply (the known static metadata options for ERC20 contracts).
This could also affect not just the default return for a contract, but for contracts like ERC721, could make a call like web3://collectionaddress/100 return an HTML representation of token ID 100 from that NFT collection (showing image, properties, current owner, etc.)
Would there be any interest in having “auto” mode be “smarter” by using ERC165 interfaces?

Author: qizhou
Date: 2023-05-18T06:57:58.959Z

Many thanks for the suggestions!  I agree that supporting some widely-adopted standard such as ERC-20, ERC-721 will increase the UX.  One concern that from my head is that this creates further dependency of ERC-4804 with other ERCs.  Further, this breaks a goal of ERC-4804, which translates an  web3:// to a single EVM message (rather than multiple messages and display them in an organized way).
Note that web3:// is highly composable - we can create a web3://, which returns an HTML and further display the information of ERC-20/721.  What do you think?

Author: qizhou
Date: 2023-05-18T07:27:09.030Z

A lot of great thoughts on improving ERC-4804.  A couple of my thoughts:



 MidnightLightning:

As an artist and developer, I’m keenly interested in the image/SVG handling. Sounds like handling of URLs ending in .svg is in progress but not quite implemented yet? From my experience exploring existing smart contracts that do on-chain image-generation, for string or bytes returns, there’s a few ways they format the results:

Raw String (e.g. MoonCatRescue: web3://0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14/accessorizedImageOf/1289 ): a string that starts with “<svg”
Data URL-style: “data:[<mediatype>][;base64],” prefix in front of the string (e.g. SVG string starts with “data:image/svg+xml,<svg”)
Token URI embed (e.g. Loot: web3://0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7/tokenURI/100): JSON blob (possibly with application/json data URL prefix, possibly base64-encoded) that contains an image property that is an SVG string (possibly with image/svg+xml data URL prefix, possibly base64-encoded).

The “Raw String” style would need a suffix on it in the Web3 URL, or would have to use some form of “magic bytes” processing to guess at the file format (which would likely have varying levels of success being automatic). Data-URL-formatted strings could be automatically unwound by the gateway server and have a good level of confidence in what format the output is supposed to be (for standard mediatypes). This would help many different output types, including text formats (e.g. Autoglyphs web3://0xd4e4078ca3495de5b1d4db434bebc5a986197782/draw/100)


Great!  We also found that using suffix of the last argument is not enough to render contract data in “auto” mode.  This is a very good summary.  One idea that we are discussing is to add a query string to specify the MIME type.  E.g., a way may be
.../100?mime=image/svg+xml (Note that / between images and svg should be escaped) or
.../100?mime.types=svg
For data URL, unfortunately, I cannot find an MIME for data URL itself.  Do you have any suggestions on that?



 MidnightLightning:

Or, to be more specific, the Web3 URL format could create a specific way to indicate a specific property of a JSON result is desired? Some possible URL formats for “sending argument ‘100’ results in a string output that is JSON-encoded. Grab the ‘image’ property of that JSON object and return it, formatted as an SVG”:

.../100.json/image.svg
.../100.json#image.svg
.../100.json?result=(image:image/svg+xml)

That first format treats JSON files as if they were folders in a file hierarchy, which seems to fit with the other goals of this initiative?


I personally won’t complicate the standard with further parsing features in JSON or any other format (e.g., HTML).  The reason is that we could use other tools to decode the data in a composable way like
curl web3://contractAddr/method?returns=(string,string,string) | jq '.[1]' 
so that we could use the composability of the tools and keep ERC-4804 as simple as possible.  What do you think?



 MidnightLightning:

One other thing to consider is using the Accept HTTP header as a way to deduce the request’s intent, and also as a way to determine desired failback methods. A request that comes with a header of
Accept: image/svg+xml, application/json;q=0.9, text/html;q=0.8, */*;q=0.5
is then very clear that it desires SVG data primarily, but if the gateway cannot serve that, JSON is second-choice, followed by HTML, and it failing all that, it would accept any other format the gateway can serve. That behavior is less to do with the URL itself, so not sure if that should be part of this standard, or a different standard on gateway behavior? The “Accept HTTP Header” is usually described as part of how the http:// schema is defined, so in that case it would fit that it should be called out in this standard that defines the web3:// schema how it handles request headers, and not just the URL itself?


This is a great suggestion!  We are currently thinking about adding an extension to ERC-4804 to support customized headers (See EIP-6944 and EIP-5219).  Definitively we can take this into account to make the standard more powerful!

Author: qizhou
Date: 2023-05-28T16:24:01.934Z

A proposal to enhance MIME type of Web3 URLs in auto model is here EIP-7087: MIME Type For Web3 URL in Auto Mode

Author: qizhou
Date: 2023-07-11T12:28:13.979Z

A Chrome-extension to support web3:// is developed by an anonymous community developer here GitHub - ComfyGummy/chrome-web3: Chrome extension for web3:// (ERC-4804) URLs
I have tested it and it runs very well even in very early stage.  The work is super fantastic with very deep understanding of Chrome browser and http!  It also provides some gif to ease the use of the extension!

Author: qizhou
Date: 2023-07-11T12:29:09.038Z

Also, we have a talk about web3:// URL (ERC-4804) at EthCC.  Please come if you are interested in it!
image1582×978 115 KB

Author: MidnightLightning
Date: 2023-07-20T12:18:04.794Z

qizhou:

For data URL, unfortunately, I cannot find an MIME for data URL itself. Do you have any suggestions on that?


“Data URL” doesn’t have a mime-type itself, since it’s a way of specifying mime types for a payload (similarly, “this file has a three-letter extension separated from the filename by a period to specify its type” doesn’t have a mime-type itself).
I would suggest that “Data URL” style payloads be parsed by the gateway as a good way to guess the mime-type. Therefore for queries like .../100 (that don’t specify a mime-type), the gateway has a pretty confident guess at what the mime-type is (same as how double-clicking on a file with a “.PNG” extension, the operating system has a pretty good guess it’s an image file and has a default action to take in that case). With that idea, .../100?mime=image/svg+xml still returns SVG (same as explicitly right-clicking a “.PNG” file and choosing “open with > picture viewer”; it doesn’t hurt anything, it’s just more verbose call than .../100.



 qizhou:

I personally won’t complicate the standard with further parsing features in JSON or any other format (e.g., HTML). The reason is that we could use other tools to decode the data in a composable way


Sure, that seems good, to have a few interlocking standards like that.

Author: qizhou
Date: 2023-07-26T15:46:02.209Z

Thanks for the comment.  The explicit MIME and dataurl support is proposed here EIP-7087: MIME Type For Web3 URL in Auto Mode.   Please take a look

Author: nand
Date: 2023-08-21T12:25:07.920Z

Hi!
Adding the info here as well on the ERC-4804 “umbrella” :
I have implemented ERC-6944 (adding ERC-5219 as a mode to ERC-4804 web3://) on :

The parsing and executing package GitHub - nand2/web3protocol: Parse and execute ERC-4804 web3:// URLs
The proof of concept EVM Browser GitHub - nand2/evm-browser: Web browser with support of the EIP-4804 web3:// protocol, which can show on-chain websites hosted on Ethereum and all others EVM chains.

I have published a demo ERC-6944 website at web3://web3-mode-5219.terraformnavigator.eth/ (Terraform NFT explorer) whose source code is at https://etherscan.io/address/0x2b51a751d3c7d3554e28dc72c3b032e5f56aa656#code

Author: nand
Date: 2023-08-25T13:00:16.053Z

Hi @qizhou
Question: I have a smartcontract method in which I return a large complex structured data (struct of arrays of struct of strings, ints, …). I want to access that via a web3:// call in auto mode that will return that to me as JSON, but I think I am stuck :
1/ Using returns=(…) does not allow structs && arrays
2/ Generating myself the JSON string in the smartcontract is consuming waay too much gas (and is conceptually wasteful).
Do you see a way to do that, or shall we discuss an extension to the syntax for returns=(…) that handle structs && arrays, as another extension?
I propose this extension spec (while remaining backward compatible) :

?returns=(uint256[]) for an array of uints e.g. [[1, 3]]
?returns=(uint256[],string[]) for a return of 2 args: an array of uints and an array of string e.g. [[1, 3], ["blah", "bloh"]]
?returns=((uint256[],int)) for a return of a single tuple/struct containing an array of uints and an int e.g. [[[1, 3], 5]]
?returns=(string,(uint256[],int)) for a return of 2 args: a string, and a tuple/struct containing an array of uints and an int e.g. ["blah", [[1, 3], 5]]
?returns=((uint256[],(int,address)) for a return of a single tuple/struct containing an array of uints and a tuple/struct of an int and a address e.g. [[[1, 3], [3, "0xabcd"]]]
?returns=((uint256[],string)[]) for a return of an array of tuple/struct containing an array of uints and an int e.g. [[[1, 3], "bb"], [[2, 5], "aa"]]

This above returns everything into JSON arrays. I would like to also propose named vars, so that it returns objects. It would be a varname: prefix to field defs, such as:

?returns=(myattr:(mylist:uint256[],blah:string),bloh:string) which would returns {myattr: {mylist: [2, 4], blah: "boo"}, bloh: "baa"}

If this looks good to you, we could add in on ERC-7087 and broaden its scope?

Author: MidnightLightning
Date: 2023-08-30T13:07:29.446Z

I believe the current “Example 2” in the EIP is incorrect. It currently reads:

Example 2
web3://cyberbrokers-meta.eth/renderBroker/9999

The protocol will find the address of cyberbrokers-meta.eth from ENS on chainid 1 (Mainnet), and then call the address with “To” = “0x…” and “Calldata” = “0x” + keccak("view(uint256)")[0:4] + abi.encode(uint256(9999)).

The example URI given is /renderBroker/9999, but the paragraph after it translates that to calling a view(uint256) function rather than the renderBroker(uint256). I think that paragraph should be updated to be:

The protocol will find the address of cyberbrokers-meta.eth from ENS on chainid 1 (Mainnet). This address exists, and has a contentcontract text value set to 0x8bb9a8baeec177ae55ac410c429cbbbbb9198cac. It will therefore use that address as the “To” value. The contract at 0x8bb9... does not have a resolveMode() function, so the function to call is renderBroker(uint256): “Calldata” = “0x” + keccak("renderBroker(uint256)")[0:4] + abi.encode(uint256(9999)).

Author: MidnightLightning
Date: 2023-08-30T13:19:54.965Z

Example 1
web3://w3url.eth/

The protocol will find the address of w3url.eth from ENS in chainid 1 (Mainnet), and then the protocol will call the address with “From” = “0x…” and “Calldata” = “0x2F”.

This should instead be:

The protocol will look up the metadata of w3url.eth from ENS in chainid 1 (Mainnet). This domain exists, and has a contentcontract text value set to w3q-g:0xEbcA4860ebBe969E9Bc42643fcb437879dBDa9C6. The prefix on that value indicates it’s on the W3Q Galileo blockchain (Blockchain ID 3334). So the protocol will call then address with “To” = “0xEbcA…” and chainid = 3334.

For “Calldata”, the code of contract w3q-g:0xEbcA... is not published on the Galileo explorer, so unclear if it has a resolveMode function or not. If it does exist, I believe the “Calldata” = “0x2F” is accurate, but if it does not have that function, it should be “Calldata” = “0x” (no calldata; same as Example 4)

Author: MidnightLightning
Date: 2023-08-30T13:30:23.673Z

Example 3
web3://vitalikblog.eth:5/

The protocol will find the address of vitalikblog.eth from ENS on chainid 5 (Goerli), and then call the address with “From” = “0x…” and “Calldata” = “0x2F” with chainid = 5.

This example does not appear to work. Looking up the ENS record for “vitalikblog.eth” on Goerli yields an address of 0xc4fbA3740f95d25B2196C9437fDb005359296D36, which is not a smart contract address at all. So that should be “Calldata” = “0x”, but wouldn’t return any value?
That ENS record has a “web3” text value set to arb-nova:0xe4ba0e245436b737468c206ab5c8f4950597ab7f. EIP6821 does not mention that text value, but the name seems to fit here? That then makes the result the same as Example 4 (calling that address on Arbitrum Nova).

Author: qizhou
Date: 2023-09-01T17:09:51.703Z

Hi @nand ,
Returning an array should be already supported in the current ABI standard, e.g., for the following code
pragma solidity >=0.8.2 <0.9.0;

contract Test {
    struct Data {
        uint256 value;
        string str;
    }

    function getValue() public pure returns (uint256[] memory) {
        uint256[] memory m = new uint256[](3);
        m[0] = 1456;
        m[1] = 1235;
        m[2] = 8673;
        return m;
    }

    function getData() public pure returns (Data memory) {
        Data memory dt;
        dt.value = 5823;
        dt.str = "abeff";
        return dt;
    }
}

You should be able to call getValue() and get the array of uint256 via returns=(uint256[]).  Please see the following link in the gateway as an example: https://0x8a7297d333b0243c766029ac31a712eef6451846.3334.w3link.io/getValue?returns=(uint256[])
For structure, I am checking how ABI encodes/decodes a structure, but please let me know if you have any findings.
For the feature of named vars, my concern is that it has not been adopted in existing ABI encoding/decoding practice and we need to cover all concern cases of the format - for example, what if one the name is missing such as ?returns=(myattr:(mylist:uint256[],string),bloh:string) where blah is missing?

Author: qizhou
Date: 2023-09-01T17:13:17.877Z

Hi @MidnightLightning
Many thanks for pointing out the typos.  We do find a couple of typos/issues with the existing EIP-4804 standard, and an amendment can be found here  Update EIP-4804: Add more details for the examples for EIP-4804 by qizhou · Pull Request #6860 · ethereum/EIPs · GitHub (Feel free to comment on it!)  Unfortunately, there is no way to amend a finalized EIP according to the current EIP process, so we may have to create another one (likely reuse EIP-6860) to override EIP-4804.

Author: nand
Date: 2023-09-03T10:11:26.339Z

qizhou:

You should be able to call getValue() and get the array of uint256 via returns=(uint256[]). Please see the following link in the gateway as an example: https://0x8a7297d333b0243c766029ac31a712eef6451846.3334.w3link.io/getValue?returns=(uint256[])


Ah ok I haven’t realized arrays were supported. Will modify the web3protocol lib to properly support it.



 qizhou:

For the feature of named vars, my concern is that it has not been adopted in existing ABI encoding/decoding practice and we need to cover all concern cases of the format - for example, what if one the name is missing such as ?returns=(myattr:(mylist:uint256[],string),bloh:string) where blah is missing?


They are indeed not part of the ABI encoding itself, but as the spec says : Despite the fact that names are intentionally not part of the ABI encoding, they do make a lot of sense to be included in the JSON to enable displaying it to the end user.
https://docs.soliditylang.org/en/latest/abi-spec.html#handling-tuple-types
Indeed, when working with web3:// calls that returns complex structures, it would be too bad to manually have to map the returning arrays into structs.
what if one the name is missing : I would say, if one or more of the name are missing, we fallback to returning arrays only with no names.
Allowed characters for the names : Since any valid string is a valid key in JSON, I suggest we do the same, and we would require quotes if the name contains : , ( ) e.g. returns=("a:1":uint) would return {"a:1": 1234}. If quotes are used and we want to include a quote inside the key, the quote should be escaped as in regular json, e.g. returns=("\"a\":1":uint) would return {"\"a\":1": 1234}
What do you think?

Author: nand
Date: 2023-11-02T16:20:22.809Z

Hi!
In accordance with @qizhou, ERC-6860 was written to formalize, add details, and do small fixes and tiny changes to ERC-4804.
You can view it here :

Ethereum Improvement Proposals


ERC-6860: Web3 URL to EVM Call Message Translation
A translation of an HTTP-style Web3 URL to an EVM call message





Please let us know if you have comments!
2 implementations of ERC-6860 were made :
Golang: GitHub - web3-protocol/web3protocol-go: Parse and execute ERC-4804 web3:// URLs
Javascript: GitHub - web3-protocol/web3protocol-js: Parse and execute ERC-4804 web3:// URLs
Both are using implementation-independent tests in toml files located at : GitHub - web3-protocol/web3protocol-tests: Parse and execute ERC-4804 web3:// URLs
EVM Browser, using the js implementation, can be used to view web3:// URLS : GitHub - nand2/evm-browser: Web browser with support of the EIP-6860 web3:// protocol, which can show on-chain websites hosted on Ethereum and all others EVM chains.
Next is coming : Curl like apps to easily test and experiment with web3:// URLS : GitHub - web3-protocol/web3curl-js: Curl-like app for ERC-4804 web3:// URLs
And next is some serious documentation too.

Author: nand
Date: 2023-12-12T10:12:35.398Z

The web3:// curl app is now there, and with useful verbose modes (level 1, 2, 3)!
Useful to understand how a web3:// query is processed.
Example (level 1 verbose) :
web3curl -v "web3://vitalikblog.eth/css/misc.css"

will output:
* Fetching URL web3://vitalikblog.eth/css/misc.css
* Parsing URL ...
* Host domain name resolver: ens
*   Domain name being resolved: vitalikblog.eth
*   Resolution chain id: 1
*   Resolution type: contentContractTxt
*   contentcontract TXT record: arb-nova:0xe4ba0e245436b737468c206ab5c8f4950597ab7f
*   Result address: 0xe4ba0e245436b737468c206ab5c8f4950597ab7f
*   Result chain id: 42170
* Contract address: 0xe4ba0e245436b737468c206ab5c8f4950597ab7f
* Contract chain id: 42170
* Resolve mode determination... 
> 0xdd473fae
< 0x6d616e75616c0000000000000000000000000000000000000000000000000000
* Resolve mode: manual
* Contract call mode: calldata
* Calldata: 0x2f6373732f6d6973632e637373
* Contract return processing: decodeABIEncodedBytes
* Contract return processing: decodeABIEncodedBytes: MIME type: text/css
*
* Calling contract ...
* Contract address: 0xe4ba0e245436b737468c206ab5c8f4950597ab7f
> 0x2f6373732f6d6973632e637373
* RPC provider used: https://nova.arbitrum.io/rpc
< 0x0000000000000000000000000000000000000000000000000000000000000020...0000000000000000000000000000000000000000000000000000000000000126
*
* Decoding contract return ...
* HTTP Status code: 200
* HTTP Headers: 
*   Content-Type: text/css

[returned data (CSS here)]

Author: MidnightLightning
Date: 2024-01-15T06:08:16.799Z

In the “Specification” section, the technical definition of web3Schema gives three options: ethereum-web3:, eth-web3:, and web3:
However, immediately following it (in the “human-friendly” description of those terms), web3Schema is defined with two options: web3: and w3:
These two descriptions contradict each other. web3: is present in both, which makes it seem like the primary/default option (and indeed all the examples use it), but what of the other three options? The other three are only present in one of the definitions or the other, but not both. Are all four valid?
IANA registrations have been approved for web3: and w3:, but not the other two. So is the first part of the Specification wrong, and ethereum-web3: and eth-web3: are not valid schemas to use for this standard?

Author: qizhou
Date: 2024-01-16T04:14:17.255Z

ethereum-web3: and eth-web3: tries to follow ERC-831: URI Format for Ethereum, but ERC-831 is Stagnant.  So in our latest updated standard ERC-6860, both ethereum-web3: and eth-web3: are removed in the schema (and unfortunately since ERC-4804 is finalized, so we have to replace it rather than modifying it).

Author: nand
Date: 2024-02-16T12:53:04.176Z

A web3:// sandbox  is now available, to play and experiment with web3:// URLs!
Temporary URL : https://web3protocol-sandbox.nand.fr/
Also, 2 new ERCs (pending PR) for the ERC-6944 resource request resolve mode :

ERC-7617: Add chunk support in ERC-6944 resource request mode: a response can be made of several methods calls (useful with serving large content).
ERC-7618: Add Content-encoding handling in ERC-6944 resource request mode : Serving compressed data can now be done.

These 2 features has been added to the web3protocol-js and web3protocol-go libs, and indirectly to web3curl, w3link.io HTTPS gateway and EVM Browser.

Author: qizhou
Date: 2024-02-16T14:26:19.138Z

nand:

A web3:// sandbox is now available, to play and experiment with web3:// URLs!
Temporary URL : https://web3protocol-sandbox.nand.fr/


This is really cool!

Author: nand
Date: 2024-07-12T16:04:40.049Z

With the aim of making creation and edition of a web3:// website easily accessible, I am working on on-chain website NFTs, named OCWebsites : you mint an OCWebsite, then you can access to a graphical interface to upload/manage/delete files, create versions, mark one version live, lock versions, globally lock, manage plugins.
At its core, the “NFT” part is just for handling ownership; and the base OCWebsite is a system handling differents versions, and different plugins. Each version can configure its plugins differently, and is totally independant : the purpose is to handle deployment with preprod/prod, but also to have an historical archive.
Then is packaged by default as plugin :

A static frontend plugin: Upload/manage/delete static files. The main one.
An admin backend, provided by ocweb.eth and served in /admin, which will make the whole website configurable. Anyone could make another admin backend.
A variables injector, served in /variables.json. Useful to boostrap the static frontend with environnment variables.
A proxy: Redirect any local path to a remote website path. Probably won’t be included by default.
A welcome page, served on /, to welcome you for the first time

I have posted a work in progress on Holesky at web3://0x7216Acab8bcF349C01D9E8f3212C7159eE794629:17000/ , you can try now! The /admin plugin is not there yet, but by using the minter website, you can access to this graphical interface.
The minter website (web3://0x7216Acab8bcF349C01D9E8f3212C7159eE794629:17000/) is also an OCWebsite :
Screenshot from 2024-07-12 17-56-28833×674 45.4 KB
Screenshot from 2024-07-12 18-02-02833×674 32.3 KB
Screenshot from 2024-07-12 18-02-42833×674 44.6 KB
I think I should have it ready for early August!

Author: nand
Date: 2024-07-12T16:21:31.236Z

@qizhou Regarding the ongoing hacked frontend situation, what do you think would be the best state-of-the-art way to certify on-chain websites / on-chain website versions ?
My naive take is, let’s have authorities (like HTTPS certificate authorities) post a public key on-chain (which algo?), then let’s have them review and sign the fact that 1/ the website / website version is immutable (source code review), and 2/ they have taken steps to verify that the application submitter is who they claim they are; then the on-chain website expose the signature via a to-be-decided interface.
Then the web3:// browser comes with 0 embedded certificate authorities (and maybe later with some), and the user can add/remove certificate authorities he trust.
Just as a demonstration purpose, we could hack something quickly, make it work with EVM browser, in a “test” mode, then we can show it, and  refine it;
I’m sure after these frontend hacks, people will notice and it will support the case of web3://

Author: nand
Date: 2024-07-13T08:54:15.332Z

Another subject : Regarding the fragment part of URLs (://host/query?args#fragment), we have not specified anything for web3://.
In http, they are not forwarded to the server, and used for anchoring (scrolling to a place in the page), but also for setting state (e.g. some single-page apps use the fragment part as the page, http://xxx/#/mypage)

In resource mode, it sounds logical to not forward it to the “server” as well (I need to fix that on the implementations)
In manual mode: Same thing.
In auto mode: even though it makes no sense to support fragment, I think we should support it because 1/ this is what we expect from URLs, and it would be confusing to not support it on a single case, and 2/ ok extreme case, but we could query an html page which would use the fragment.

So I would go forward adding to erc-6860 the fact that we have the same behavior than HTTP for fragment. (and if we want to send the # char to the server, we url encode it, like HTTP). Any objections?

Author: BoxChen
Date: 2024-07-15T14:20:12.173Z

@qizhou I have a suggestion, although EIP6860 is currently used as a view function, it would be nice to provide some standard execution parameters, such as value, gaslimit, and especially blocknumber(the second argument to eth_call), for easy access to short-term history data.

Author: qizhou
Date: 2024-07-15T15:06:03.501Z

Great suggestion!  I agree that we should add more eth_call parameters in the standard.  However, this means that we have to change the semantics of manual mode a bit - in manual mode, all paths and queries will be passed to the contract.  This means that we need to have some exceptions to the queries.
One example I am thinking about is introducing a special query prefixed by _, which specifies a parameter for eth_call.  E.g.,
web3://usdc.eth/balanceOf/vitalik.eth?returns=(uint256)&_blockNumber=10000
Note that some RPC clients may not support historical state eth_call so web3:// with historical block number may return error.

Author: qizhou
Date: 2024-07-15T15:09:15.452Z

nand:

My naive take is, let’s have authorities (like HTTPS certificate authorities) post a public key on-chain (which algo?), then let’s have them review and sign the fact that 1/ the website / website version is immutable (source code review), and 2/ they have taken steps to verify that the application submitter is who they claim they are; then the on-chain website expose the signature via a to-be-decided interface.


I cannot get the point.  To certify web3://, we only need to prove that the content is from the latest EVM (e.g., light client from Helios or succient proof after verklized state). Why we need additional authorities?

Author: qizhou
Date: 2024-07-15T15:10:10.155Z

Good point! Fragments should be supported as part of goal to be compatible with HTTP.

Author: nand
Date: 2024-07-15T15:46:24.485Z

In addition to EVM verification, I was thinking, for sensitive frontends, for an optional mechanism of external “auditors” which would be required to review and sign any new website change, to be displayed at the browser level. But yeah I am probably over-thinking it, I drop this!

Author: BoxChen
Date: 2024-07-16T07:01:57.717Z

_blockNumber is a good option, but also _value and _from to do some mock calls, I’ll write a pr if I can

Author: qzhodl
Date: 2024-07-16T10:32:33.789Z

I think we can follow the same governance practice for the smart contract: a governance contract will be the admin of the NFT, and only when the token votes exceed a certain threshold can they upgrade the website to a new version.

Author: BoxChen
Date: 2024-07-29T13:33:21.237Z

With the current parsing, many contracts do not have a function that sets the resolvemode. But the call function in these contracts contains some indeterminate long parameters, such as address,uint,tuple, etc. I think we can add some arg to handle these parameters.

Author: qizhou
Date: 2024-07-29T14:07:31.843Z

What is the value of allowing different resolveMode for existing contracts?  Could you please give some examples?

Author: BoxChen
Date: 2024-07-29T14:20:16.277Z

Actually it should be adding more autoparameter types, I was wrong, I will try to change the gateway and add more autoparameter types.

Author: nand
Date: 2024-08-02T15:42:27.438Z

Hi @BoxChen
Thanks for your PR on web3protocol-go at Add array and tuple params support by nishuzumi · Pull Request #1 · web3-protocol/web3protocol-go · GitHub , I can see there is quite some work.
You are looking at adding array/tuple as input to auto mode, that’s a good idea!
I think we should review the specification first here:


For tuple arg, I see your example /functionName/(bool,uint256,bool,uint256[])!(true,123,false,[456,789]) : reusing the returns= syntax is a good idea. Question for the values: how to handle the ,, (, ), [, ] special chars in string values? For example, let’s say I have /functionName/(string,uint)!... and I want to pass the hello "a,") string as the first parameter, /functionName/(string,uint)!(hello "a,"),1234) won’t work. I believe the solution is : we add optional double-quotes to the string value (with the support of quote escaping \"), so that here we have /functionName/(string,uint)!("hello \"a,\")",1234). Any other idea?


For array arg, you propose /functionName/uint64[]![1,3,5]: sound good to me. We should also support multidimensional arrays, such as /functionName/uint64[2][2]![[1,2],[3,4]]. And with the above suggestion of optional double quotes for string values, we would have for example /functionName/string[]![1,abcd,"bla[]"], which will send the array of 3 strings 1, abcd and bla[] to the smart contract.


And of course we should support recursion, with e.g. array of structs such as /funcName/(uint,bool)[]![(1,false),(2,false)], complex mix such as /funcName/((uint,(bool,bool),string[])[],bool)!([(5,(true,true),[boo,baa]),(2,(false,true),[aa,")"])],true), …
Any input/ideas on this rough specification? (If you want, I can do the whole writing on this on the ERC, or you can propose a PR, as you want.)
Thanks for working on this, it is a non-trivial item.

Author: BoxChen
Date: 2024-08-02T17:34:48.515Z

Hi @nand
Thank you very much for your suggestions.
Regarding the first question, yes, my test case doesn’t seem to be as comprehensive as it should be, regarding this case, a stack join for double quotes could be added to the splitTupleElement function. Also you reminded me that all cases of transliteration should be filtered here, including ( [ etc.
The case for multi-dimensional arrays will be relatively complex, but it should be possible to use a regular way to loop through the matches, and the processing here to not complicated.
In the meantime, recursive support should theoretically be supported directly, I’ll try to test this with the test suite.
Thank you very much for the suggested changes, which add a lot of things I’ve overlooked.
In the meantime I I suggest that web3protocal-go does a formatting session using gofmt, at the moment there is no standard formatting procedure for we b3protocal-go’s code, including no use of tab indentation and no omission of the post line semicolon, if that’s possible I can submit a pr to format everything.

Author: BoxChen
Date: 2024-08-03T08:15:13.017Z

Hello,
I am currently encountering some new issues. I’m not sure what standard is being used for string parsing. From what we can see, it seems that strings can be parsed without adding double quotes. If this is the case, then the termination symbols should be commas (,), closing parentheses ), and closing square brackets ], correct?

Author: nand
Date: 2024-08-03T14:32:40.572Z

Hi @BoxChen



 BoxChen:

In the meantime I I suggest that web3protocal-go does a formatting session using gofmt, at the moment there is no standard formatting procedure for we b3protocal-go’s code, including no use of tab indentation and no omission of the post line semicolon, if that’s possible I can submit a pr to format everything.


Sure, thanks, yes please do a PR to format all the code – I admit I never used gofmt there.



 BoxChen:

I am currently encountering some new issues. I’m not sure what standard is being used for string parsing. From what we can see, it seems that strings can be parsed without adding double quotes. If this is the case, then the termination symbols should be commas (,), closing parentheses ), and closing square brackets ], correct?


Well, right now with the existing format /funcName/string!<value>, <value> do not need any double quotes because there are no special characters that can break the parsing of the URL (besides /, ? and #, which are global delimiters, and for which we expect them to be URI-percent-encoded (%2F, %3F and %23)).
The new feature we are discussing is adding 5 new delimiters : [, ], (, ), ,.
Let’s say we have /funcName/string[2]![<value>,<value2>].
If I want to send the strings 1,2,3 and [ to the smart contract:

Without double quote , it will be : /funcName/string[2]![1,2,3,[] : it will break parsing.
With double quote, it will be : /funcName/string[2]!["1,2,3","["] : it can be parsed.

Do you agree?
Thanks for working on this

Author: BoxChen
Date: 2024-08-04T06:28:54.351Z

HI @nand
Using double quotes is indeed a good approach. However, this special implementation might lead to inconsistent parsing across different string contexts. For example, string!1234, string![“1234”,“1234”], (“1234”,[“344”]). The inconsistency might only occur in arrays and tuples.
There’s another approach: requiring all string content to be URI-percent-encoded. According to the wiki, characters like [, ], (, ), and , can all be percent-encoded. This second method has a lower cost and provides a more uniform standard.

Author: BoxChen
Date: 2024-08-04T06:47:30.338Z

Make a pr to fmt code use go fmt by nishuzumi · Pull Request #2 · web3-protocol/web3protocol-go · GitHub

Author: nand
Date: 2024-08-04T11:12:12.595Z

Hi @BoxChen



 BoxChen:

There’s another approach: requiring all string content to be URI-percent-encoded. According to the wiki, characters like [, ], (, ), and , can all be percent-encoded. This second method has a lower cost and provides a more uniform standard.


This could work, but it would make things awkard and weird, because it would require a double URI-percent-encoding. Let me explain.
In HTTP URLs, URI components (e.g. pathPart, queryName, queryValue in /<pathPart1>/<pathPart2>?<queryName>=<queryValue>) are URI-percent-encoded so that they can be parsed.
When the web3:// / http:// URL parsing library parse an URL, they first split the URL into their component, and then, for each component, they first do the URI-percent-decoding (which you can see at mode-auto.go:147 at web3protocol-go for the path parts), and then work on it.
So the path parts string!ab,cd, string!ab%2Ccd, or even %73%74%72%69%6E%67%21%61%62%2C%63%64 are identical and will give the same result, because URI components are always decoded first before being processed.
So let’s say we want to URI-percent-encode strings in arrays/tuples. I have the string a]b I want to give to the smartcontract. If I do : /funcName/string[1]![a%5Db], then the URL library parsing will first decode the URI component string[1]![a%5Db] into string[1]![a]b], then start working on it : it will not work.
It would require a double encoding : string[1]![a%255Db]. Why 2 encodings? Because there are two layers of encoding : one at URI-component level, and one at the string value level.
So, knowing that we need 2 layers of encoding, I believe using URI-percent-encoding for both layers is confusing, because double URI-percent-encoding are difficult to read. I believe using double quotes for the string value encoding is more clear and intuitive.



 BoxChen:

Using double quotes is indeed a good approach. However, this special implementation might lead to inconsistent parsing across different string contexts. For example, string!1234, string![“1234”,“1234”], (“1234”,[“344”]). The inconsistency might only occur in arrays and tuples.


I’ll write some examples.
(Also, the double quotes would be always optional unless necessary.)
Complex (Array/Tuples):
string[2]![1,2] → 1 and 2
string[2]!["1",2] → 1 and 2
string[2]!["1","2"] → 1 and 2
string[2]!["(1)",2] → (1) and 2
string[2]!["[1]",2] → [1] and 2
string[2]!["\"1\"",2] → "1" and 2
(string,string[2])![1,(2,3)] → 1 and the array 2 and 3
(string,string[2])!["1",(2,"3")] → 1 and the array 2 and 3
Simple string:
string!1234 → 1234
string!"1234" → "1234"
string![1234] → [1234]
So there are here 2 differents ways to parse string values.
Are you suggesting that we modify the way simple strings are parsed so that we use the same parsing for all strings (so we add double quote support for simple strings?)?
If yes, the issue is : we are changing the standard, and it could break existing web3:// URLs.
Or were you thinking about other inconsistencies?



 BoxChen:

Make a pr to fmt code use go fmt by nishuzumi · Pull Request #2 · web3-protocol/web3protocol-go · GitHub


Thanks! Will merge.

Author: BoxChen
Date: 2024-08-05T12:13:31.478Z

Hi @nand
I understand. I completely agree with your approach. I will add a parsing method to the string type to support both formats simultaneously. Thank you for your guidance.

Author: nand
Date: 2024-09-13T13:27:54.010Z

Hi!
I have a caching proposal :
Problem :
RPC calls made by the web3:// client are often rate-limited, and in case of use of commercial RPC offerings, incurs a cost. This is especially important for HTTPS gateways.
Idea :
In Resource request mode, the smart contract answering a request can output an ETag header, from the standard HTTP caching mechanism ( HTTP caching - HTTP | MDN ). In normal HTTP, with this ETag mechanism, the client which request again the same page use the If-None-Match: [ETagPreviously received] header: the server returns 304 Not Modified is the content has not changed.
Since request headers are not forwarded to the smart contract in resource request mode (and anyway we want to avoid extra calls to RPCs), we could have the following solution :

After having requested a page, the web3:// client reads the response ETag (if any), and maintain a mapping of (chain id, smart contract address, URL) => ETag.
The smart contract emit a to-be-standardized event, such as ETagClear(string[]) and ETagClearAll(), when the content on pages change, e.g. ETagClear(["/path", "/path2"]), and  ETagClearAll() when clearing the whole smart contract cache.
The web3:// client listen for these events, and clear their internal (chain id, smart contract address, URL) => ETag mapping accordingly.
When the web3:// client is being asked to fetch a page with the If-None-Match: header, it checks its internal (chain id, smart contract address, URL) => ETag mapping. If it is matching, it returns a 304 Not Modified (and avoid RPC calls).

So this is the responsability of the smart contract to emit an ETag header when it thinks it is relevant, and to emit the events to clear the cache at the correct places.
If the web3:// client does not implements mechanism, the website works as of right now without cache.
Do you have feedback on this?

Author: qizhou
Date: 2024-09-16T19:37:01.564Z

Interesting idea!  The caching idea is reasonable.  In addition, using EVM events to invalidate cache is efficient, especially since it is friendly for a client that runs a light client of Ethereum.
One question is how this works with existing HTTP caching such as Cache-Control?

Author: nand
Date: 2024-09-19T06:14:29.385Z

Thanks!
It works well because the ETag and Cache-Control tags are defined together in RFC9111 (HTTP Caching) and RFC9110 (HTTP Semantics), and what the proposal is doing is plugging a hole of HTTP caching for web3://.
A good comparaison is :
In traditional HTTP, we have the scenario of a server, a proxy (CDN, varnish, …) and the browser. The browser query the server through the proxy.
With a request response, the server and proxy emits instructions with the Cache-Control tag (accompagnied with Etag and some more).
With a request, the browser and proxy query cache update with If-None-Match and If-Modified-Since.
In web3://, it’s like the above, but the server is the smart contract, the web3:// client software (web3protocol-go, web3protocol-js) is the proxy.
What is currently broken is that with a request, the proxy (web3:// client) cannot query the server (smart contract) for cache update with If-None-Match and If-Modified-Since, because the Resource Request mode do not support HTTP headers.
The proposal is fixing this broken link : the proxy (web3:// client) pre-emptively collect cache invalidations by listening to blockchain events.
The proxy (web3:// client) then can start as a traditional HTTP proxy cache, which can be configured for both being a private cache (web3:// client used by a browser) or a shared cache (web3:// client used by an HTTPS proxy).
So, for a shared cache scenario, we can cache the body of web3:// requests, and once a web3:// website using ETags has been queried by the proxy once, then the proxy will never query the RPC again until the smart contract emit a cache invalidation : that’s a huge saving of RPC calls.
Finally, to support both ETags and time-based caching (max-age), and to be more general, the events may just be PathContentUpdated([]string): indicators that the content for a path has changed.

Author: nand
Date: 2024-09-20T14:23:09.614Z

Ok here is a draft of an ERC, which still need some work.
I unfortunately end up with a situation where I need an extra flag just to ensure that web3:// clients implementing this ERC does not end up serving infinite stale content from resource requests website doing standard HTTP caching without knowing this ERC.
I’ll try to think about solutions, but well, that’s not too big a drawback.
Edit: I managed to make the flag fit in a more proper manner, as an RFC 9111 (HTTP cache) section 5.2.3 extension directive.
Let me know if you have feedback  thanks!

Author: TechnicallyWeb3
Date: 2024-09-22T22:48:49.753Z

Hey, I’ve been working on this for a while now… I call this the Web3 Transfer Protocol but found web3:// fails in some browsers due to the number in the protocol. I had to use web:// in our proof of concept for this reason. We’re planning on switching to wttp://
You can check out the browser project which we forked from minbrowser as our proof of concept on our GitHub technicallyweb3/min-web and our contract at /web-contract. The web contract itself is a transferrable file and token store which allows our modified browser to render the content.

Author: TechnicallyWeb3
Date: 2024-09-22T22:51:29.557Z

Oh and if you do decide to build the latest version of our browser you can check out the contracts deployed to web://web4calculator.eth or web://technicallyweb3.eth to see some react projects which we deployed to Polygon.

Author: qzhodl
Date: 2024-09-23T02:23:20.720Z

Great job! I’m curious about the exact reason why web3:// fails due to the number. Additionally, Nand has developed a web browser that can handle native web3:// URLs: GitHub - web3-protocol/evm-browser: Web browser with support of the ERC-4804 / ERC-6860 web3:// protocol, which can show on-chain websites hosted on Ethereum and all others EVM chains.

Author: TechnicallyWeb3
Date: 2024-09-23T02:28:18.524Z

Could have been a weird bug in minbrowser, I should definitely bring up the bug report in their repo to get to the bottom of it. Could be minbrowser, chromium or electron. Our team just decided to use only letters in case this was an issue in any other browsers since we hope to add extensions to enable this functionality on other browsers. I’ll look into the Nand browser! Thanks for the link!

Author: nand
Date: 2024-12-15T13:49:25.959Z

Hi!
I am happy ERC-7774 has been merged (still draft), and is now viewable at :

Ethereum Improvement Proposals


ERC-7774: Cache invalidation in ERC-5219 mode Web3 URL
Introduce a new HTTP cache control method using EVM events for invalidation





At its core, it allows ressource request mode websites to use much less RPC calls by signaling changes via EVM events, so that, once initially loaded, a web3:// website no longer require RPC calls.
This will be useful to prevent service disruption (RPC 429 responses, or being blocked, if too much usage), and lower costs (if using a paid RPC provider).
Website creators will be incentivized to use this ERC, because :

It will make it cheaper/more stable to serve its own HTTP mirror
Provider of global HTTP mirrors in the future may apply restrictions to handle heavy traffic, and will look favorably at websites having a low RPC usage
For individual web3:// browser, too much RPC usage could make RPC go 429, and will break the website experience of users.

This spec is implemented (except wildcard in paths) in web3protocol-go, and has been used in OCWebsites (web3://ocweb.eth) in conjunction of the web3gateway.dev HTTPS gateway (which use web3protocol-go).
The result is: Once the cache is warmed up, the only OCWebsite traffic is RPC calls checking for EVM events, otherwise the RPC use is traffic insensitive.
A bit remains to do :
I would like to expose a way for the website to know up to which block the EVM events have been processed. Use case : You submit a tx to edit a page, then you redirect the user to the page : before redirecting, you would want to be sure the change has been taken into account.
A rough idea : a /.well-known/ URL that expose the currently processed blocks of blockchains.
The client can then poll this URL and wait until the user TX block was processed in the web3:// client before redirecting. That way he can ensure the user will see the new version.
The web3:// client MAY use the fetching of this /.well-known/ URL as a signal to speed up the processing of new blocks.

Author: nand
Date: 2024-12-15T13:54:08.055Z

Other news : A nice tool :


github.com




GitHub - web3-protocol/web3protocol-http-gateway-js: An HTTPS gateway for your ERC-4804/6860 web3://...
An HTTPS gateway for your ERC-4804/6860 web3:// website






Just run :
npx web3protocol-http-gateway "web3://ocweb.eth" 

and it will serve web3://ocweb.eth at http://localhost:8080 !
It is like GitHub - ethstorage/web3url-gateway: A gateway implementation of the web3 access protocol (web3://) that can serve HTTP-style Web3 URL for blockchain resource access., except that :

It is only for a specific number of websites (1+), it is not for all websites.
It use the web3protocol-js library instead of web3protocol-go (ERC-7774 not implemented there yet)
It is meant for web3:// website owners to very quickly host their own HTTPS gateway, with their own DNS domain, so easy do https://mydomain.com when having web3://mydomain.eth

Author: frani
Date: 2025-04-14T21:48:11.140Z

any have some idea of unified RPC method with URI schemas som make URL flexibles and easy to call wallets to call actions?
I ve been thinking something like this:
ethereum:<method>[:chainid]?<params>
example of eth_sentTransaction:
in JS you probably will call this action like this:

window.ethereum.request({
  "method": "eth_sendTransaction",
  "params": [
    {
      "from": "0x8082da67710c14e7f668efc73ac27ad6b2d7cafe",
      "to": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
      "gas": "0x76c0",
      "gasPrice": "0x4a817c800",
      "value": "0x0",
      "data": "0xa9059cbb000000000000000000000000ffce4d191cb5007ee9ad7226581f7e217b68cafe00000000000000000000000000000000000000000000000000000000000f4240636166656369746f"
    }
  ]
})

while translating that into URL, can be easily like this
ethereum:eth_sendTransaction:324?from=0x8082da67710c14e7f668efc73ac27ad6b2d7cafe&to=0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238&gas=0x76c0&gasPrice=0x4a817c800&value=0x0&data=0xa9059cbb000000000000000000000000ffce4d191cb5007ee9ad7226581f7e217b68cafe00000000000000000000000000000000000000000000000000000000000f4240636166656369746f

above example is for a single ethereum request, also another option is setup multiple request using base64 encode params like this:
array list of multi request
[
  {
    "method": "wallet_switchEthereumChain",
    "params": [{ "chainId": "0x144" }]
  },
  {
    "method": "eth_sendTransaction",
    "params": [
      {
        "from": "0x8082da67710c14e7f668efc73ac27ad6b2d7cafe",
        "to": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
        "gas": "0x76c0",
        "gasPrice": "0x4a817c800",
        "value": "0x0",
        "data": "0xa9059cbb000000000000000000000000ffce4d191cb5007ee9ad7226581f7e217b68cafe00000000000000000000000000000000000000000000000000000000000f4240636166656369746f"
      }
    ]
  }
]

and keeping previous URL format ( `ethereum:<rpc_method>[:]?[]
and in URL with params in base64
ethereum:multi-request:324?requests_b64=W3sibWV0aG9kIjoid2FsbGV0X3N3aXRjaEV0aGVyZXVtQ2hhaW4iLCJwYXJhbXMiOlt7ImNoYWluSWQiOiIweDE0NCJ9XX0seyJtZXRob2QiOiJldGhfc2VuZFRyYW5zYWN0aW9uIiwicGFyYW1zIjpbeyJmcm9tIjoiMHg4MDgyZGE2NzcxMGMxNGU3ZjY2OGVmYzczYWMyN2FkNmIyZDdjYWZlIiwidG8iOiIweDFjN0Q0QjE5NkNiMEM3QjAxZDc0M0ZiYzYxMTZhOTAyMzc5QzcyMzgiLCJnYXMiOiIweDc2YzAiLCJnYXNQcmljZSI6IjB4NGE4MTdjODAwIiwidmFsdWUiOiIweDAiLCJkYXRhIjoiMHhhOTA1OWNiYjAwMDAwMDAwMDAwMDAwMDAwMDBmZmNlNGQxOTFjYjUwMDdlZTlhZDcyMjY1ODFmN2UyMTdiNjhjYWZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZjQyNDA2MzYxNmY2NjYzNjk3In1dfV0=

Author: frani
Date: 2025-04-14T21:52:42.295Z

This new URL format, with a focus on RPC-based calls, introduces greater flexibility and versatility for real-world QR code usage. By enabling structured and standardized interactions — such as transactions, network switching, and contract calls — it bridges the gap between Web3 and everyday experiences. In many parts of the world where QR codes are already widely used for payments and services, this approach enhances the practical adoption of Web3 technologies.

Author: qizhou
Date: 2025-04-15T10:40:56.797Z

Did you take a look at ERC-681?  ERC-4804 is designed as a http-like URL to locate Etherem resources and the target users would be the ones using browsers.

Author: frani
Date: 2025-04-15T16:55:07.493Z

thanks! I’ve already been investigating a little bit more and create a EIP ( EIP-7924: Ethereum Intent URI (EI-URI): A Universal Action URI format for Ethereum )
kind regrads