Skip to Content
Dial v1 live šŸŽ‰
SdkExamples

Examples

Complete code examples for common Dial SDK use cases.

Quick Examples

Basic Audio Call

import { DialClient } from '@dial/sdk'; import { SiweMessage } from 'siwe'; const dial = new DialClient({ apiKey: process.env.DIAL_API_KEY }); // Authenticate with SIWE const nonce = await dial.auth.getNonce(); const siweMessage = new SiweMessage({ domain: 'dial.wtf', address: walletAddress, statement: 'Sign in to Dial', uri: 'https://dial.wtf', version: '1', chainId: 1, nonce, }); const message = siweMessage.prepareMessage(); const signature = await wallet.signMessage(message); const userDialer = await dial.asUser({ siwe: { message, signature } }); // Make call const call = await userDialer.calls.start({ to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', type: 'audio' }); console.log('Calling...', call.id);

Video Call with React

import { useState, useEffect } from 'react'; import { DialClient } from '@dial/sdk'; export function VideoCall() { const [dial] = useState(() => new DialClient({ apiKey: process.env.NEXT_PUBLIC_DIAL_API_KEY })); const [call, setCall] = useState(null); const [localStream, setLocalStream] = useState(null); const [remoteStream, setRemoteStream] = useState(null); useEffect(() => { dial.on('call:incoming', handleIncomingCall); dial.on('stream:local', setLocalStream); dial.on('stream:remote', setRemoteStream); return () => { dial.off('call:incoming'); dial.off('stream:local'); dial.off('stream:remote'); }; }, []); const handleIncomingCall = (incomingCall) => { setCall(incomingCall); }; const startCall = async () => { const newCall = await dial.calls.start({ to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', type: 'video' }); setCall(newCall); }; return ( <div> {!call ? ( <button onClick={startCall}>Start Video Call</button> ) : ( <div> <video ref={(el) => { if (el) el.srcObject = remoteStream }} autoPlay /> <video ref={(el) => { if (el) el.srcObject = localStream }} autoPlay muted /> <button onClick={() => call.end()}>End Call</button> </div> )} </div> ); }

Send Message

await dial.messages.send({ to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', content: 'Hey! How are you?', type: 'text' });

Real-time Chat

import { useState, useEffect } from 'react'; export function Chat({ dial, recipient }) { const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); useEffect(() => { loadHistory(); dial.on('message:received', (msg) => { if (msg.from === recipient) { setMessages(prev => [...prev, msg]); } }); }, [recipient]); const loadHistory = async () => { const history = await dial.messages.getMessages({ with: recipient, limit: 50 }); setMessages(history); }; const send = async () => { await dial.messages.send({ to: recipient, content: input, type: 'text' }); setInput(''); }; return ( <div> <div className="messages"> {messages.map(msg => ( <div key={msg.id}> <strong>{msg.from}:</strong> {msg.content} </div> ))} </div> <input value={input} onChange={(e) => setInput(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && send()} /> </div> ); }

Full Applications

Complete Calling App (React + Next.js)

// pages/_app.tsx import { DialProvider } from '@dial/sdk/react'; export default function App({ Component, pageProps }) { return ( <DialProvider apiKey={process.env.NEXT_PUBLIC_DIAL_API_KEY}> <Component {...pageProps} /> </DialProvider> ); } // components/CallInterface.tsx import { useState, useEffect } from 'react'; import { useDial } from '@dial/sdk/react'; export function CallInterface() { const { dial, isConnected } = useDial(); const [call, setCall] = useState(null); const [recipient, setRecipient] = useState(''); const [isMuted, setIsMuted] = useState(false); const [isVideoEnabled, setIsVideoEnabled] = useState(true); useEffect(() => { if (!dial) return; dial.on('call:incoming', setCall); dial.on('call:ended', () => setCall(null)); return () => { dial.off('call:incoming'); dial.off('call:ended'); }; }, [dial]); const startCall = async (type) => { const newCall = await dial.calls.start({ to: recipient, type }); setCall(newCall); }; const answerCall = () => dial.calls.answer(call.id); const declineCall = () => dial.calls.decline(call.id); const endCall = () => dial.calls.end(call.id); const toggleMute = async () => { await dial.calls.toggleMute(call.id); setIsMuted(!isMuted); }; const toggleVideo = async () => { await dial.calls.toggleVideo(call.id); setIsVideoEnabled(!isVideoEnabled); }; if (!isConnected) { return <div>Connecting to Dial...</div>; } if (!call) { return ( <div className="call-setup"> <input type="text" placeholder="Enter wallet address" value={recipient} onChange={(e) => setRecipient(e.target.value)} /> <button onClick={() => startCall('audio')}> šŸ“ž Audio Call </button> <button onClick={() => startCall('video')}> šŸ“¹ Video Call </button> </div> ); } if (call.status === 'ringing' && call.direction === 'incoming') { return ( <div className="incoming-call"> <h2>Incoming Call</h2> <p>From: {call.from}</p> <button onClick={answerCall}>āœ… Answer</button> <button onClick={declineCall}>āŒ Decline</button> </div> ); } return ( <div className="active-call"> <div className="video-container"> <video ref={(el) => { if (el && call) { el.srcObject = dial.calls.getRemoteStream(call.id); } }} autoPlay className="remote-video" /> {call.type === 'video' && ( <video ref={(el) => { if (el && call) { el.srcObject = dial.calls.getLocalStream(call.id); } }} autoPlay muted className="local-video" /> )} </div> <div className="call-controls"> <button onClick={toggleMute}> {isMuted ? 'šŸ”‡' : 'šŸŽ¤'} </button> {call.type === 'video' && ( <button onClick={toggleVideo}> {isVideoEnabled ? 'šŸ“¹' : '🚫'} </button> )} <button onClick={endCall} className="end-call"> šŸ“ž End Call </button> </div> </div> ); } // pages/index.tsx export default function Home() { return ( <div> <h1>Dial Video Calling</h1> <CallInterface /> </div> ); }

NFT-Gated Video Room

import { useAccount } from 'wagmi'; import { useDial } from '@dial/sdk/react'; export function GatedRoom() { const { address } = useAccount(); const { dial } = useDial(); const [room, setRoom] = useState(null); const [hasAccess, setHasAccess] = useState(false); useEffect(() => { checkAccess(); }, [address]); const checkAccess = async () => { if (!address) return; const access = await dial.gatedRooms.checkAccess({ roomId: 'your-room-id', walletAddress: address }); setHasAccess(access.allowed); }; const joinRoom = async () => { if (!hasAccess) { alert('You need to hold the required NFT'); return; } const joinedRoom = await dial.gatedRooms.join({ roomId: 'your-room-id', walletAddress: address }); setRoom(joinedRoom); }; if (!address) { return <div>Please connect your wallet</div>; } if (!hasAccess) { return ( <div> <h2>šŸ”’ Access Denied</h2> <p>You need to hold an NFT from the collection to enter</p> </div> ); } return ( <div> <h2>āœ… Access Granted</h2> {!room ? ( <button onClick={joinRoom}>Join Room</button> ) : ( <ConferenceView room={room} /> )} </div> ); }

Live Streaming Dashboard

export function StreamDashboard() { const { dial } = useDial(); const [stream, setStream] = useState(null); const [isLive, setIsLive] = useState(false); const [viewers, setViewers] = useState(0); const createStream = async () => { const newStream = await dial.streaming.create({ title: 'My Live Stream', description: 'Going live!', isPublic: true }); setStream(newStream); }; const goLive = async () => { await dial.streaming.start({ streamId: stream.id, video: true, audio: true, quality: '1080p' }); setIsLive(true); }; useEffect(() => { if (!stream) return; dial.on('stream:viewer:count', ({ count }) => { setViewers(count); }); }, [stream]); return ( <div> {!stream ? ( <button onClick={createStream}>Create Stream</button> ) : ( <div> <h2>{stream.title}</h2> <p>Stream Key: {stream.streamKey}</p> {isLive && <div>šŸ”“ LIVE • {viewers} viewers</div>} <button onClick={isLive ? endStream : goLive}> {isLive ? 'End Stream' : 'Go Live'} </button> </div> )} </div> ); }

Integration Examples

With wagmi (Ethereum + SIWE)

import { useAccount, useSignMessage, useChainId } from 'wagmi'; import { useDial } from '@dial/sdk/react'; import { SiweMessage } from 'siwe'; export function WalletIntegration() { const { address } = useAccount(); const { signMessageAsync } = useSignMessage(); const chainId = useChainId(); const { dial } = useDial(); const authenticate = async () => { // Get nonce from Dial const nonce = await dial.auth.getNonce(); // Create SIWE message const siweMessage = new SiweMessage({ domain: 'dial.wtf', address, statement: 'Sign in to Dial', uri: 'https://dial.wtf', version: '1', chainId, nonce, issuedAt: new Date().toISOString(), }); const message = siweMessage.prepareMessage(); const signature = await signMessageAsync({ message }); const userDialer = await dial.asUser({ siwe: { message, signature } }); return userDialer; }; return ( <button onClick={authenticate}> Connect to Dial </button> ); }

With Solana Wallet Adapter (SIWS)

import { useWallet } from '@solana/wallet-adapter-react'; import { useDial } from '@dial/sdk/react'; import { SigninMessage } from '@solana/wallet-standard-util'; import bs58 from 'bs58'; export function SolanaIntegration() { const { publicKey, signMessage } = useWallet(); const { dial } = useDial(); const authenticate = async () => { if (!publicKey || !signMessage) return; // Get nonce from Dial const nonce = await dial.auth.getNonce(); // Create SIWS message const siwsMessage = new SigninMessage({ domain: 'dial.wtf', address: publicKey.toBase58(), statement: 'Sign in to Dial', uri: 'https://dial.wtf', version: '1', chainId: 'mainnet', nonce, issuedAt: new Date().toISOString(), }); const messageText = siwsMessage.prepare(); const messageBytes = new TextEncoder().encode(messageText); const signatureBytes = await signMessage(messageBytes); const signature = bs58.encode(signatureBytes); const userDialer = await dial.asUser({ siws: { message: messageText, signature } }); return userDialer; }; return ( <button onClick={authenticate}> Connect to Dial </button> ); }

More Examples

Browse our example repositories:

Next Steps

Last updated on