Skip to Content
Tokio Upgrade Docs are released! 🎉
Tokio V3Frontend Development

Frontend Development

Building decentralized applications (dApps) on Splendor is straightforward due to our full compatibility with the Ethereum ecosystem. This page provides guidance for frontend developers integrating with Splendor V3 (Tokio).

Web3 Libraries

Splendor works seamlessly with all major Ethereum frontend libraries:

ethers.js

ethers.js  is a complete and compact library for interacting with the Ethereum Blockchain and its ecosystem.

// Example using ethers.js to connect to Splendor import { ethers } from 'ethers'; // Connect to Splendor Mainnet const provider = new ethers.JsonRpcProvider('https://chain.splendor.org'); // Get the latest block number const getBlockNumber = async () => { const blockNumber = await provider.getBlockNumber(); console.log(`Current block number: ${blockNumber}`); return blockNumber; };

web3.js

web3.js  is a collection of libraries that allow you to interact with a local or remote ethereum node using HTTP, IPC or WebSocket.

// Example using web3.js to connect to Splendor import Web3 from 'web3'; // Connect to Splendor Mainnet const web3 = new Web3('https://chain.splendor.org'); // Get the latest block number const getBlockNumber = async () => { const blockNumber = await web3.eth.getBlockNumber(); console.log(`Current block number: ${blockNumber}`); return blockNumber; };

React Integration with Wagmi

Wagmi  is a collection of React Hooks for working with Ethereum. It’s modular, efficient, and has great developer experience.

Installation

npm install wagmi viem@2.x # or yarn add wagmi viem@2.x

Configuration

// config.ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' import { defineChain } from 'viem' // Define Splendor chains export const splendorMainnet = defineChain({ id: 232, name: 'Splendor', nativeCurrency: { decimals: 18, name: 'Splendor', symbol: 'SPL', }, rpcUrls: { default: { http: ['https://chain.splendor.org'] }, }, }) export const splendorTestnet = defineChain({ id: 231, name: 'Splendor Testnet', nativeCurrency: { decimals: 18, name: 'Splendor', symbol: 'SPL', }, rpcUrls: { default: { http: ['https://testchain.splendor.org'] }, }, }) // Create wagmi config export const config = createConfig({ chains: [splendorMainnet, splendorTestnet, mainnet, sepolia], transports: { [splendorMainnet.id]: http(), [splendorTestnet.id]: http(), [mainnet.id]: http(), [sepolia.id]: http(), }, })

React Components

// App.tsx import { WagmiProvider } from 'wagmi' import { config } from './config' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { ConnectButton } from './components/ConnectButton' import { Account } from './components/Account' import { Balance } from './components/Balance' const queryClient = new QueryClient() export function App() { return ( <WagmiProvider config={config}> <QueryClientProvider client={queryClient}> <div> <h1>Splendor dApp Example</h1> <ConnectButton /> <Account /> <Balance /> </div> </QueryClientProvider> </WagmiProvider> ) }

ConnectButton Component

// components/ConnectButton.tsx import { useConnect } from 'wagmi' import { injected } from 'wagmi/connectors' export function ConnectButton() { const { connect, isPending } = useConnect() return ( <button onClick={() => connect({ connector: injected() })} disabled={isPending} > {isPending ? 'Connecting...' : 'Connect Wallet'} </button> ) }

Account Component

// components/Account.tsx import { useAccount, useDisconnect } from 'wagmi' export function Account() { const { address, isConnected } = useAccount() const { disconnect } = useDisconnect() if (!isConnected) return null return ( <div> <div>Connected to {address}</div> <button onClick={() => disconnect()}>Disconnect</button> </div> ) }

Balance Component

// components/Balance.tsx import { useAccount, useBalance } from 'wagmi' export function Balance() { const { address, isConnected } = useAccount() const { data } = useBalance({ address, }) if (!isConnected) return null return ( <div> Balance: {data?.formatted} {data?.symbol} </div> ) }

Wallets Integration

MetaMask

The most popular Ethereum wallet that works perfectly with Splendor. Learn how to add Splendor to MetaMask.

WalletConnect

Integrate WalletConnect to allow users to connect with multiple wallets:

npm install @web3modal/wagmi
// config.ts import { http, createConfig } from 'wagmi' import { mainnet } from 'wagmi/chains' import { w3mConnectors } from '@web3modal/wagmi' import { splendorMainnet, splendorTestnet } from './chains' export const config = createConfig({ chains: [splendorMainnet, splendorTestnet, mainnet], transports: { [splendorMainnet.id]: http(), [splendorTestnet.id]: http(), [mainnet.id]: http(), }, connectors: w3mConnectors({ projectId: 'YOUR_PROJECT_ID', chains: [splendorMainnet, splendorTestnet, mainnet], }), })

Data Fetching

Fetch on-chain data with Wagmi hooks:

// Token balance example import { useReadContract } from 'wagmi' import { erc20Abi } from 'wagmi/abi' export function TokenBalance({ tokenAddress }: { tokenAddress: string }) { const { address } = useAccount() const { data, isLoading } = useReadContract({ address: tokenAddress, abi: erc20Abi, functionName: 'balanceOf', args: [address], }) if (isLoading) return <div>Loading...</div> if (!data) return <div>No data</div> return ( <div> Token Balance: {data.toString()} </div> ) }

Sending Transactions

import { useWriteContract } from 'wagmi' import { erc20Abi } from 'wagmi/abi' import { parseEther } from 'viem' export function SendToken({ tokenAddress }: { tokenAddress: string }) { const { writeContract, isPending, isSuccess } = useWriteContract() const handleSend = () => { writeContract({ address: tokenAddress, abi: erc20Abi, functionName: 'transfer', args: ['0xRecipientAddress', parseEther('1')], }) } return ( <div> <button onClick={handleSend} disabled={isPending}> {isPending ? 'Sending...' : 'Send 1 Token'} </button> {isSuccess && <div>Transaction successful!</div>} </div> ) }

Best Practices

  1. Error Handling: Implement robust error handling for transactions and blockchain interactions
  2. Loading States: Always show loading indicators during pending transactions
  3. Gas Estimation: Estimate gas before submitting transactions to avoid failures
  4. Account Handling: Properly manage connected/disconnected states
  5. Network Detection: Detect and handle network changes gracefully
  6. Block Confirmations: Wait for sufficient block confirmations for important transactions

User Experience Tips

  • Provide clear feedback for transaction states (pending, success, failed)
  • Implement proper error messages that users can understand
  • Consider using progressive disclosure for complex blockchain operations
  • Provide transaction history and status
  • Use optimistic UI updates when appropriate

Testing

Use tools like Hardhat  or Foundry  with local networks for testing before deploying to Splendor Testnet.

Resources