proto iNFT

about

Anyone can use this iNFT pattern as a way to securely host websites by publishing them as NFTs.

These iNFT websites can be their own browser experience, in addition to (along with all other standard NFTs) being automatically included in public NFT marketplaces such as OpenSea, within a wallet such as Rainbow or shown on a DAO dashboard such as KALI.

Though the IPFS hosted HTML in this “proto iNFT” proof-of-concept is opinionated for a “legal seals” application, the iNFT’s pattern generally and especially up to that point is unopinionated.

Here is the “proto iNFT” as rendered by Mirror.xyz (the metadata’s “image” value isn’t intended to be the iNFT’s background, despite being shown as such in the Mirror.xyz ‘s rendering at time of publication):

 

Please visit the “interface tokens” article for context:

walk-through

result

Here’s what an iNFT looks like in OpenSea (sans scrollbar sizing mistake):

proto iNFT side-1
proto iNFT side-1

Clicking on the parent flip button (lower flip button) cycles through the NFT’s 3 sides:

proto iNFT side-2
proto iNFT side-2
proto iNFT side-3
proto iNFT side-3

OpenSea’s iframes are sandbox iframes that don’t allow-same-origin, so the “proto iNFT” ’s PDF side can’t be displayed on OpenSea. Instead, the iNFT offers the base64 workaround described in the “proto iNFT side-2” image shown above.

Using the iNFT’s parent smart contract as a self-referencing oracle that side-3 relies on for trustless-stateful reporting is described in the “interface tokens” article shared above.

The “proto iNFT” ’s side-1 plays with nesting 2-sides within it. Clicking on the child flip button (upper flip button) shown in the “proto iNFT side-1” image above offers a backside form that modifies the front-side via the reprint button:

proto iNFT side-1 parent, side-2 child
proto iNFT side-1 parent, side-2 child
proto iNFT side-1 parent, side-1 child modified by side-2 child
proto iNFT side-1 parent, side-1 child modified by side-2 child

Though this result is opinionated for “legal seals” and other experiments, the general concepts include:

  • sides, and nested sides, for a physical token inspired ‘tiled’ interface

  • a side can be static, and potentially entirely onchain, e.g. a base64 PDF side

  • a side modifies a different side, e.g. a backside modifies a front-side

  • outsides sources, including the NFT’s own smart contract, can modify a side

under-the-hood

The “proto iNFT” ’s smart contract is at:

It uses a Wrappr contract but minted through PolygonScan rather than Wrappr’s UI found here:

If a unique 0x address mints with the Wrappr’s UI, or through PolygonScan, that 0x address will be automatically added to the “proto iNFT” ‘s side-3 0x addresses listed below the ‘signer under seal’ title.

This is a screenshot of the “proto iNFT” ’s minting transaction:

proto iNFT mint
proto iNFT mint

The “proto iNFT” ’s minting transaction is here:

The uri uses the base64 pattern described in the “interface tokens” article shared above:

uri lookup
uri lookup

Plugging the base64 into a browser renders the “proto iNFT” ’s onchain JSON metadata:

proto iNFT metadata
proto iNFT metadata

This is the animation_uri HTML within the JSON’s base64 rendered as text:

<!DOCTYPE html>
<html>
  <head>
	<title>proto iNFT</title>
	<script src="https://cdn.jsdelivr.net/npm/web3@1.2.9/dist/web3.min.js"></script>
  </head>
  <body>
	<iframe id="$0" width="100%" height="500" style="display: block"></iframe>
	<script id="app">
	  ( function app() {
		  async function request() {
			  _0.response = await fetch( _0.ipfs )
			  ; _0.string.parent += await _0
				  .response.text()
			  ; _0.base64 = _0.string.parent
				  .replace( _0.prefix, '' )
			  ; _0.string.child = atob(
				  _0.base64
			  )
			  ; _0.json = JSON.parse(
				  _0.string.child
			  )
			  ; _0.iframe.src = _0.json
				  .animation_url
			  ;
		  }
		  function loop( $0 ) {
			  _0.contract.methods.KeyIndex( $0 )
				  .call().then( $1 => {
					  _0.version[
						  $1.key
					  ] = $1.version
					  ;
					  if ( $0 < _0.count ) {
						  _0.loop( $0 +1 )
						  ; return
						  ;
					  }
					  _0.next()
					  ;
				  } )
				  .catch( $0 => {
					  console.error( $0 )
					  ;
				  } )
			  ;
		  }
		  function next() {
			  _0.contract.methods.KeyValue(
				  'proto iNFT'
				  , _0.version[ 'proto iNFT' ]
			  ).call().then( $0 => {
				  _0.ipfs += $0
				  ; _0.request()
				  ;
			  } ).catch( $0 => {
				  console.error( $0 )
				  ;
			  } )
			  ;
		  }
		  const _0 = new App
		  ; _0.contract = new _0.web3.eth
				.Contract( _0.abi, _0.address )
		  ; _0.contract.methods.KeyCount().call()
				.then( $0 => {
					_0.count = $0
					; _0.loop( 0 )
					;
				} )
				.catch( $0 => {
					console.error( $0 )
					;
				} )
		  ;
		  function App() {
			  this.abi = [... redacted]
			  ; this.address = '0x02ef4cd76c44b781'
				  + '302dd34142051704a94aabec'
			  ; this.base64 = null
			  ; this.contract = null
			  ; this.count = null
			  ; this.iframe = document
				  .getElementById( '$0' )
			  ; this.ipfs = ''
			  ; this.json = null
			  ; this.loop = loop
			  ; this.next = next
			  ; this.prefix = 'data:application/js'
				  + 'on;base64,'
			  ; this.response = null
			  ; this.request = request
			  ; this.string = {}
			  ; this.string.parent = ''
			  ; this.string.child = ''
			  ; this.version = {}
			  ; this.web3 = new Web3(
				  new Web3.providers.HttpProvider(
					  redacted
				  )
			  )
			  ;
		  }
	  } )( this )
	</script>
  </body>
</html>

This animation_uri HTML is as-small-a-footprint-as-possible wrapper, for:

  • minimum onchain storage, given how expensive onchain data costs

  • doesn’t include any upgradable aspects of the “proto iNFT,” since it’s not upgradable

One of the ways the animation_uri HTML keeps its footprint down is by using as-small-a-footprint-as-possible upgradable onchain smart contract oracle, found here:

The smart contact is a simple key-value pair object, that also has LIFO versioning for the value.

In the iNFT use case, by changing the proto iNFT key-value’s value to a different DNS hosted HTML file, the “proto iNFT” is updated to the new link. For best practice as of now, the value should be an IPFS hosted HTML file.

proto iNFT prior version
proto iNFT prior version
proto iNFT current version
proto iNFT current version

This IPFS hosted HTML file can be large. The IPFS hosted HTML for this current “proto iNFT” version is ~4000 lines long.

conclusion

NFTs, “iNFTs,” as the way to distribute website client-side files:

  • publishes to as many places at once as possible

  • versioning is well-managed and transparent

  • marketplaces and other last-mile distributors manage HTTPS certificates

  • trustless, censor-resistant and commodified website-objects

  • token ID (smart-contract array “port”) #0 could be the UI used to mint the token, helping protect against malicious minting dapps

backside link to website hosted by OpenSea
backside link to website hosted by OpenSea

Here’s the “proto iNFT” as a website hosted by OpenSea:

Since this version of the “proto iNFT” isn’t a sandbox iframe, but rather the top-level DOM, it can display the parent side-2 PDF as intended:

same-origin allowed proto iNFT as an OpenSea website
same-origin allowed proto iNFT as an OpenSea website

iNFTs have a very interesting client-server-blockchain 3-sided dynamic to explore.

However, the chance to have a client-blockchain 2-sided dynamic is arguably far more important for progressive decentralization.

“proto iNFT” relies on an Alchemy blockchain server, as well as JavaScript library CDN servers. It’s a thin, but nevertheless server-dependent, client-server-blockchain 3-sided dynamic.

A client-blockchain 2-sided dynamic is not yet possible when using onchain oracles, unfortunately.

Subscribe to bestape
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.