Skip to content

Instantly share code, notes, and snippets.

@sbauch
Created February 23, 2022 16:58
Show Gist options
  • Save sbauch/fc746d796653d15b165832bf0badbfbc to your computer and use it in GitHub Desktop.
Save sbauch/fc746d796653d15b165832bf0badbfbc to your computer and use it in GitHub Desktop.
React input component for getting an NFT's contract address and token ID from popular marketplace URL strings
// Please stop using the OpenSea API to load all of my NFTs.
// It's getting terribly unwieldy the more NFTs I own, and
// I don't want to sift through a needle in a haystack to
// find the NFT I want to select for display etc. You're
// also contributing to the idea that NFTs are centralized,
// plus putting unnecessary load on OS servers.
// Most users though aren't technical enough to understand
// contract addresses and token IDs. So instead of asking
// for those directly, use an input like this where a user
// can paste a link from OpenSea, Rainbow or LooksRare.
import { BigNumber } from 'ethers';
import { getAddress } from 'ethers/lib/utils';
import React, { ReactElement } from 'react';
export type NFT = {
contractAddress: string;
tokenId: BigNumber;
};
const openSea = (url: string): NFT | undefined => {
if (!url.startsWith('https://opensea.io/assets')) return;
const parts = url.split('/');
const [contractAddress, tokenId] = parts.splice(parts.length - 2, 2);
if (/^0x[a-fA-F0-9]{40}$/.test(contractAddress) && /^\d+$/.test(tokenId)) {
return {
tokenId: BigNumber.from(tokenId),
contractAddress: getAddress(contractAddress),
};
}
};
const rainbow = (url: string): NFT | undefined => {
if (!url.startsWith('https://rainbow.me')) return;
const [contractAddress, tokenId] =
new URL(url).searchParams.get('nft')?.split('_') || [];
if (/^0x[a-fA-F0-9]{40}$/.test(contractAddress) && /^\d+$/.test(tokenId)) {
return {
tokenId: BigNumber.from(tokenId),
contractAddress: getAddress(contractAddress),
};
}
};
const looksRare = (url: string): NFT | undefined => {
if (!url.startsWith('https://looksrare.org/collections')) return;
const parts = url.split('/');
const [contractAddress, tokenId] = parts.splice(parts.length - 2, 2);
if (/^0x[a-fA-F0-9]{40}$/.test(contractAddress) && /^\d+$/.test(tokenId)) {
return {
tokenId: BigNumber.from(tokenId),
contractAddress: getAddress(contractAddress),
};
}
};
const RESOLVERS: ((url: string) => NFT | undefined)[] = [
openSea,
rainbow,
looksRare,
];
const nftFromUrl = (url: string): NFT | undefined => {
let resolved: NFT;
let index = 0;
while (!resolved && index < RESOLVERS.length) {
resolved = RESOLVERS[index].call(this, url);
index++;
}
return resolved;
};
const NFTFinder = ({
onChange,
}: {
onChange: (val: NFT) => void;
}): ReactElement => {
return (
<>
<input
onChange={(e) => {
const resolved = nftFromUrl(e.target.value);
resolved && onChange(resolved);
}}
/>
</>
);
};
export default NFTFinder;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment