Make a pr to fmt code use go fmt by nishuzumi · Pull Request #2 · web3-protocol/web3protocol-go · GitHub
Hi @BoxChen
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.
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?
Thanks! Will merge.
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.
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[])
andETagClearAll()
, when the content on pages change, e.g.ETagClear(["/path", "/path2"])
, andETagClearAll()
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 a304 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?
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
?
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.
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!
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.
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.
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.
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!
Hi!
I am happy ERC-7774 has been merged (still draft), and is now viewable at :
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.
Other news : A nice tool :
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 dohttps://mydomain.com
when havingweb3://mydomain.eth
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=
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.
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.
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