How I  got on-chain

Updated: 20/12/22 – A few anomalies have been pointed out, so I've made some edits below. There's also an update or two at the end of article.

Note: I am not a programmer, I’m an artist first and foremost. Yes, I’ve played with bits of code here and there, I have 35 years experience, freelance, in print and web design which has necessitated some self-sufficiency in tech skills. But I’m very much self taught.

NFTs and storage

A quick explainer, in simple terms – when you mint an edition or a 1/1, you set up the Title, Description, etc. – this is the metadata and your wallet signs and locks the NFT to your identity. The JPG/PNG you upload, gets sent to a peer-to-peer server somewhere else – it’s not stored ON THE BLOCKCHAIN because blockchains aren’t designed for large files. It might look like it, but your JPG is not stored on-chain.

Various services are used for storage, IPFS, Arweave are common ones, it's a pretty standard approach. These organisations get paid to store the files by the platform you’re using. Apparently some platforms don’t use these storage standards and use their own, so if the platform goes under, or stops paying the storage then your NFT can disappear. That’s not great for longevity.

When your JPG is uploaded successfully to IPFS, a link to that file is generated and embedded with with your metadata. That’s the data that sits on the blockchain when you hit the ‘mint’ button (along with a bunch of contract data, rules, royalty settings etc).

That all works fine – a hyperlink to ‘The File’. It makes sense because blockchains are ledgers.  A conventional ledger doesn’t have all the details of a business transaction it might just say ‘paperclips $2’ in the purchases column — it doesn’t say what colour they are or if they are small or large; it won't say which stationery cupboard they’re in or how many you’ve got left. There are other systems that track stock of stuff. 

Newbie error

My first mint was in Feb 2021. I hadn’t got very far with platform applications and I didn’t really know which to apply for. Quickly frustrated, I decided to go it alone and use OpenSea to launch my first collection of 100 1/1s. They were made with a combination of Procreate and Photoshop, with file sizes of 2–3 mb. I didn’t question where files lived or how good the OpenSea contract was.

Here they are.

Not all contracts and not all platforms are the same

Towards the latter half of creating my first series, I saw a tweet by @caktux reviewing the various NFT platforms and their adherence to the ERC721 / 1155 standards. OpenSea (OS) was one of the worst apparently.

Here’s the thread

As a newbie – I found it difficult to understand contracts, the interface and lingo of 'Etherscan' let alone find where my own work lived on the blockchain. The shared contract of OS exacerbated this. The @caktux  review started to make sense — “it’s not just me”. The OS contract was great to ‘get you going’ – it offered no-gas lazy minting and it’s relatively easy to set up a collection. The downsides were now a bit clearer. I’d also read a couple of collector tweets that they didn’t rate the OS contract at all and probably wouldn’t collect anything minted on it. That was slightly worrying.

I resolved to try and learn about contracts and the standards in the future, I wasn’t about to learn ‘Solidity’, I was fully committed to getting to the end of my 100 1/1s project. In the meantime I’d got accepted on Known Origin and was pleased that it was a decent platform with what looked like a decent and respected contract. They’re nice people at KO too.


I was picking bits of knowledge here and there – where files went to, what happened when you mint, the whole gas thing and IPFS. ‘Interplanetary File System’ – sounds way cooler and futuristic than it is. We’re not storing data on Mars just yet; really it’s a web 2.0 distributed peer-to-peer file system. I started thinking ‘what if these IPFS companies go bust?’. What if they don’t have a back-up?’… Still so many questions.

Some of them have been answered by the venerable Jason Bailey @artnome and his @clubNFT service — essentially this is a backup service for your NFTs. There’s a basic backup file service and then a ‘pinning’ service that makes a duplicate of your NFT link on IPFS. I’m not completely sure how it works, but it seems like a fine idea. A thing that guarantees the longevity of your collection and puts the power in the hands of the owner and not the platform. 

Conceptually though, isn’t’ a backup a copy? Not the original? Not ‘THE File’? Not ‘The Paperclips' we bought? Not 'My Monkey JPG'? That thing that, that very file that was linked to by the artist on the blockchain? The very point of the technology? The idea we keep explaining to the detractors? I guess a backup is at least something, if it all goes to shit, you get to keep a copy of your funny monkey.

Part of the @NFTclub homepage says

  • 10% of NFTs are on-chain.
  • 40% of NFTs are on private servers and at risk.
  • 50% of NFTs are on IPFS & can be saved with ClubNFT.

The third part we understand – it’s a backup link of our JPG on IPFS.

The second part – well that’s a tricky one to get around - if someone’s minted on a crappy platform with a crappy contract and non-standard storage and they go bust, then there’s not much we can do about that.

It goes to highlight how you should do your own research when it comes to platforms. I liken it to artists painting with housepaint – a material that is designed to degrade over a very short time (20 or so years so you have to paint your house again, rather then the 100s of years that oil paint lasts). Housepaint cracks and crazes, can’t be stabilised once it has and eventually falls off the canvas. No more art. A crappy contract is like cheap art materials.

But what about ClubNFT’s first part – ‘10% of NFTs are on-chain’. What does that even mean?

‘Clever Bastards’

BAYC came out and the whole PFP thing took over NFT Twitter. I was happily minting 1/1s away on Known Origin. I tried Solana platforms which had a slightly different way of minting. I started to learn about to Hashlists and JSON files. JSON stands for  JavaScript Object Notation – basically a file and data format that has become standardised.

On ETH we soon got used to paying gas every time we minted and I was wondering what it would cost to mint 100,000 BAYC monkeys – what the gas fees would be. I then read this article from Larva Labs from August 21 – ‘Cryptopunks were on-chain’. 

It's still there

But what is on-chain? There’s that phrase again. How did that work? Aren't blockchains difficult for storage? Surely that must be incredibly limiting? If it were a few dollars gas per Kb for storing ‘some text’ — ie a contract –– on-chain what’s a 3Mb JPG going to cost? I couldn’t decide if Cryptopunks had a low-res pixelated look because they had limited storage, size/cost, or whether that was ‘the style’. 

Then it all became a bit clearer when I discovered these things are rendered when the contract is called. They use SVG a lot. An in-depth articel from Simon de le Rouviere from August 2021 explains a lot about how it all works and the ins and outs of on-chain projects (you’ll need your code head on)

TLDR – SVG is used a lot. It’s a bunch of code, not a JPG, that suddenly makes sense. There’s everyone saying ‘collecting JPGs’ , but even things look pixelated they are actually made of SVG – in the words of Ian Dury ‘There ain’t half been some clever bastards’. 

I’d used SVG a lot in my design career, Scaleable Vector Graphics – the files you get out of Adobe Illustrator, CorelDraw and others. I’d remembered it was introduced around 1999 in my web design days. Internet Explorer supported it very early on and it was a much better than GIF for rendering logos and graphics. Better because it’s based on mathematical splines, points and curves, it takes a lot less data space to draw a shape than it does with pixels and of course it’s faster to download. The best bit is that it's scaleable. Print to any size, scale it up and vinyl it on the side of a bus or a building – you can’t do that with a BMP.

I started thinking about using SVG more and more.

Too many pixels

At that point there were a lot of artists getting onboard with NFTs (great!). I saw a lot of abstract pixel pushers, people loading brushes into ‘Procreate’. A lot of really good work, a lot of ‘meh’. The market was getting crowded and a lot of it started to look the same. The critique was non-existent and there was a lot of back slapping and popularity contests. ‘No thanks’.

I took a pause and a step back. 

Full on with SVG

I dived in with making work with SVG – some I managed to animate with Javascript. There were a lot of pitfalls. I was minting on Known Origin at the time becasuse it was one of the few platforms that let you mint with vectors. (most have a limited MIME-type file list for ‘upload’ on minting). 

There were one or two pieces exploring movement and continuous loops – I was also looking at colour rotation. I loved the idea of an abstract piece slowly and imperceptibly changing colour – over several minutes even. If you attempted something like that with GIF or MOV then you’d end up with huge file sizes – too big even for IPFS. 

This one ‘Kisetsu’ is only about 89kb, changing colours with a seamless loop. I’ve generated a GIF version – that came out at 11mb!

'Kisetsu' on Versum

I found that when you render an SVG with a filter the filesize increases vastly 4-5mb instead of a few hundred Kb. Some platforms won't accept SVG animated with JS, but are ok with CSS animations.

Jumping forward briefly to Autumn 2022 and you still couldn’t mint SVG on (Solana). But you could mint an html file. “That’s a bit of an anomaly” I thought. As a technical challenge I took it upon myself to embed SVG into HTML5 and see if I could get it onto exchange and upgrade my HTML skills while I was at it (CSS ‘grids’ mainly). 

I was also thinking “HTML - that can be responsive” ie. change size according to the device you’re showing it on,  so it could scale up and down. I got it working.

'Bloom' on
The html uses a lazy load – all the separate SVG layers load at different rates. Click it and it will reload.

I’ve since been on Discord with folks and they’re looking at adding SVG – which will make them the only SOL marketplace supporting vectors.

