Skip to content

Commit

Permalink
Add support for IPFS metadata imageUrl in getAvatar (#2426).
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed Dec 24, 2021
1 parent 2f57c6a commit 3d6a7ec
Showing 1 changed file with 27 additions and 9 deletions.
36 changes: 27 additions & 9 deletions packages/providers/src.ts/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,11 @@ export interface Avatar {
linkage: Array<{ type: string, content: string }>;
}

const matcherIpfs = new RegExp("^(ipfs):/\/(.*)$", "i");
const matchers = [
new RegExp("^(https):/\/(.*)$", "i"),
new RegExp("^(data):(.*)$", "i"),
new RegExp("^(ipfs):/\/(.*)$", "i"),
matcherIpfs,
new RegExp("^eip155:[0-9]+/(erc[0-9]+):(.*)$", "i"),
];

Expand All @@ -264,6 +265,10 @@ function _parseBytes(result: string): null | string {
return hexDataSlice(result, offset + 32, offset + 32 + length);
}

// Trim off the ipfs:// prefix and return the default gateway URL
function getIpfsLink(link: string): string {
return `https:/\/gateway.ipfs.io/ipfs/${ link.substring(7) }`;

This comment has been minimized.

Copy link
@githubdoramon

githubdoramon Jan 11, 2022

@ricmoo just realized that the gateway seems to have a TERRIBLE performance when compared to simply using ipfs.io/ipfs

Any strong reasons for using the gateway?

This comment has been minimized.

Copy link
@ricmoo

ricmoo Jan 11, 2022

Author Member

I thought the gateway was the official way? Can you send any documentation on using not-the gateway? Do the CORS headers works property?

This comment has been minimized.

}

export class Resolver implements EnsResolver {
readonly provider: BaseProvider;
Expand Down Expand Up @@ -402,7 +407,7 @@ export class Resolver implements EnsResolver {
}

async getAvatar(): Promise<null | Avatar> {
const linkage: Array<{ type: string, content: string }> = [ ];
const linkage: Array<{ type: string, content: string }> = [ { type: "name", content: this.name } ];
try {
// test data for ricmoo.eth
//const avatar = "eip155:1/erc721:0x265385c7f4132228A0d54EB1A9e7460b91c0cC68/29233";
Expand All @@ -411,8 +416,8 @@ export class Resolver implements EnsResolver {

for (let i = 0; i < matchers.length; i++) {
const match = avatar.match(matchers[i]);

if (match == null) { continue; }

switch (match[1]) {
case "https":
linkage.push({ type: "url", content: avatar });
Expand All @@ -424,7 +429,7 @@ export class Resolver implements EnsResolver {

case "ipfs":
linkage.push({ type: "ipfs", content: avatar });
return { linkage, url: `https:/\/gateway.ipfs.io/ipfs/${ avatar.substring(7) }` }
return { linkage, url: getIpfsLink(avatar) };

case "erc721":
case "erc1155": {
Expand Down Expand Up @@ -471,19 +476,32 @@ export class Resolver implements EnsResolver {
// ERC-1155 allows a generic {id} in the URL
if (match[1] === "erc1155") {
metadataUrl = metadataUrl.replace("{id}", tokenId.substring(2));
linkage.push({ type: "metadata-url-expanded", content: metadataUrl });
}

// Get the token metadata
const metadata = await fetchJson(metadataUrl);
if (!metadata) { return null; }
linkage.push({ type: "metadata", content: JSON.stringify(metadata) });

// Pull the image URL out
if (!metadata || typeof(metadata.image) !== "string" || !metadata.image.match(/^(https:\/\/|data:)/i)) {
return null;
let imageUrl = metadata.image;
if (typeof(imageUrl) !== "string") { return null; }

if (imageUrl.match(/^(https:\/\/|data:)/i)) {
// Allow
} else {
// Transform IPFS link to gateway
const ipfs = imageUrl.match(matcherIpfs);
if (ipfs == null) { return null; }

linkage.push({ type: "url-ipfs", content: imageUrl });
imageUrl = getIpfsLink(imageUrl);
}
linkage.push({ type: "metadata", content: JSON.stringify(metadata) });
linkage.push({ type: "url", content: metadata.image });

return { linkage, url: metadata.image };
linkage.push({ type: "url", content: imageUrl });

return { linkage, url: imageUrl };
}
}
}
Expand Down

0 comments on commit 3d6a7ec

Please sign in to comment.