diff --git a/packages/providers/package.json b/packages/providers/package.json index 3528f3737d..d7f5bfdca8 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -17,6 +17,7 @@ "@ethersproject/abstract-provider": "^5.6.0", "@ethersproject/abstract-signer": "^5.6.0", "@ethersproject/address": "^5.6.0", + "@ethersproject/base64": "^5.6.0", "@ethersproject/basex": "^5.6.0", "@ethersproject/bignumber": "^5.6.0", "@ethersproject/bytes": "^5.6.0", diff --git a/packages/providers/src.ts/base-provider.ts b/packages/providers/src.ts/base-provider.ts index d8e8f849ef..faa7d40a1d 100644 --- a/packages/providers/src.ts/base-provider.ts +++ b/packages/providers/src.ts/base-provider.ts @@ -4,6 +4,7 @@ import { Block, BlockTag, BlockWithTransactions, EventType, Filter, FilterByBlockHash, ForkEvent, Listener, Log, Provider, TransactionReceipt, TransactionRequest, TransactionResponse } from "@ethersproject/abstract-provider"; +import { encode as base64Encode } from "@ethersproject/base64"; import { Base58 } from "@ethersproject/basex"; import { BigNumber, BigNumberish } from "@ethersproject/bignumber"; import { arrayify, concat, hexConcat, hexDataLength, hexDataSlice, hexlify, hexValue, hexZeroPad, isHexString } from "@ethersproject/bytes"; @@ -568,6 +569,16 @@ export class Resolver implements EnsResolver { } } + const skynet = hexBytes.match(/^0x90b2c605([0-9a-f]*)$/); + if (skynet) { + if (skynet[1].length === (34 * 2)) { + // URL Safe base64; https://datatracker.ietf.org/doc/html/rfc4648#section-5 + const urlSafe: Record = { "=": "", "+": "-", "/": "_" }; + const hash = base64Encode("0x" + skynet[1]).replace(/[=+\/]/g, (a) => (urlSafe[a])); + return "sia:/\/" + hash; + } + } + return logger.throwError(`invalid or unsupported content hash data`, Logger.errors.UNSUPPORTED_OPERATION, { operation: "getContentHash()", data: hexBytes diff --git a/packages/tests/src.ts/test-providers.ts b/packages/tests/src.ts/test-providers.ts index 0cd84c9e53..df89c517db 100644 --- a/packages/tests/src.ts/test-providers.ts +++ b/packages/tests/src.ts/test-providers.ts @@ -1405,6 +1405,22 @@ describe("Resolve ENS avatar", function() { }); }); +describe("Resolve ENS content hash", function() { + [ + { title: "skynet", name: "skynet-ens.eth", value: "sia:/\/AQCRuTdTPzCyyU6I82eV7VDFVLPW82LJS9mH-chmjDlKUQ" }, + { title: "ipns", name: "stderr.eth", value: "ipns://12D3KooWB8Z5zTNUJM1U98SjAwuCSaEwx65cHkFcMu1SJSvGmMJT" }, + { title: "ipfs", name: "ricmoo.eth", value: "ipfs://QmdTPkMMBWQvL8t7yXogo7jq5pAcWg8J7RkLrDsWZHT82y" }, + ].forEach((test) => { + it(`Resolves avatar for ${ test.title }`, async function() { + this.timeout(60000); + const provider = ethers.getDefaultProvider("homestead", getApiKeys("homestead")); + const resolver = await provider.getResolver(test.name); + const contentHash = await resolver.getContentHash(); + assert.equal(contentHash, test.value, "content hash"); + }); + }); +}); + describe("Test EIP-2544 ENS wildcards", function() { const provider = (providerFunctions[0].create("ropsten"));