Created
February 23, 2022 16:58
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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