I made a separate piece called ‘Anpassen’ (German for ‘to adjust’) This uses several SVG files with transparency, embedded into HTML layers. Resize the browser and you get a slightly different composition every time. 

Pushing my SVG skills further I investigated more animation. I wanted an abstract painting that is subtly 'living and breathing'. I can see it in the corner of room on an LCD display, like the house cat asleep. I called it  ‘Blemished’ and it has a continuous seamless loop.

'Blemished' on

its partner piece ‘Blemish’ is on ETH on Rarible
'Blemish' on Rarible

So I was going full SVG AND chain-agnostic – but at the back of my head, I still wanted something on-chain.

This was starting to become a problem that I just had to solve.


Here’s a Twitter thread of some of the platforms who support SVG. One of the most surprising and glaring problems is ‘Superrare doesn't support SVG’ a graphics format that’s been around for 22+ years. I’m appalled.

Platforms that support SVG - Twitter thread
(If anyone has additions or updates, please let me know)

An Upgrade

I have always thought that this technology is end-to-end. No middleman. No intermediary gallery, no gallerist telling you what to do, or influencers saying who’s in or out. In the long term OpenSea's contract probably wasn’t going to cut it, Known Origin was having difficulty with some of my SVGs animated with Javascript and they sold out to eBay anyway – they started curtailing artists from certain countries (US trade policy etc.). No thanks.

In January 2022 I set myself up with the Manifold Studio contract tool. I’d signed up immediately and made my own ERC721 contract and minted some 16:9 pixel-based works. Deeply buried in their documentation was a ‘how to mint on-chain’ on an ERC721 contract. This essentially mean't taking SVG data, convert to a URI, (replaces the link to IPFS), wrap it in JSON and then you have to log into the contract on Etherscan. Signing in with your contract wallet and interacting directly with the contract on-chain was a totally new concept. But that's how you send your SVG code to the contract – it adds +1 to the token list. They make it sound so easy. 

That really got me thinking – what if I reinterpreted my original 100 Xs with SVG? What if I redrew them and then minted them on-chain. I was going to call them ‘Upgrades’ and offer them to collectors of the original 100. ‘Upgrades’ because it was an upgraded contract (better than OS), ‘upgrade’ as in upgraded software. There were going to be all sorts of mechanisms for swapping, burning, upgrading. I was getting ahead of myself… Definitely.

The Manifold instructions were slightly confusing – but I got there in the end. As a demo, I took one of my SVG pieces and converted it following Manifold’s instructions and put it into a format that I could upload direct to the contract in etherscan…

I hit ‘write’ on mainnet and Metamask popped-up with a quote of

$3k gas!
I rejected the transaction and that effectively put an end to the 'Upgrades' project – there’s no way I could afford the gas to mint a single 1/1 on-chain. 

1155 though?
Months went by and 'the merge' happened, I wasnt going to give up. With my ‘$3k gas’ Manifold test I’d been quite liberal with my vectors and layers. There was a lot going on in my files – layers, grads etc. Maybe if I could get the file size down some and I could mint using a 1155 contract and do an edition, that might offset the gas price?

I tried to interpret Manifold’s instructions using a 1155 contract.

It just wouldn't work – I kept getting errors on ‘contract write’, I think I must have tried about 20 different files and generated different optimised variants. Something was amiss and I just wasn't seeing it. It must have been a missing ‘}’ in the code or something – it usually is.

Frustrated, the project was parked again.

The ETH merge wasn’t going to solve my gas problem. So I started thinking about L2 sidechains. These are basically blockchains that run like Ethereum and are compatible with it using slightly different tokens (Polygon uses 'Matic'). I’d seen projects minting huge amounts of NFTs using very little gas. If you check your 'collections / hidden' on OpenSea it’s probably full of speculative and spammy 'wallet fluff' made on Polygon – sent to you for free.

Zang’ came on my radar – an ‘on-chain’ text-based gallery running on Polygon. It's for, writing and poetry etc – that made sense, unless you want nice typography, poetry uses small files and very little data, just text. I liked the idea.

Zang also supported HTML 5 (it’s just text) and they’d minted their one demo token. So I adapted some of my html-learning and put together a couple of demo pieces to see if I could get something working. After a couple of ‘misses’ – where they were rendering a tiny thumbnails (a problem with the ‘grid’ tag which was used to create a responsive border in the html got blocked’). I stripped that tag out and had success. 

Zang gallery tokens 44 and 43 – my pieces – are the only ‘pictures’ on Zang the rest of the tokens on there so far are ‘just text’. I feel like I've taken it over a little!

