Skip to main content

Contacts List

One central feature of BasicPay is a list of contacts containing a user's name and associated Stellar addresses.

User experience

There are a few ways for a user to interact with the contact list. One way is that they can add a user and address on the /dashboard/contacts page (which also checks for a valid public key!).

contact list

See it in action here: https://basicpay.pages.dev/dashboard/contacts

Code implementation

We will create a Svelte store to keep track of a user's contact list.

Creating the contacts store

As with the rest of our user-data, the contacts list will live in the browser's localStorage. We are using the svelt-local-storage-store package to facilitate this. We create a Svelte store to hold the data, and add a few custom functions to manage the list: empty, remove, add, favorite, and lookup.

note

This tutorial code is simplified for display here. The code is fully typed, documented, and commented in the source code repository.

/src/lib/stores/contactsStore.js
import { v4 as uuidv4 } from "uuid";
import { persisted } from "svelte-local-storage-store";
import { StrKey } from "stellar-sdk";
import { error } from "@sveltejs/kit";
import { get } from "svelte/store";

// We are wrapping this store in its own function which will allow us to write
// and customize our own store functions to maintain consistent behavior
// wherever the actions need to take place.
function createContactsStore() {
// Make a `persisted` store that will hold our entire contact list.
const { subscribe, set, update } = persisted("bpa:contactList", []);

return {
subscribe,

// Erases all contact entries from the list and creates a new, empty contact list.
empty: () => set([]),

// Removes the specified contact entry from the list.
remove: (id) =>
update((list) => list.filter((contact) => contact.id !== id)),

// Adds a new contact entry to the list with the provided details.
add: (contact) =>
update((list) => {
if (StrKey.isValidEd25519PublicKey(contact.address)) {
return [...list, { ...contact, id: uuidv4() }];
} else {
throw error(400, { message: "invalid public key" });
}
}),

// Toggles the "favorite" field on the specified contact.
favorite: (id) =>
update((list) => {
const i = list.findIndex((contact) => contact.id === id);
if (i >= 0) {
list[i].favorite = !list[i].favorite;
}
return list;
}),

// Searches the contact list for an entry with the specified address.
lookup: (address) => {
let list = get(contacts);
let i = list.findIndex((contact) => contact.address === address);
if (i >= 0) {
return list[i].name;
} else {
return false;
}
},
};
}

// We export `contacts` as the variable that can be used to interact with the contacts store.
export const contacts = createContactsStore();

Source: https://github.com/stellar/basic-payment-app/blob/main/src/lib/stores/contactsStore.js

Using the contacts store

On the /dashboard/contacts page

We also have a page dedicated to managing contacts. The /dashboard/contacts page will allow the user to collect and manage a list of contact entries that stores the contact's name and Stellar address. The contact can also be flagged or unflagged as a "favorite" contact to be displayed on the main /dashboard page.

/src/routes/dashboard/contacts/+page.svelte
<script>
// We import things from external packages that will be needed
import { Trash2Icon, UserPlusIcon } from "svelte-feather-icons";

// We import any Svelte components we will need
import TruncatedKey from "$lib/components/TruncatedKey.svelte";

// We import any stores we will need to read and/or write
import { contacts } from "$lib/stores/contactsStore";

// We declare a _reactive_ component variable that will hold information for
// a user-created contact entry, which can be added to the contacts store.
$: newContact = {
name: "",
address: "",
favorite: false,
id: "",
};
</script>

<!-- HTML has been omitted from this tutorial. Please check the source file -->

Source: https://github.com/stellar/basic-payment-app/blob/main/src/routes/dashboard/contacts/+page.svelte

On the /dashboard page

The contacts store is now exported from this file and can be accessed and used inside a Svelte page or component. Here is how we've implemented a "favorite contacts" component for display on the main BasicPay dashboard.

/src/routes/dashboard/components/FavoriteContacts.svelte
<script>
// We import the `contacts` store into our Svelte component
import { contacts } from "$lib/stores/contactsStore";
import TruncatedKey from "$lib/components/TruncatedKey.svelte";

// `$:` makes a Svelte variable reactive, so it will be re-computed any time
// the `$contacts` store is modified. We access a Svelte store by adding `$`
// to the beginning of the variable name.
$: favoriteContacts = $contacts?.filter((contact) => contact.favorite);
</script>

<!-- HTML has been omitted from this tutorial. Please check the source file -->

Source: https://github.com/stellar/basic-payment-app/blob/main/src/routes/dashboard/components/FavoriteContacts.svelte