feat: support Swarm and IPNS ENS contenthashes
This commit is contained in:
parent
86bc8a894b
commit
1122b33ff8
|
@ -14,8 +14,9 @@ const AUTH_METHODS = toHashSet(["eth_accounts", "eth_coinbase", "eth_sendTransac
|
||||||
const SIGN_METHODS = toHashSet(["eth_sign", "personal_sign", "eth_signTypedData", "eth_signTypedData_v3"])
|
const SIGN_METHODS = toHashSet(["eth_sign", "personal_sign", "eth_signTypedData", "eth_signTypedData_v3"])
|
||||||
const ACC_METHODS = toHashSet(["eth_accounts", "eth_coinbase"])
|
const ACC_METHODS = toHashSet(["eth_accounts", "eth_coinbase"])
|
||||||
|
|
||||||
const IPFS_SCHEME = "https"
|
const HTTPS_SCHEME = "https"
|
||||||
const IPFS_GATEWAY = ".infura.status.im"
|
const IPFS_GATEWAY = ".infura.status.im"
|
||||||
|
const SWARM_GATEWAY = "swarm-gateways.net"
|
||||||
|
|
||||||
const base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
const base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
@ -279,15 +280,21 @@ QtObject:
|
||||||
self.status.permissions.clearPermissions()
|
self.status.permissions.clearPermissions()
|
||||||
|
|
||||||
proc ensResourceURL*(self: Web3ProviderView, ens: string, url: string): string {.slot.} =
|
proc ensResourceURL*(self: Web3ProviderView, ens: string, url: string): string {.slot.} =
|
||||||
# TODO: add support for swarm: "swarm-gateways.net/bzz:/...." and ipns
|
|
||||||
|
|
||||||
let contentHash = contenthash(ens)
|
let contentHash = contenthash(ens)
|
||||||
if contentHash == "": # ENS does not have a content hash
|
if contentHash == "": # ENS does not have a content hash
|
||||||
return url_replaceHostAndAddPath(url, url_host(url), IPFS_SCHEME)
|
return url_replaceHostAndAddPath(url, url_host(url), HTTPS_SCHEME)
|
||||||
|
|
||||||
let decodedContentHash = contentHash.decodeContentHash()
|
let decodedHash = contentHash.decodeENSContentHash()
|
||||||
let base32Hash = base32.encode(string.fromBytes(base58.decode(decodedContentHash))).toLowerAscii().replace("=", "")
|
case decodedHash[0]:
|
||||||
result = url_replaceHostAndAddPath(url, base32Hash & IPFS_GATEWAY, IPFS_SCHEME)
|
of ENSType.IPFS:
|
||||||
|
let base32Hash = base32.encode(string.fromBytes(base58.decode(decodedHash[1]))).toLowerAscii().replace("=", "")
|
||||||
|
result = url_replaceHostAndAddPath(url, base32Hash & IPFS_GATEWAY, HTTPS_SCHEME)
|
||||||
|
of ENSType.SWARM:
|
||||||
|
result = url_replaceHostAndAddPath(url, SWARM_GATEWAY, HTTPS_SCHEME, "/bzz:/" & decodedHash[1] & "/")
|
||||||
|
of ENSType.IPNS:
|
||||||
|
result = url_replaceHostAndAddPath(url, decodedHash[1], HTTPS_SCHEME)
|
||||||
|
else:
|
||||||
|
warn "Unknown content for", ens, contentHash
|
||||||
|
|
||||||
proc replaceHostByENS*(self: Web3ProviderView, url: string, ens: string): string {.slot.} =
|
proc replaceHostByENS*(self: Web3ProviderView, url: string, ens: string): string {.slot.} =
|
||||||
result = url_replaceHostAndAddPath(url, ens)
|
result = url_replaceHostAndAddPath(url, ens)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import transactions
|
||||||
import algorithm
|
import algorithm
|
||||||
import web3/[ethtypes, conversions], stew/byteutils, stint
|
import web3/[ethtypes, conversions], stew/byteutils, stint
|
||||||
import libstatus/eth/contracts
|
import libstatus/eth/contracts
|
||||||
|
import chronicles, sequtils, httpclient, libp2p/[multihash, multicodec, cid]
|
||||||
|
|
||||||
const domain* = ".stateofus.eth"
|
const domain* = ".stateofus.eth"
|
||||||
|
|
||||||
|
@ -253,3 +254,50 @@ proc setPubKey*(username, pubKey, address, gas, gasPrice, password: string, succ
|
||||||
|
|
||||||
proc statusRegistrarAddress*():string =
|
proc statusRegistrarAddress*():string =
|
||||||
result = $contracts.getContract("ens-usernames").address
|
result = $contracts.getContract("ens-usernames").address
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
ENSType* {.pure.} = enum
|
||||||
|
IPFS,
|
||||||
|
SWARM,
|
||||||
|
IPNS,
|
||||||
|
UNKNOWN
|
||||||
|
|
||||||
|
proc decodeENSContentHash*(value: string): tuple[ensType: ENSType, output: string] =
|
||||||
|
if value == "":
|
||||||
|
return (ENSType.UNKNOWN, "")
|
||||||
|
|
||||||
|
if value[0..5] == "e40101":
|
||||||
|
return (ENSType.SWARM, value.split("1b20")[1])
|
||||||
|
|
||||||
|
if value[0..7] == "e3010170":
|
||||||
|
try:
|
||||||
|
let defaultCodec = parseHexInt("70") #dag-pb
|
||||||
|
var codec = defaultCodec # no codec specified
|
||||||
|
var codecStartIdx = 2 # idx of where codec would start if it was specified
|
||||||
|
# handle the case when starts with 0xe30170 instead of 0xe3010170
|
||||||
|
if value[2..5] == "0101":
|
||||||
|
codecStartIdx = 6
|
||||||
|
codec = parseHexInt(value[6..7])
|
||||||
|
elif value[2..3] == "01" and value[4..5] != "12":
|
||||||
|
codecStartIdx = 4
|
||||||
|
codec = parseHexInt(value[4..5])
|
||||||
|
|
||||||
|
# strip the info we no longer need
|
||||||
|
var multiHashStr = value[codecStartIdx + 2..<value.len]
|
||||||
|
|
||||||
|
# The rest of the hash identifies the multihash algo, length, and digest
|
||||||
|
# More info: https://multiformats.io/multihash/
|
||||||
|
# 12 = identifies sha2-256 hash
|
||||||
|
# 20 = multihash length = 32
|
||||||
|
# ...rest = multihash digest
|
||||||
|
let multiHash = MultiHash.init(nimcrypto.fromHex(multiHashStr)).get()
|
||||||
|
return (ENSType.IPFS, $Cid.init(CIDv0, MultiCodec.codec(codec), multiHash))
|
||||||
|
except Exception as e:
|
||||||
|
error "Error decoding ENS contenthash", hash=value, exception=e.msg
|
||||||
|
raise
|
||||||
|
|
||||||
|
if value[0..8] == "e50101700":
|
||||||
|
return (ENSType.IPNS, parseHexStr(value[12..value.len-1]))
|
||||||
|
|
||||||
|
return (ENSType.UNKNOWN, "")
|
||||||
|
|
|
@ -49,7 +49,13 @@ Rectangle {
|
||||||
var host = _web3Provider.getHost(url);
|
var host = _web3Provider.getHost(url);
|
||||||
if(host.endsWith(".eth")){
|
if(host.endsWith(".eth")){
|
||||||
var ensResource = _web3Provider.ensResourceURL(host, url);
|
var ensResource = _web3Provider.ensResourceURL(host, url);
|
||||||
urlENSDictionary[_web3Provider.getHost(ensResource)] = host;
|
|
||||||
|
if(/^https\:\/\/swarm\-gateways\.net\/bzz:\/([0-9a-fA-F]{64}|.+\.eth)(\/?)/.test(ensResource)){
|
||||||
|
// TODO: populate urlENSDictionary for prettier url instead of swarm-gateway big URL
|
||||||
|
return ensResource;
|
||||||
|
} else {
|
||||||
|
urlENSDictionary[_web3Provider.getHost(ensResource)] = host;
|
||||||
|
}
|
||||||
url = ensResource;
|
url = ensResource;
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
|
|
Loading…
Reference in New Issue