import { verify as nano25519_verify } from 'nano25519'
import { Account } from './account'
+import { utf8 } from './convert'
import { Database } from './database'
/**
-* Represents a basic address book of Nano accounts. Multiple addresses can be
-* saved under one nickname.
-*/
+ * Represents a basic address book of Nano accounts. Multiple addresses can be
+ * saved under one nickname.
+ */
export class Rolodex {
/**
- * @returns {'Rolodex'}
- */
+ * @returns {'Rolodex'}
+ */
static get DB_NAME (): 'Rolodex' { return 'Rolodex' }
/**
- * Adds an address to the rolodex under a specific nickname.
- *
- * If the name exists, add the address as a new association to that name. If
- * the account exists under a different name, update the name. If no matches
- * are found at all, add a new entry.
- *
- * @param {string} name - Contact alias for the address
- * @param {string} address - Nano account address
- * @returns {Promise<boolean>} Promise for true if name and address are added to the rolodex, else false
- */
+ * Adds an address to the rolodex under a specific nickname.
+ *
+ * If the name exists, add the address as a new association to that name. If
+ * the account exists under a different name, update the name. If no matches
+ * are found at all, add a new entry.
+ *
+ * @param {string} name - Contact alias for the address
+ * @param {string} address - Nano account address
+ * @returns {Promise<boolean>} Promise for true if name and address are added to the rolodex, else false
+ */
static async add (name: string, address: string): Promise<boolean> {
if (name == null || name === '') {
throw new Error('Name is required for rolodex entries')
}
/**
- * Removes a Nano address from its related contact in the rolodex.
- *
- * @param {string} address - Nano account address
- * @returns {Promise<boolean>} Promise for true if address successfully removed, else false
- */
+ * Removes a Nano address from its related contact in the rolodex.
+ *
+ * @param {string} address - Nano account address
+ * @returns {Promise<boolean>} Promise for true if address successfully removed, else false
+ */
static async deleteAddress (address: string): Promise<boolean> {
const name = await this.getName(address)
if (name == null) {
}
/**
- * Removes a contact and its related Nano addresses from the rolodex.
- *
- * @param {string} name - Contact name to delete
- * @returns {Promise<boolean>} Promise for true if name and related addresses successfully removed, else false
- */
+ * Removes a contact and its related Nano addresses from the rolodex.
+ *
+ * @param {string} name - Contact name to delete
+ * @returns {Promise<boolean>} Promise for true if name and related addresses successfully removed, else false
+ */
static async deleteName (name: string): Promise<boolean> {
const records = await this.getAddresses(name)
records.push(name)
}
/**
- * Gets all Nano account addresses associated with a name from the rolodex.
- *
- * @param {string} name - Alias to look up
- * @returns {Promise<string[]>} Promise for a list of Nano addresses associated with the name
- */
+ * Gets all Nano account addresses associated with a name from the rolodex.
+ *
+ * @param {string} name - Alias to look up
+ * @returns {Promise<string[]>} Promise for a list of Nano addresses associated with the name
+ */
static async getAddresses (name: string): Promise<string[]> {
try {
const records = await Database.get<Record<string, string[]>>(name, this.DB_NAME)
}
/**
- * Gets all names stored in the rolodex.
- *
- * @returns {Promise<string[]>} Promise for a list of all names stored in the rolodex
- */
+ * Gets all names stored in the rolodex.
+ *
+ * @returns {Promise<string[]>} Promise for a list of all names stored in the rolodex
+ */
static async getAllNames (): Promise<string[]> {
try {
const records = await Database.getAll<string>(this.DB_NAME)
}
/**
- * Gets the name associated with a specific Nano address from the rolodex.
- *
- * @param {string} address - Nano account address
- * @returns {Promise<string|null>} Promise for the name associated with the address, or null if not found
- */
+ * Gets the name associated with a specific Nano address from the rolodex.
+ *
+ * @param {string} address - Nano account address
+ * @returns {Promise<string|null>} Promise for the name associated with the address, or null if not found
+ */
static async getName (address: string): Promise<string | null> {
try {
const records = await Database.get<Record<string, string>>(address, this.DB_NAME)
}
/**
- * Verifies whether the public key of any Nano address saved under a specific
- * name in the rolodex was used to sign a specific string.
- *
- * @param {string} name - Alias to look up
- * @param {string} signature - Signature to use for verification
- * @param {string} data - Signed data to verify
- * @returns {Promise<boolean>} True if the signature was used to sign the data, else false
- */
+ * Verifies whether the public key of any Nano address saved under a specific
+ * name in the rolodex was used to sign a specific string.
+ *
+ * @param {string} name - Alias to look up
+ * @param {string} signature - Signature to use for verification
+ * @param {string} data - Signed data to verify
+ * @returns {Promise<boolean>} True if the signature was used to sign the data, else false
+ */
static async verify (name: string, signature: string, data: string): Promise<boolean> {
const addresses = await this.getAddresses(name)
for (const address of addresses) {
const { publicKey } = new Account(address)
- if (nano25519_verify(publicKey, signature, data)) {
+ if (nano25519_verify(signature, utf8.toHex(data), publicKey)) {
return true
}
}