Dial Profile
Every wallet address on Dial has an associated profile used for calls, messaging, and all communication features. Profiles provide human-readable identity information tied to your wallet.
Profile Overview
A Dial Profile includes:
- Display Name - Your preferred name shown to others
- Avatar - Profile picture/image
- Bio - Short description
- Status - Current availability status
- Links - Social media and Web3 profiles
- Preferences - Communication settings
Getting Started
View Your Profile
const profile = await userDialer.profile.get();
console.log(profile.displayName); // "Alice.eth"
console.log(profile.avatar); // "https://..."
console.log(profile.status); // "online"View Another User’s Profile
const bobProfile = await userDialer.profile.getProfile({
walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
});
console.log(bobProfile.displayName);
console.log(bobProfile.bio);Profile Object
interface DialProfile {
walletAddress: string;
displayName: string;
avatar?: string;
bio?: string;
status: 'online' | 'away' | 'busy' | 'offline';
customStatus?: string;
links?: {
twitter?: string;
github?: string;
discord?: string;
website?: string;
ens?: string;
};
preferences?: ProfilePreferences;
createdAt: Date;
updatedAt: Date;
}
interface ProfilePreferences {
allowCalls: boolean;
allowMessages: boolean;
allowGroupInvites: boolean;
showOnlineStatus: boolean;
notificationSettings: NotificationSettings;
}Updating Your Profile
Update Display Name
await userDialer.profile.update({
displayName: 'Alice.eth'
});Update Avatar
// Upload from file
await userDialer.profile.updateAvatar({
file: avatarFile // File or Blob
});
// Or use URL
await userDialer.profile.update({
avatar: 'https://example.com/avatar.jpg'
});Update Bio
await userDialer.profile.update({
bio: 'Building the future of Web3 communication 🚀'
});Update Multiple Fields
await userDialer.profile.update({
displayName: 'Alice.eth',
bio: 'Web3 developer & builder',
links: {
twitter: '@alice_eth',
github: 'alice',
website: 'https://alice.com'
}
});Status Management
Set Status
// Predefined statuses
await userDialer.profile.setStatus('online');
await userDialer.profile.setStatus('away');
await userDialer.profile.setStatus('busy');
await userDialer.profile.setStatus('offline');
// Custom status message
await userDialer.profile.setStatus('online', {
customMessage: 'In a meeting until 3pm'
});Get Status
const status = await userDialer.profile.getStatus();
console.log(status.current); // 'online'
console.log(status.message); // 'In a meeting until 3pm'Listen for Status Changes
userDialer.on('profile:status', ({ walletAddress, status }) => {
console.log(`${walletAddress} is now ${status}`);
});Privacy & Preferences
Communication Preferences
await userDialer.profile.updatePreferences({
allowCalls: true,
allowMessages: true,
allowGroupInvites: false, // Don't allow group invites from strangers
showOnlineStatus: true
});Block List Management
// Block a user
await userDialer.profile.blockUser('0x...');
// Unblock a user
await userDialer.profile.unblockUser('0x...');
// Get blocked users
const blockedUsers = await userDialer.profile.getBlockedUsers();Privacy Settings
await userDialer.profile.updatePrivacy({
profileVisibility: 'public', // 'public', 'contacts', 'private'
callPrivacy: 'contacts', // Who can call you
messagePrivacy: 'everyone', // Who can message you
lastSeenVisibility: 'contacts' // Who can see when you were last online
});Notification Settings
Configure Notifications
await userDialer.profile.updateNotificationSettings({
calls: {
enabled: true,
sound: true,
vibrate: true,
showPreview: true
},
messages: {
enabled: true,
sound: true,
vibrate: true,
showPreview: false // Hide message content in notifications
},
groupMessages: {
enabled: true,
mentionsOnly: true // Only notify when mentioned
},
voicemail: {
enabled: true,
sound: true
}
});Do Not Disturb
// Enable DND
await userDialer.profile.enableDoNotDisturb({
until: new Date('2024-12-01T09:00:00'), // Optional end time
allowContacts: true, // Allow calls/messages from contacts
allowEmergency: true // Allow emergency contacts
});
// Disable DND
await userDialer.profile.disableDoNotDisturb();Profile Verification
ENS Integration
// Link ENS name
await userDialer.profile.linkENS({
ensName: 'alice.eth'
});
// Profile automatically shows verified ENS
const profile = await userDialer.profile.get();
console.log(profile.links.ens); // 'alice.eth'
console.log(profile.verified.ens); // trueSocial Verification
// Verify Twitter
await userDialer.profile.verifyTwitter({
handle: '@alice_eth'
});
// Verify GitHub
await userDialer.profile.verifyGithub({
username: 'alice'
});Contact Management
Add Contact
await userDialer.profile.addContact({
walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
nickname: 'Bob', // Optional custom name
tags: ['friend', 'web3'] // Optional tags
});Get Contacts
const contacts = await userDialer.profile.getContacts();
contacts.forEach(contact => {
console.log(contact.walletAddress);
console.log(contact.profile.displayName);
console.log(contact.nickname); // Your custom nickname
});Update Contact
await userDialer.profile.updateContact({
walletAddress: '0x...',
nickname: 'Bobby',
tags: ['friend', 'developer'],
notes: 'Met at ETHDenver 2024'
});Remove Contact
await userDialer.profile.removeContact('0x...');Profile Search
Search for Users
// Search by display name
const results = await dial.registry.searchProfiles({
query: 'alice',
limit: 20
});
results.forEach(profile => {
console.log(profile.walletAddress);
console.log(profile.displayName);
});Search by ENS
const profile = await dial.registry.getProfileByENS('alice.eth');
console.log(profile.walletAddress);Profile Events
Subscribe to profile-related events:
// Profile updated
userDialer.on('profile:updated', (profile) => {
console.log('Profile updated:', profile);
});
// Status changed
userDialer.on('profile:status', ({ walletAddress, status }) => {
console.log(`${walletAddress} status: ${status}`);
});
// Contact added
userDialer.on('profile:contact:added', (contact) => {
console.log('New contact:', contact);
});
// Contact removed
userDialer.on('profile:contact:removed', ({ walletAddress }) => {
console.log('Contact removed:', walletAddress);
});Complete Example: React Profile Component
import { useState, useEffect } from 'react';
import { DialProfile } from '@dial/sdk';
export function ProfileEditor({ userDialer }) {
const [profile, setProfile] = useState<DialProfile | null>(null);
const [displayName, setDisplayName] = useState('');
const [bio, setBio] = useState('');
const [status, setStatus] = useState<'online' | 'away' | 'busy' | 'offline'>('online');
useEffect(() => {
loadProfile();
}, [userDialer]);
const loadProfile = async () => {
const currentProfile = await userDialer.profile.get();
setProfile(currentProfile);
setDisplayName(currentProfile.displayName);
setBio(currentProfile.bio || '');
setStatus(currentProfile.status);
};
const handleSave = async () => {
await userDialer.profile.update({
displayName,
bio
});
await userDialer.profile.setStatus(status);
// Reload profile
await loadProfile();
};
const handleAvatarUpload = async (file: File) => {
await userDialer.profile.updateAvatar({ file });
await loadProfile();
};
if (!profile) return <div>Loading...</div>;
return (
<div className="profile-editor">
<h2>Edit Profile</h2>
<div className="avatar-section">
<img src={profile.avatar} alt="Avatar" />
<input
type="file"
accept="image/*"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) handleAvatarUpload(file);
}}
/>
</div>
<div className="form-field">
<label>Display Name</label>
<input
type="text"
value={displayName}
onChange={(e) => setDisplayName(e.target.value)}
placeholder="Your display name"
/>
</div>
<div className="form-field">
<label>Bio</label>
<textarea
value={bio}
onChange={(e) => setBio(e.target.value)}
placeholder="Tell us about yourself"
rows={4}
/>
</div>
<div className="form-field">
<label>Status</label>
<select
value={status}
onChange={(e) => setStatus(e.target.value as any)}
>
<option value="online">Online</option>
<option value="away">Away</option>
<option value="busy">Busy</option>
<option value="offline">Offline</option>
</select>
</div>
<button onClick={handleSave}>Save Changes</button>
<div className="profile-info">
<p>Wallet: {profile.walletAddress}</p>
<p>Member since: {profile.createdAt.toLocaleDateString()}</p>
</div>
</div>
);
}Profile Storage
Profiles are stored on-chain with optional decentralized storage:
- On-chain: Basic profile data (name, status)
- IPFS: Avatar images and media
- s3worm: Additional metadata and preferences
All profile data is associated with your wallet address and can be updated at any time.
Wallet-Based Identity
Dial Profiles leverage wallet addresses as the core identity:
- âś… No email required - Your wallet is your identity
- âś… No phone number required - Web3-native communication
- âś… Cross-platform - Same profile across all apps using Dial
- âś… Self-sovereign - You own and control your data
- âś… Portable - Take your profile anywhere
Next Steps
Last updated on