Skip to content

feat: on-chain SVG NFT recipe with Chainlink price feeds#39

Merged
PetarStoev02 merged 5 commits into
mainfrom
feat/onchain-svg-nft
Apr 9, 2026
Merged

feat: on-chain SVG NFT recipe with Chainlink price feeds#39
PetarStoev02 merged 5 commits into
mainfrom
feat/onchain-svg-nft

Conversation

@PetarStoev02
Copy link
Copy Markdown
Contributor

Summary

  • New EVM-only recipe: decode on-chain SVG NFTs, render base64 tokenURI metadata, interact with dynamic NFTs that react to Chainlink price feeds
  • Base64 tokenURI decoding with support for both base64 and UTF-8 encoded SVGs
  • Sandboxed iframe rendering for XSS protection
  • Chainlink AggregatorV3 integration with live price polling
  • Dynamic NFT minting via safeMint
  • Educational .learn.md (~2500 words) covering on-chain storage, SVG encoding pipeline, Chainlink oracles, rendering security, and gas considerations

Why EVM only

On-chain SVG generation via abi.encodePacked inside tokenURI() is an EVM-specific pattern. Solana NFTs use Metaplex which stores URIs pointing off-chain. Chainlink is also EVM-native.

Files

recipes/onchain-svg-nft/
├── meta.json
├── evm.tsx
├── README.md
├── onchain-svg-nft.learn.md
└── example/evm/page.tsx

Sources referenced in learn.md

Test plan

  • npm run format:check passes
  • Recipe structure matches existing conventions (meta.json, evm.tsx, README, .learn.md, example/)
  • Code compiles with wagmi/viem types
  • Example page pre-populates with Nouns contract (mainnet) for immediate testing

Closes #19

EVM-only recipe covering base64 tokenURI decoding, on-chain SVG rendering
in sandboxed iframes, Chainlink price feed integration, and dynamic NFT
minting. Includes educational deep-dive on on-chain vs off-chain storage,
SVG security, and gas considerations.

Refs #19
- Replace redundant svgContent state with useMemo derived from metadata
- Guard handleMint on address being defined (prevent minting to zero address)
- Wrap handleMint BigInt conversion in try/catch
- Add res.ok check on off-chain metadata fetch
- Add enabled guard on Chainlink useReadContract
- Fix unconditional ellipsis on short URIs
- Disable mint button when wallet not connected
@PetarStoev02 PetarStoev02 marked this pull request as ready for review April 9, 2026 10:41
Remove the bare example/evm/page.tsx and replace with a full showcase
app built on the recipe-shell template. Includes:
- w3-kit design system (tokens, dark mode, Geist font)
- w3-kit NFTCard and PriceTicker components
- Live Loot NFT + Chainlink price feed on mainnet
- Deploy & Mint flow on Sepolia with pre-compiled contract
- RecipeLayout with wallet connect and theme toggle
…d deploy status

- Change evm.tsx default Chainlink address from Sepolia to mainnet
- Remove unused useWriteContract/useWaitForTransactionReceipt for deploy
- Replace error-as-status with dedicated deployStatus state
- Add mountedRef to prevent state updates after unmount in deploy polling
@PetarStoev02
Copy link
Copy Markdown
Contributor Author

Review

Reviewed recipe content, showcase example, and code quality.

Recipe files (evm.tsx, learn.md, README, meta.json):

  • Base64 tokenURI decoding with both base64 and UTF-8 SVG support
  • Chainlink AggregatorV3 integration with live polling
  • SVG rendered in sandboxed iframe (XSS-safe)
  • Educational deep-dive with sources (EIP-721, OpenZeppelin, Chainlink docs, SSTORE2)

Showcase example (TanStack Start + w3-kit components):

  • Live Loot NFT rendering from mainnet via NFTCard component
  • Live ETH/USD price from Chainlink mainnet oracle via PriceTicker component
  • Deploy & Mint flow on Sepolia with pre-compiled DynamicSvgNft contract
  • Proper deploy status state, mounted ref cleanup, error handling

Review fixes applied:

  • Mainnet default for Chainlink price feed (was Sepolia — cross-chain mismatch)
  • Removed dead useWriteContract/useWaitForTransactionReceipt hooks from deploy section
  • Replaced error-as-status pattern with dedicated deployStatus state
  • Added mountedRef guard for deploy polling cleanup

LGTM — ready to merge.

@PetarStoev02 PetarStoev02 merged commit 29251d9 into main Apr 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recipe: Dynamic on-chain SVG NFTs with price-reactive metadata

1 participant