They’re extremely limited – but these are really my first two pieces on-chain. The problem is you can’t do much with them OpenSea and the other marketplaces think the NFT is ‘just text’ because the MIME-type is set as text and so won’t render anything on their platforms. Not something that will be fixed anytime soon.

This is what it looks like on OpenSea

That missing ’}’

The ETH on-chain 1115 test had been parked for a couple of months – but I left about 3 messages on 3 different channels on Manifold’s Discord.

The answer came – I was given simple instructions to replace every single quote in my 721 code (the $3k gas code) with a backslash before itThen wrap it in a single quote and square brackets.[‘likethis’]. So it wasnt a missing ‘}’ it was a little more complex than that.

‘What?!’ – I'd have never got to that on my own. I converted a Zang test file and tried a 1155 contract on Goerli (Eth testnet). Frustratingly I ran out of free testnet ETH and had to wait 24hrs for more, but when i'd replenished, it worked a dream on testnet – it rendered! It even showed on OpenSea straight away. Time to see what the gas would be like on Ethereum mainnet. 

Taking the exact same demo code I went for it. It worked! Gas was about $300–400 – yes, expensive and probably swallowable for a set of editions. I rejected the transaction because I wasn’t going to mint a demo file as my first real on-chain ETH piece. 

Minting a demo SVG direct in Etherscan and the gas quote

I’d got there, after nearly a year of trying and failing, optimising files, working out what made them larger I’d finally got to a working proof of concept.

Niftykit and Polygon – a dead end

In parallel to my ETH 1155 success, as a punt (pay ETH to become a member), I joined Niftykit. It’s a bit like Manifold, but seems aimed more at creating collections of PFPs of layered monkeys with different hats on etc. 

Build your own kit of parts, upload the parts to IPFS yourself, generate your IPFS links to your files, build a JSON file with a description of all those parts and go. You can upload NFTs as CSV file with your IPFS links in that. ‘Excel again, I thought I was done with that!’. I gave it a go and instead of putting IPFS links in my Excel I used my Manifold SVG/URI code. 

Things got going quite quickly using a Polygon contract (they offer several flavours of sidechain, as well as Ethereum). I was really leaning on my newly acquired ‘Manifold skills. The first attempt worked pretty well, but I wasn’t getting any previews of my art on any marketplaces. With a few clicks and a bit of waiting – they appeared on OpenSea AND on Rarible. Bit of a revelation really – the Niftykit team hadn't expected it to work on Rarible at all.

Here it is 'Shinjuku' on Opensea [burned]

Here it is on Rarible [burned]

'Shinjuku' Demo art

On NiftyKit you can add a whole bunch of NFTs together (remember it’s aimed at collections), so I tried a second one, adding a line to my Excel file – but it didn't work this time. The first one was still ok – the second one nothing. I tried again and again, and ended minting repeats to myself which I burned – but annoyingly still show up. I walked away – always a good idea. 

It came to me on a dog walk. CSV is a relatively basic format – 'there must be a cell limit for file size or something'. Not quite – CSV has a cell limit of 32,767 characters. My second NFT used over 34,000. I made a few minor adjustments to the file and it was good to go. This time working perfectly.

Full ETH and on-chain

Now we were flying. I recently finished a new SVG piece ‘Testcard’. This time I was going full ETH, no Polygon. Using the same method it worked straight away. Even better – it appeared within an hour or two of being in my wallet on Looksrare, Rarible, Gem, OpenSea AND on my mobile Metamask. Far far more than expected. 
'Testcard' previewing in my Metamask wallet on iOS:

'Testcard' on

The working previews on marketplaces proved that I’d finally done it. It’s not strictly how it’s supposed to be done, it’s not how LarvaLabs and all those massive teams of people do it, but for an artist that’s not really a coder, I’ve got a result and now i’m making some more. I'm sure some clever kid is going to come along and pick holes in all of this.

See it here on OpenSea [burned]

Update 20/12/22 – ‘No it's not!’

As predicted, someone cleverer than me has pointed out that it's not there yet. The whole NiftyKit thing is a blind alley!

@yungwknd contacted me via Twitter and we had a very interesting DM chat late one evening Euro time. They pointed out to me that my mints aren't on-chain at all. It's just minted to a private server. 
Hum. Slightly deflated of course.
What's happened is – the SVG code I have, actually worked – after several failed attempts, BUT what it looks like a mint with no JPG or PNG involved with IPFS – I've got a bit carried away with my 'working code' and actually the metadata is on NK’s server (along with my SVG).
Just because it's not on IPFS doesn't mean it's on-chain. @yungwknd showed me a hyperlink (the tiniest of single character links!) on the contract in OS and that points to the data and shows that it's IPFS.
So turns out it's a 'type 2' in NFTClub's description (see above) – not what I was expecting. If NiftyKit go down, so does the NFT which is of course, not what I wanted at all. There's an option to put the metadata in IPFS – but along with that goes my SVG, so it looks like that's just minting an SVG in IPFS. Again not on-chain.
That's 3 steps forward and 2 steps backwards. I have some more trials to do and will see what happens when I 'kill' my NK contract, port to IPFS etc. But it looks like that's a complete dead-end. 
Good news is though – I have some working SVG code to use, and someone knowledgeable to bounce off.
It's a a hell of a journey and I'm determined to get to the end of this.

