Skip to main content

useContacts Hook

The useContacts hook provides contact management functionality.

Basic Usage

import { useContacts } from '@testinprod-io/privacy-boost-react';

function ContactList() {
  const { contacts, addContact, removeContact } = useContacts();

  return (
    <ul>
      {contacts.map((contact) => (
        <li key={contact.id}>
          {contact.name}: {contact.privacyAddress.slice(0, 20)}...
        </li>
      ))}
    </ul>
  );
}

Return Value

interface UseContactsResult {
  // Reactive data
  contacts: Contact[];

  // CRUD operations
  addContact(params: CreateContactParams): Promise<Contact>;
  removeContact(privacyAddress: string): Promise<void>;
  updateContact(privacyAddress: string, params: UpdateContactParams): Promise<Contact>;

  // Query functions
  findByAddress(privacyAddress: string): Contact | undefined;
  search(query: string): Contact[];
}

Contact Type

interface Contact {
  id: string;
  name: string;
  privacyAddress: PrivacyAddress;
  note?: string;
  createdAt: number;
  updatedAt: number;
}

Adding Contacts

const { addContact } = useContacts();

const handleAddContact = async () => {
  await addContact({
    name: 'Alice',
    privacyAddress: '0x04...alice-address',
    note: 'Friend from work',
  });
};

Removing Contacts

const { removeContact } = useContacts();

const handleRemove = async (privacyAddress: string) => {
  if (confirm('Remove this contact?')) {
    await removeContact(privacyAddress);
  }
};

Updating Contacts

const { updateContact } = useContacts();

const handleUpdate = async (privacyAddress: string) => {
  await updateContact(privacyAddress, {
    name: 'New Name',
    note: 'Updated note',
  });
};

Searching Contacts

const { contacts, search } = useContacts();
const [query, setQuery] = useState('');

const filteredContacts = query ? search(query) : contacts;

Complete Example

import { useState } from 'react';
import { useContacts } from '@testinprod-io/privacy-boost-react';
import { isValidPrivacyAddress } from '@testinprod-io/privacy-boost';

function ContactsManager() {
  const {
    contacts,
    addContact,
    removeContact,
    search,
  } = useContacts();

  const [searchQuery, setSearchQuery] = useState('');
  const [newName, setNewName] = useState('');
  const [newAddress, setNewAddress] = useState('');
  const [error, setError] = useState('');

  const filteredContacts = searchQuery ? search(searchQuery) : contacts;

  const handleAdd = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');

    if (!newName.trim()) {
      setError('Name is required');
      return;
    }

    if (!isValidPrivacyAddress(newAddress)) {
      setError('Invalid privacy address');
      return;
    }

    try {
      await addContact({
        name: newName.trim(),
        privacyAddress: newAddress,
      });
      setNewName('');
      setNewAddress('');
    } catch (err) {
      setError(err.message);
    }
  };

  return (
    <div>
      {/* Search */}
      <input
        type="text"
        value={searchQuery}
        onChange={(e) => setSearchQuery(e.target.value)}
        placeholder="Search contacts..."
      />

      {/* Contact List */}
      <ul>
        {filteredContacts.map((contact) => (
          <li key={contact.id}>
            <strong>{contact.name}</strong>
            <span>{contact.privacyAddress.slice(0, 20)}...</span>
            {contact.note && <small>{contact.note}</small>}
            <button onClick={() => removeContact(contact.privacyAddress)}>
              Remove
            </button>
          </li>
        ))}
      </ul>

      {/* Add Form */}
      <form onSubmit={handleAdd}>
        <h4>Add Contact</h4>
        <input
          type="text"
          value={newName}
          onChange={(e) => setNewName(e.target.value)}
          placeholder="Name"
        />
        <input
          type="text"
          value={newAddress}
          onChange={(e) => setNewAddress(e.target.value)}
          placeholder="Privacy address"
        />
        {error && <p style={{ color: 'red' }}>{error}</p>}
        <button type="submit">Add Contact</button>
      </form>
    </div>
  );
}

Contact Picker for Transfers

function ContactPicker({
  onSelect,
}: {
  onSelect: (address: string) => void;
}) {
  const { contacts } = useContacts();

  if (contacts.length === 0) {
    return <p>No contacts saved</p>;
  }

  return (
    <select onChange={(e) => onSelect(e.target.value)}>
      <option value="">Select a contact...</option>
      {contacts.map((contact) => (
        <option key={contact.id} value={contact.privacyAddress}>
          {contact.name}
        </option>
      ))}
    </select>
  );
}

// Usage in transfer form
function TransferWithContacts() {
  const [recipient, setRecipient] = useState('');
  const { send } = useVault();

  return (
    <div>
      <ContactPicker onSelect={setRecipient} />
      <input
        value={recipient}
        onChange={(e) => setRecipient(e.target.value)}
        placeholder="Or enter address..."
      />
      <button onClick={() => send({ to: recipient, ... })}>
        Send
      </button>
    </div>
  );
}

Next Steps