New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Loading player…

Rendering Onchain: Experiments, Techniques, and Getting Started with Onchain NFT Metadata

ETHGlobalMon, Oct 9, 2023, 12:00 AM

Join nnnnicholas for a talk titled "Rendering Onchain: Experiments, Techniques, and Getting Started with Onchain NFT Metadata". Welcome to back to ETHGlobal Waterloo, where it all began! Returning to Canada's tech hub, we're thrilled to bring together international enthusiasts and local talent for an unforgettable hackathon experience. This year we had 650+ attendees from 29 different countries and 47% were new to Web3! We concluded the weekend with 168 projects submitted and gave away $250,000+ in prizes ----------------- Follow us: https://twitter.com/ETHGlobal​ Check us out: https://ethglobal.co​m Email us at: hello@ethglobal.com

Transcript

foreign [Music] hello my name is Nicholas and today I'm going to be telling you about my Adventures rendering svgs on chain as I'm going to be showing you some experiments that I did some techniques and lessons that I learned along the way and giving you uh some like a repo that'll be really useful if you want to do some on-chain SVG maybe even during this hackathon so thank you for coming so this project started when I decided that I wanted to give Juicebox nfts metadata uh maybe show of hands do people in here know what juice boxes have you ever heard of it one two three oh hey before um so for people who don't know Juice Box isn't immutable and open source protocol on ethereum it lets anyone permissionlessly issue tokens in exchange for contributions to treasuries and those treasuries are called juice boxes because everything is on chain prospective contributors can diligence the juice boxes parameters before they interact with it so before you make a donation to a project you can discover uh who controls it how are they going to spend the money is the token issuance stable or will it change over time and can I get a refund if I decide I want to quit the project these kinds of on-chain um uh features are enabled by being an on chain protocol there's over a thousand projects on Juicebox already some of them are very big and famous Constitution Dao Assange Dao spiced out others are smaller at many small Charities for instance Marin County swim Association is a local charity in Marin supporting uh youth access to uh to Aquatic Sports there's also some open source projects that are developing business models on the blockchain with blockchain revenues uh one interesting one is planetable which is an IP Mac application for creating ipfs locally hosted blogs so it's a bit of a background on Juicebox the reason I mention this is because each juice box project is represented by an nft uh the owner of that nft is able to configure the Juicebox project and by this mechanism juice boxes are composable with all kinds of governance and Management Systems so for instance URI could create a juice box and hold it in our metamask rainbow or other eoa wallet and control it that way we could pass it to a gnosis safe and have a multi-sig govern the project we could give it to an on-chain governance protocol like open Zeppelin Governor or compound governor we could put it into a specifically designed contract or we could burn the ownership of the project altogether by sending the nft to the burn address so by having access controls over the project controlled by an nft it's composable with any form of future smart wallet or eoa Etc the problem is that uh before I started this project these nfts had no metadata so when you go to the collection on openc or other marketplaces or if you go and check out these nfts on etherscan or using whatever kind of uh interface you choose they have no metadata or they didn't at least at the start of this project so when you ping this token URI function it returned nothing an empty string so I decided to solve this by creating some metadata contracts that would bring life to the protocol visually and through structured metadata properties and so I embarked on this project and I'm going to tell you about that during what I learned and I'll give you some resources so that you can uh check it out on your own and make your own svgs integrate them into your own projects so the there were two goals for this project when I set out the first was to render project data to nfts visually uh the idea uh essentially I wanted to surface live blockchain data from the status of these treasuries how much eth is inside of them how many tokens have been issued against these projects Etc to emphasize the unchaineness of the projects I wanted to visualize that directly in the image without a recourse to ipfs or any kind of https hosted metadata I wanted to do it entirely on chain uh the second thing that I wanted to do was maintain the ethos of project sovereignty that we have at Juice Box uh the juice box contracts are all immutable while we do release upgrades it's up to a project owner to choose if they would like to apply that upgrade and no upgrades are applied like pushed to the projects themselves so I wanted to carry that ethos through to the metadata so I wanted to simultaneously in the first goal provide some kind of visual information related to their on-chain status live analytics metrics about the project and also allow people to opt out and have their own metadata if they prefer if they're willing to write their own metadata contract so what's so interesting about on chain metadata anyway there's many cool things uh and the ones that stick out to me are uh first of all that we avoid having off-chain dependencies like ipfs which often require using a service like infuria or um uh pinata which are centralized services that do the pinning for you alternately you can do it yourself but uh with the consequences of the the metadata being served quite slowly if you're hosting it on your own machine or on a single instance on AWS Etc um another cool thing about on-chain uh metadata is that it allows you to compose with other contracts on chain the uis that are generated with on-chain data are also provably accurate and censorship resistant they're permanently hosted they don't depend on anything off chain and uh most of all I think visualization is like a first step on this journey towards a hypothetical future that a lot of people are excited about where nfts begin to merge with apps where nfts allow you to not only surface data from the blockchain but also enable interactivity finally it's just fun and an interesting experiment to do things on chain so the first step in this project was to visualize protocol data the protocols data in an SVG and I began with the aesthetic question of what should these things look like so I sought to take aesthetic inspiration from these uh very uh exciting I don't know enigmatic um see a lot old school CRT CLI interfaces with this orange glowing feel to them and I took that inspiration into figma where I designed an SVG there's many choices of where you I so I guess I should preface this by saying I decided to take a path of creating uh watching SVG specifically because it suited the requirements for the project um so I found inspiration in these uh old images of CRTs and I took it into figma to begin designing I made the choice early on to do a to use a mono spaced font in order to be able to do the layout uh on a row by row basis here I'm showing some iterations on the design from figma um and the reason I chose a monospace font is because it allowed me to deal with the uh variable length of the data that I was going to be fetching from the protocol that varies between all the different projects makes it easier to to think about um so I prototyped this in figma and there are many different tools that you could use originally I started with inkscape uh in my past life I worked in a digital fabrication lab where inkscape is a open source SVG editing tool that's very cool and I highly suggest however inkscape generates quite ugly uh svgs if you actually look at the text of the XML so I ended up switching to figma which generates cleaner svgs nevertheless one lesson to take away from this is if you are planning to do on-chain rendering you will have to go and manually edit the SVG even if you get it from an application like figma because it adds all kinds of craft that you don't really need on shading Additionally you should confirm early as early as possible in the process earlier than I did that all of the effects and styles that are being applied by your SVG editor of choice are going to be represented uh similarly across all browsers so for instance I had problems with I decided to use the glow effect in figma and when I brought this into my solidity contract and started playing with the actual files it turns out that in Safari the glow effect is a style that is not supported currently moreover uh the uh the way that they deal with white space like multiple spaces in a row uh was it was uh it wasn't displaying correctly so I had to deal with these issues later so I suggest early on in your process when you're moving from your prototyping stage into your solidity quickly check that it's working properly in all browsers that you expect to be uh to be viewed in at least so how do we actually write the contract uh so I've taken some Snippets out of the contract I don't want to bore you with too much technical detail so we're I'm just going to get to the the core functionality that I had to implement in the contract and how it works I decided to use not only a monospaced font but actually a font that is on chain uh there's a developer another contributor at juice box down named peripheralist who created an nft project called capsules which you can check out at cpsls.app and this is an nft project and as a part of it he created his own font and deployed it to the blockchain so you can ping his contract and it will return a base64 encoded string of each of the font weights for this typeface that he created so in the first section of this slide what I'm showing is the code that goes and fetches that uh basically for encoded string representation of the 500 weight font from his contract once we have that in the contract it's time to go and collect all the data from the Juicebox protocol to grab all the treasure information about a given project and and just to give you some context these uh this code will be executed when openc or whatever Marketplace or other browser goes and fetches the token URI from the nft contract so so we're creating the possibility to generate the SVG that we ultimately want to return here so once we collect the Juicebox data um which takes uh quite a few uh calls to many different contracts to go and explore because the projects can have different uh treasury configurations they might be interacting with different projects this is quite an involved process once we have the treasury information and the typeface we can begin concatenating this into one big SBG this is a very um dense function that uh really does need to be broken up into many smaller functions so if you are planning to create an on-chain SVG or any other kind of on-chain XML or you know HTML something else I highly suggest that you break it into functional pieces into the smallest functions possible because you will hit a stack too deep error very quickly if you're concatenating and creating something really large especially the string concatenation causes stackady bearers uh frequently so the first lesson is to break it break your on-chain SVG creation if it is complex uh into multiple functions to avoid stack to deep errors um also avoid the temptation to use via IR via IR is a function in any compiler but vir is what it's called in uh it's a flag it's what is called in forage what it does is essentially instead of compiling your solidity directly it uh compiles it to an intermediate representation where it can squeeze out some additional efficiency this is cool because it means if you're getting a stack too deep error because your function is too long and you have too many variables in memory via IR will compress them and allow you to get away with uh you know a less than efficient function however the IR is slower to run in test so it will slow down your development process it also makes tracing errors very difficult because the errors will correspond to the intermediate representation code rather than to the solidity that you wrote so it will be difficult to find where the problems are in your code finally etherscan verification at least at the time when I was deploying these contracts did not allow you to verify a contract compiled with via IR so you may do the entire project and everything is working and then you go to verify your contract on etherscan and it doesn't work which can be quite disappointing next you have to test what you're doing as you're developing and implementing the uh code that you did the imagery that you've developed in your visual mock-up you need to test and see that it's actually working and there's many good solutions for this one of the most exciting ones is a project called hot chain SVG by a developer named winter which gives you hot reloading svgs so essentially you have your solidity code you save and it immediately refreshes a browser window with the changes that you've implemented this is very cool feels like developing react for example however it doesn't support mainnet forking and for me this was very important because the contract that I was working on had to interact with several protocols namely ens many many Juice Box contracts as well as existing projects and this typeface it would be too complicated and time consuming to redeploy each of those protocols inside of my test environment as well as populate each of those protocols with example projects and cover all the potential use cases for those projects to get representative sample when testing so I decided to pursue a mainnet forking strategy which meant that I couldn't use this hot chain SPG project if your project doesn't have that requirement then I encourage you to check out hotchain SVG for me because I needed to do mainnet forking I had to develop something of my own and I turned to a friend of mine from Montreal of kanu who created an ffi script ffi is a function in Forge that allows you to call JavaScript and other software on your computer during a test so uh in on this slide I'm showing you the JS that runs every time I run a test where I want to visualize the output where that I'm rendering and what this essentially means is you call Forge test Dash Dash ffi and it will uh instantiate the contract run the test then take the output from your token URI function save it as an SVG on your file system and open it in your SVG your default SVG application which for me is the browser so basically you hit test and suddenly Brave pops open with the SVG right there this is very cool and yeah if you're planning if you need to do main networking feel free to grab this code everything's open source of course so hey it works uh we've got a contract now that is able to render these images these svgs which are representing live on-chain data so uh what are these things showing us so in the top left you can see we have the project handle which is um a contract that connects juice box to ens these are ens names uh we also can see the cycle number which is to say how far along we are in the Project's life as well as how much time is left in the current cycle we have the balance of the project how much eth is inside of it are there any payouts scheduled if so the the value that's scheduled is there as well as the total outstanding excuse me the total outstanding token Supply and the address of the project owner abbreviated so that it fits into the space there one thing that you can't see here is that actually the project name the juice box uh emoticon and the project owner address Are all uh a tags which do work inside of svgs you can use some HTML tags inside of svgs in openc uh there's and we'll talk about this a little bit more in a second openc serves cached versions of any on-chain um uh metadata and so in openc for security reasons and because they're serving uh PNG cash uh you can't click they don't those links don't work uh however if you were to render this on your own site you could click those links and for instance if you click jigglyjams it'll take you to the Jiggly Jams project so I also wanted to let people um Express their uh attitude of their project through color and so I also included in this contract uh a theming system which is a mapping of the of project ID to theme struct and a theme struct just contains three hex values four colors which I concatenate into the token URI if they have been set um yeah so uh we covered the first uh aspect the first goal which was to provide the default metadata for every project but I realized as the project went on that I didn't want to be didactic and I wanted to let people create their own metadata if they prefer in the spirit of the protocol so the second goal was to let any project choose to replace the metadata with their own contract I chose a registry architecture to achieve this so um project owners can decide if they want to set their own metadata contract and if they don't we serve the default metadata that I just showed you previously if they do choose to set their own metadata when uh openc or a user goes to grab the token URI from the contract it will check have they set a custom contract if not serve that orange or customized color default metadata if they have serve the metadata from their contract it's pretty simple it's just a mapping but it is effective this registry also allows us to create sophisticated contracts that are not intended to be the metadata for a single project but even metadata for multiple projects so to demonstrate this I created another metadata renderer this one allows you any project owner to set for their project uh ipfs https R weave or other string that where a Json can be fetched that uh you know it populates the metadata of that project so for this example I created this contract that lets you set a custom ipfs CID for your project and here it's pulling up a picture from ipfs for this particular project so we're not strictly stuck in on-chain metadata with this registry design you can also have off-chain metadata if you prefer finally don't forget to refresh your caches if you're doing on-chain metadata one thing you need to be careful of is as I mentioned earlier openc and other providers and many dapps that rely on openc for uh fetching metadata uh it can fall out of date and if you're familiar with nfts you're familiar with clicking refresh metadata on the open C page that's fine but if the whole purpose is to demonstrate a live metadata then you need to have some kind of solution for this there are uh there is an EIP ERC 4906 that lets an nft contract emit an event and openc and other indexers listen for those events and if they hear it they refresh the metadata cache because some change has happened however 4906 only works in the context where the metadata is changing due to a contract interaction on the nft contract itself but if your nft contract is pointing to another contract that renders your metadata events on that contract will not tell openc to change to update their cache and so 4906 is useful if all of your metadata being rendered inside of her contract and if it only changes when someone executes a transaction in this case that's not how it works because the time is always ticking down in the uh in the time left in the current cycle for example so to solve this I wrote a in typescript I wrote a process uh that runs in a pm2 on a VPS uh that goes and fetches all the token IDs what is the number of IDs in the nft contract and tells uh openc to update each one one after another ideally this is made obsolete in the future by openc uh supporting an API endpoint where you can have uh you know just tell them one time update the whole collection so far that's not the case so if you have this problem you can also go and steal this repo uh and and maybe it'll be useful for you uh once the metadata rendering was complete for the Juicebox protocol I decided it would be fun as a stretch goal to make these things collectible because as I mentioned these nfts for the juice box nfts represent ownership of a juice box and so not everyone can have them and you can't sell them because that nft is the ownership of the project and so you probably want that in a in a multi-sig or in an on-chain governance contract so how are people actually going to see this metadata that you've spent so much time creating my solution was to create uh something called Juicebox stock cards this is an 1155 open Edition contract uh with a very low mint price when someone mints one of these cards they receive an 1155 in their wallet the proceeds go to the project in question and uh the metadata for this 1155 open Edition is simply a reference to the Juicebox Project's own metadata so as a consequence essentially these open editions are like little Billboards that can be in your followers wallets in their rainbow wallet they can check the status of the project by having an open Edition that has the exact same metadata as the project itself so you can make your own metadata too and I thought it would be nice if I uh provided something to get you started uh so you don't just have my project as an example uh here are a few links uh the first one I think is the most interesting one it allows you it's essentially a forge solidity repo where if you download it install the dependencies by calling Forge install and yarn install uh with the instructions are in the readme and then hit uh Forge test dash dash ffi you'll immediately have an SVG rendered from solidity in your browser so I think we have a few minutes so maybe I can actually demonstrate that uh actually before I do I'll just explain the other links uh so the first one is this uh SVG uh demo repo that I'll show you the second one is a boilerplate if you wanted to write your own metadata contract that's compatible with the Juicebox contracts that I wrote you can Fork this project it has all the Imports already in there it's gonna work uh right out the gate so it's a sort of a little bit of stuff on top of that SVG rendering um boilerplate in the first link and the third link is to the docs for everything that I've talked about today uh actually here I'll quit out of this for a second so this is that repo I mentioned in the first link um oh you can't see that can you there we go so uh this is that repo uh uh oh nope sorry this is the real one oh I see I have to look on this screen okay um so this uh you can see here we have these are the properties that will be like the uh properties of the nft not visual properties but uh properties that you can sort by in openc for example and here we're generating the actual SVG so if you download this and you simply install the dependencies and there's instructions for that in the readme and then you call Forge test ffi it's going to open it on my screen so I gotta move this over so this is rendered from uh solidity so if we go here it's a little difficult for me to see but if we change this to I don't know blue obviously better to use actual hex colors uh oh sorry it's on my screen there we go so you can start playing with an SPG like right away it's very very fast and I encourage you to do that so one of the next steps uh so in this project what I've shown you is some tips and some lessons learned from uh creating an on-chain SPG rendering contract that just visualizes what's happening on chain in a dynamic image the next step is to create an nft that is interactive and to do that you would need to bundle in something like ethers or web3js into the nft potentially drawing it from an on-chain Source or potentially grabbing it from a regular HTTP root uh like uh you know from a CDN Etc so the promise of this is that we can have nfts that not only visualize what's happening on chain but allow you to write to the chain also by constructing a transaction request that metamask or whatever wallet you're using can understand and then propagate it to an RPC the problem here with a missing piece is that as we mentioned earlier openc sandboxes and caches at FTS and so you can't have interactive you can only have limited interaction inside of the openc frame and so the second piece that I think is interesting that people might want to work on is an nft app browser that is to say uh website most likely that allows you to browse nfts and interact with them to do things like construct transactions that you can propagate on shading so that's my talk thank you very much for attending and if anybody has any questions I'd be happy to answer thank you any questions yep oh good question um I'm not super deep on what all the prizes are that are available I don't know if there's anything where this will be particularly beneficial but one that comes to mind is I know 6551 the token bound like nft owned wallets could be interesting to have those wallets rendering something on chain representing what's inside of them with no off-chain dependencies so for instance uh yeah you could have an nft where you send it an asset and then it shows it and it's not relying on ipfs or http um I think also some of this on chain stuff could be very interesting on noses chain or polygon or other l2s or side chains where gas B's are lower you could do even more aggressive things not just with the rendering but with having more interactivity uh to to write to them to change what's being shown any other questions yeah okay if you're uh yeah there's a you most likely have to uh sign a transaction if you're logging into an app that wants you to verify that you own a certain wallet or if you want to send a transaction so those are cases when uh yeah it's uh it is the question is if you're making a game do you have to pop up a transaction request every time you want to do some in-game interaction and if the game State needs to be modified on chain and you need you want to restrict actions to the owner of a certain wallet then yes you probably do one alternative is to write your own app let's say a mobile app where you keep the keys and it's more of a custodial system so instead of asking the user for permission to their key you make every button just work uh and you don't ask Ben for permission to sign with their private key you just do it on their behalf that's that's a way around that yeah yeah you could I would suggest you probably want to make your own wallet built into your game yep any other questions okay thank you very much

Automatic transcript — names and jargon may be misspelled.