Update II – ‘It's IPFS’

So a quick login to the NiftyKit backend and update a setting or two on the metadata. It's ported all the data over to IPFS and no longer on their own server. It's a step up in the food chain, but definitely still not what I'm trying to achieve. So I'm abandoning this particular blind alley for now, but not all is lost. NiftyKit looks a half decent tool for minting on Polygon, Arbitrum, Ethereum, Optimism with batch minting, waitlists, etc.

Update III – Finally success

So I dumped the whole NiftyKit blind alley. I'd led myself down this dead end and got carried away with myself. The nature of things web3.0 make it difficult to know where things 'live'. Why are so many web3.0 platforms so obstinately bad and hard to use with terrible UI/UX? You'd have thought we'd have learned from 20+ years of web2.0.
All is not lost because I used the Niftykit tool for a little collaboration. I created 75 NFTs for a web3.0 client The idea is a simple – a seasonal NFT in place of conventional Christmas card. So I used NiftyKit and Polygon and minted all 75 for less than a couple of dollars. 
But getting back to the on-chain project – I spent a happy afternoon making a new artwork derived from 'Testcard'. There were several variants. Some with grads, some optimised, some exported with slightly different settings. Ages was spent optimizing the SVG with various tools getting it down to less than 15Kb. After 'minimizing' (that's where essentially you get rid of the code layout for human legibility, losing line breaks etc) and the next two stages of embedding the code into JSON format I got it down it 11Kb. Variants were that were Base64 rather than UTF-8, but that didnt improve the file size so I reverted to UTF-8. Time to mint. This was via my Manifold 721 contract – so I thought this properly 'blue chip' if this works. (Artist's own contract PLUS on-chain). I called it 'Testcard Min' after the 'minimizing' process. 
'Testcard Min'
Logging into Manifold and linking through to the contract on Etherscan, I went with Goerli testnet first (got plenty of free testnet ETH stocked up this time) and it worked first time. Yay!
Time to go with Mainnet. Pasted the code into the contract and gas came up as $200 – a lot, but not terrible – i've had a lot worse quotes, so thought 'what the hell ' and clicked the 'approve' button.
Both OpenSea and Rarible showed it within minutes. But I wasn't going to be making any claims quite yet – what with my recent experiences, I didn't want to get ahead of myself. I quick DM to my new buddy @yungwknd and a link. Then wait.
[@yungwknd is on Manifold's Discord, seems to be a troubleshooter and problem solver and an all round good guy. As are all the Manifold crew – I think they are probably the best people in web3.0 right now]
An hour or two later @yungwknd comes back to confirm to me that yes, it's on-chain

Quick tip
Go to Opensea click on an NFT. Under 'details' you get Contract Address, TokenID, Standard, Chain and and Creator Fee. If 'Token ID' number is a hyperlink then the NFT is arweave or IPFS. If the number is not a hyperlink, then on chain. There's other ways to tell, but I think this is the easiest indicator.
Compare these two by the amazing Ripcache:

Above: Not on-chain – hyperlinked Token ID
Above: On-chain – Token ID is not hyperlinked. So where is it – part of the contract.
So that's it – I got there in the end. 
Here's 'TestcardMin' on OpenSea
Thanks to everyone at Manifold, particularly @yungwknd. Everyone that has put up with my inane ramblings and my obsession with this. I've learned a lot a long the way and I'm sure there's still a whole load to learn. Like 'a TEZOS version', like 'compression techniques', but that's probably a subject for another article.

Update IV

All the experimental NFTs and contracts have now been burned /deleted.

'TestcardMin' is my first 1/1 piece on ERC721. 'BroadcastMin' is its sister piece and is a very small edition on ERC1155. 'Glyphset' is larger file 1/1 using Polygon/Eth and The original ‘Testcard’ will join it shortly.

TestcardMin on Opensea
BroadcastMin on Rarible
Glyphset Edition on Rarible

Resources and links

Zang gallery
Manifold’s on-chain instructions

AltJames on Twitter