Kevin McMahon


Blog Search

Making Sure OpenSea Can Read Your Contract-level Metadata

Leaving this here for my future self and for others as this question pops up on the OpenSea discord quite a bit.

tl;dr – Don’t return an IPFS URI (ipfs://{cid}) or IPFS HTTP gateway URL ({cid} or{cid}) via the contractURI() function. Use a traditional HTTP web API or base64 encode the metadata JSON and return it from the function if you want OpenSea to be able to read the contract-level metadata and display it on your collection’s page.

OpenSea allows smart contract developers to include storefront-level metadata by implementing a function named contractURI() and returning a URI pointing to the metadata. OpenSea expects metadata formatted as JSON that consists of a few specific attributes they recognize. This information is pre-populated into the NFT’s collections page associated with the smart contract on OpenSea.

For individual non-fungible tokens (NFT) like ERC721’s and ERC1155’s, calling the tokenURI() function with a tokenId value as a parameter returns a URI that points at the token’s metadata. The tokenURI() function typically returns URI that point to traditional endpoints like web servers or cloud storage using conventional URL protocols (https://) or, more commonly in web3, to files stored on IPFS via the IPFS URL protocol (ipfs://). URIs returned from this function can point directly to IPFS or via IPFS HTTP gateways without problems.

It is unclear from the docs, but the responses from the token URI function can vary more than the contract URI function. I have experimented with valid URI variations, all pointing to the same JSON, and had no success with having the contract URI function return either IPFS or IPFS public gateway URIs. Providing the same types of URI from the token URI functions has worked as expected. What I have found to work are the following:

  1. Return the metadata JSON as a base64 encoded string. Do not forget to prepend the string with data:application/json;base64,{yourBase64EncodedStringHere}.

  2. Return a URL pointing to a conventional REST API endpoint that returns the metadata JSON.

I cannot explain why the API requests to a REST API work as expected or why the requests to IPFS or an IPFS public gateway do not. I plan to file this as a ticket with OpenSea, and hopefully, if they’re unable to address the issue outright, they can at least update the docs to be more explicit about what can and cannot be returned from the contract URI function.

Authenticating to Heroku via CLI with MFA Turned On

Leaving this here for my future self.

Heroku has turned off interactive login and pushes folks to authenticate via a browser when authenticating to use the CLI app. This works fine if you don’t have MFA turned on (you should though!) and the flow completes without issue. If you do have MFA turned on, you’ll get a blank screen and a cryptic message (“IP address mismatch”) when attempting to complete the login.

To authenticate from the CLI you can follow this note from the Heroku Developer Docs and put your newly generated API key in a .netrc file or set and environment variable (HEROKU_API_KEY) or just enter the API key to the password prompt when interacting with the CLI.

➜  ~ heroku auth:login -i
heroku: Enter your login credentials

Logged in as [YOUR_EMAIL_HERE]

Carvey Replacement Hinges

The internet is almost as impressive as my ability to break things. This is a story about how I broke a CNC machine and was able to not only find the exact replacement parts but order them for next day delivery within about 20 minutes.


The Inventables Carvey model I am using uses Southco E6-10-301-20 Series Adjustable Torque Position Control Hinge with Holes.

Southco E6-10-301-20 Series Adjustable Torque Position Control Hinge with Holes (PDF)

Amazon Link

What Happened

Recently a friend let me borrow a Carvey that was taking up space at his place and, not 10 mins after getting it powered up, I broke it. To make a long story short, I racked the lid when attempting to pick it up, which caused both hinges to fail catastrophically. The hydraulic lift, which props the lid open and provides a soft close, put a tremendous amount of pressure on the device’s plastic hinges. Once the first hinge failed, the second failed immediately. It felt like my heart was going to be next.

After calling the very understanding owner and apologizing for destroying the hinges, we discussed the steps necessary for repair. Inventables support is great. I’m sure I could’ve got replacement hinges from them. But that would take phone calls, support tickets, and waiting for them to ship one-off parts. The parts are just hinges. If we could get replacements, it is a simple process to affix them to the case. Maybe we can find replacements ourselves.

So the search began. After coming up empty via the search engine route, McMaster-Carr was the next stop. It turns out there are tons of different hinges. McMaster-Carr apparently has all of them. We were however able to find something that looked promising. With the specs of the McMaster-Carr hinge now in hand, I got my calipers out. The sizes matched (give or take a ten-thousandth of an inch). We felt good about having a viable replacement option, but the question lingered if we could do better.

After a closer inspection of the broken hinges, I noticed that they had Southco branding. A quick search of their site led us to the spec sheet of the Southco E6-10-301-20. That was it, and of course, Amazon has it stocked and ready to ship.

The fact that I was able to identify these hinges, source them from a supplier, order a small number of them, and have them shipped to my door in two days is amazing. That I was able to do it within 20 minutes after I broke them blows my mind—what a world.

Favorites from September 2020

A collection of some of my favorite links, images, tweets and quotes from September 2020. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.

via wendy macnaughton on Instagram: “Art.”


Favorites from August 2020

A collection of some of my favorite links, images, tweets and quotes from August 2020. This is not an exhaustive list but does captures some things I found interesting, thought-provoking, or cool over the past month.

Nostalgia is a helluva drug.

This blue box is the last thing in the world that I thought our democracy would hinge on.







“A bad system will beat a good person every time.” W. Edwards Demming

via @marshallk

“The optimal strategy might be executing a suboptimal plan at a fast pace. Strategy evolves as lessons are learned—and the person who moves faster, learns faster. Learning is a marathon and perfection is a weighted vest.” – @JamesClear