import { Account } from './account'
import { bytes, utf8 } from './convert'
-import { RolodexEntry } from '#types'
+import { NamedData } from '#types'
import { SafeWorker } from '#workers'
/**
* saved under one nickname.
*/
export class Rolodex {
- #entries: RolodexEntry[] = []
-
/**
* Adds an address to the rolodex under a specific nickname.
*
* the account exists under a different name, update the name. If no matches
* are found at all, add a new entry.
*
- * @param {string} name - Alias for the address
+ * @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
*/
- async add (name: string, address: string): Promise<boolean> {
+ static async add (name: string, address: string): Promise<boolean> {
if (name == null || name === '') {
throw new Error('Name is required for rolodex entries')
}
.replaceAll('\\', '\\u005c')
const account = Account.import(address)
- const existingName = await this.getName(account.address)
- if (existingName == null) {
- const { result } = await SafeWorker.assign<boolean>({
- method: 'store',
- store: 'Rolodex',
- password: '',
- [address]: utf8.toBytes(name).buffer
- })
- return result
- } else if (existingName !== name) {
- const { result: isDestroyed } = await SafeWorker.assign<boolean>({
- method: 'destroy',
- store: 'Rolodex',
- name: address
- })
- if (!isDestroyed) {
- throw new Error('Failed to replace existing rolodex entry')
+ try {
+ const existingName = await this.getName(account.address)
+ if (existingName === name) {
+ return true
}
- const { result: isUpdated } = await SafeWorker.assign<boolean>({
+ const data: NamedData = {
method: 'store',
store: 'Rolodex',
- password: '',
+ password: utf8.toBytes('').buffer,
[address]: utf8.toBytes(name).buffer
- })
- return isUpdated
- } else {
- const addresses = await this.getAddresses(name)
- if (addresses.some(a => a === account.address)) {
- return true
- } else {
- addresses.push(account.address)
- const addressesJson = JSON.stringify(addresses)
- const { result } = await SafeWorker.assign<boolean>({
- method: 'store',
- store: 'Rolodex',
- password: '',
- [name]: utf8.toBytes(addressesJson).buffer
- })
- return result
}
+ if (existingName != null) {
+ const filteredAddresses = (await this.getAddresses(existingName)).filter(a => a !== address).sort()
+ data[existingName] = utf8.toBytes(JSON.stringify(filteredAddresses)).buffer
+ }
+ const existingAddresses = await this.getAddresses(name)
+ existingAddresses.push(account.address)
+ data[name] = utf8.toBytes(JSON.stringify(existingAddresses)).buffer
+ const { result } = await SafeWorker.assign<boolean>(data)
+ return result
+ } catch (err) {
+ throw new Error('failed to add address', { cause: err })
}
}
/**
- * Gets the name associated with a specific Nano address from the rolodex.
+ * Removes a Nano address from its related contact in 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
+ * @returns {Promise<boolean>} Promise for true if address successfully removed, else false
*/
- async getName (address: string): Promise<string | null> {
- try {
- const response = await SafeWorker.assign<ArrayBuffer>({
- method: 'fetch',
- name: address,
- store: 'Rolodex',
- password: ''
- })
- return bytes.toUtf8(new Uint8Array(response[address]))
- } catch (err) {
- console.log(err)
- return null
+ static async deleteAddress (address: string): Promise<boolean> {
+ const name = await this.getName(address)
+ if (name == null) {
+ return false
+ }
+ const addresses = (await this.getAddresses(name)).filter(a => a !== address).sort()
+ const { result: isUpdated } = await SafeWorker.assign<boolean>({
+ method: 'store',
+ store: 'Rolodex',
+ password: utf8.toBytes('').buffer,
+ [name]: utf8.toBytes(JSON.stringify(addresses)).buffer
+ })
+ if (!isUpdated) {
+ throw new Error('failed to remove address from existing name')
}
+ const { result } = await SafeWorker.assign<boolean>({
+ method: 'destroy',
+ store: 'Rolodex',
+ [address]: name
+ })
+ return result
}
/**
- * Gets all Nano addresses associated with a name from the rolodex.
+ * 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 data: NamedData = {
+ method: 'destroy',
+ store: 'Rolodex',
+ [name]: name
+ }
+ const addresses = await this.getAddresses(name)
+ for (const address of addresses) {
+ data[address] = name
+ }
+ const { result } = await SafeWorker.assign<boolean>(data)
+ return result
+ }
+
+ /**
+ * 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
*/
- async getAddresses (name: string): Promise<string[]> {
+ static async getAddresses (name: string): Promise<string[]> {
try {
const response = await SafeWorker.assign<ArrayBuffer>({
method: 'fetch',
name,
store: 'Rolodex',
- password: ''
+ password: utf8.toBytes('').buffer
})
- const addressesJson = bytes.toUtf8(new Uint8Array(response[name]))
- return JSON.parse(addressesJson)
+ const addresses = response[name]
+ return addresses
+ ? JSON.parse(bytes.toUtf8(new Uint8Array(addresses))).sort()
+ : []
} catch (err) {
- console.log(err)
+ console.error(err)
return []
}
}
*
* @returns {Promise<string[]>} Promise for a list of all names stored in the rolodex
*/
- async getAllNames (): Promise<string[]> {
+ static async getAllNames (): Promise<string[]> {
try {
const response = await SafeWorker.assign<ArrayBuffer>({
method: 'export',
name: '',
store: 'Rolodex',
- password: ''
+ password: utf8.toBytes('').buffer
})
return Object.keys(response).filter(v => v.slice(0, 5) !== 'nano_')
} catch (err) {
- console.log(err)
+ console.error(err)
return []
}
}
+ /**
+ * 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 response = await SafeWorker.assign<ArrayBuffer>({
+ method: 'fetch',
+ name: address,
+ store: 'Rolodex',
+ password: utf8.toBytes('').buffer
+ })
+ const name = response[address]
+ return name
+ ? bytes.toUtf8(new Uint8Array(name))
+ : null
+ } catch (err) {
+ console.error(err)
+ return null
+ }
+ }
+
/**
* Verifies whether the public key of any Nano address saved under a specific
* name in the rolodex was used to sign a specific set of data.
* @param {...string} data - Signed data to verify
* @returns {Promise<boolean>} True if the signature was used to sign the data, else false
*/
- async verify (name: string, signature: string, ...data: string[]): Promise<boolean> {
+ static async verify (name: string, signature: string, ...data: string[]): Promise<boolean> {
const { verify } = await import('./tools.js')
- const entries = this.#entries.filter(e => e.name === name)
- for (const entry of entries) {
- const key = entry.account.publicKey
- const verified = await verify(key, signature, ...data)
+ const addresses = await this.getAddresses(name)
+ for (const address of addresses) {
+ const { publicKey } = Account.import(address)
+ const verified = await verify(publicKey, signature, ...data)
if (verified) {
return true
}
return false
}
}
+
return await this.fetch(name, store, password, true)
}
case 'destroy': {
- return { result: await this.destroy(name, store) }
+ return { result: await this.destroy(data, store) }
}
default: {
throw new Error(`unknown Safe method ${method}`)
}
}
} catch (err) {
- console.log(err)
+ console.error(err)
throw new Error('Safe error', { cause: err })
}
}
/**
* Removes data from the Safe without decrypting.
*/
- static async destroy (name: string, store: string): Promise<boolean> {
+ static async destroy (data: NamedData, store: string): Promise<boolean> {
try {
- return await this.#delete(name, store)
+ return await this.#delete(Object.keys(data), store)
} catch (err) {
- console.log(err)
+ console.error(err)
throw new Error(this.ERR_MSG)
}
}
const records: SafeRecord[] = all
? await this.#getAll(store)
: await this.#get(fields, store)
- if (records == null || records.length === 0) {
- throw new Error('Failed to find records')
+ if (records == null) {
+ throw new Error('')
}
const decryptionKeys: { [salt: string]: CryptoKey } = {}
for (const record of records) {
}
return results
} catch (err) {
- console.log(err)
+ console.error(err)
throw new Error('Failed to get records', { cause: err })
} finally {
bytes.erase(password)
return await globalThis.crypto.subtle.deriveKey(derivationAlgorithm, derivationKey, derivedKeyType, false, [purpose])
}
- static async #delete (name: string, store: string): Promise<boolean> {
+ static async #delete (names: string[], store: string): Promise<boolean> {
const transaction = this.#storage.transaction(store, 'readwrite')
const db = transaction.objectStore(store)
return new Promise((resolve, reject) => {
- const request = db.delete(name)
- request.onsuccess = (event) => {
- resolve((event.target as IDBRequest).result)
+ const requests = names.map(name => {
+ const request = db.delete(name)
+ request.onsuccess = (event) => {
+ console.log('delete request successful but not yet committed')
+ }
+ request.onerror = (event) => {
+ console.error('getAll request error before transaction committed')
+ }
+ return request
+ })
+ transaction.oncomplete = (event) => {
+ console.log('delete transaction committed')
+ for (const request of requests) {
+ if (request?.error != null) {
+ reject(request.error)
+ }
+ if (request.result !== undefined) {
+ resolve(false)
+ }
+ }
+ resolve(true)
}
- request.onerror = (event) => {
+ transaction.onerror = (event) => {
console.error('Database error')
reject((event.target as IDBRequest).error)
}
const transaction = this.#storage.transaction(store, 'readonly')
const db = transaction.objectStore(store)
return new Promise((resolve, reject) => {
- const requests = names.map(name => db.get(name))
+ const requests = names.map(name => {
+ const request = db.get(name)
+ request.onsuccess = (event) => {
+ console.log('get request successful but not yet committed')
+ }
+ request.onerror = (event) => {
+ console.error('get request error before transaction committed')
+ }
+ return request
+ })
transaction.oncomplete = (event) => {
- const results = requests.map(r => r.result)
+ console.log('get transaction committed')
+ const results = []
+ for (const request of requests) {
+ if (request?.error == null && request.result != null) {
+ results.push(request.result)
+ }
+ }
resolve(results)
}
transaction.onerror = (event) => {
return new Promise((resolve, reject) => {
const request = db.getAll()
request.onsuccess = (event) => {
- resolve((event.target as IDBRequest).result)
+ console.log('getAll request successful but transaction not yet committed')
}
request.onerror = (event) => {
+ console.error('getAll request error before transaction committed')
+ }
+ transaction.oncomplete = (event) => {
+ console.log('getAll transaction committed')
+ if (request?.error != null) {
+ reject(request.error)
+ } else if (request.result == null) {
+ reject('getAll request failed')
+ } else {
+ resolve(request.result)
+ }
+ }
+ transaction.onerror = (event) => {
console.error('Database error')
reject((event.target as IDBRequest).error)
}
const transaction = this.#storage.transaction(store, 'readwrite')
const db = transaction.objectStore(store)
return new Promise((resolve, reject) => {
- records.map(record => db.put(record, record.label))
+ const requests = records.map(record => {
+ const request = db.put(record, record.label)
+ request.onsuccess = (event) => {
+ console.log('put request successful but not yet committed')
+ }
+ request.onerror = (event) => {
+ console.error('put request error before transaction committed')
+ }
+ return request
+ })
transaction.oncomplete = (event) => {
- resolve((event.target as IDBRequest).error == null)
+ console.log('put transaction committed')
+ const results = []
+ for (const request of requests) {
+ if (request?.error == null && request.result != null) {
+ results.push(request.result)
+ }
+ }
+ resolve(results.length > 0)
}
transaction.onerror = (event) => {
console.error('Database error')
await suite('Rolodex valid contact management', async () => {
- await test('should create a rolodex and add two contacts', async () => {
- const rolodex = new Rolodex()
- assert.equal(rolodex.constructor, Rolodex)
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
-
- assert.equal(rolodex.getAllNames().length, 2)
- assert.equal(rolodex.getAllNames()[0], 'JohnDoe')
- assert.equal(rolodex.getAllNames()[1], 'JaneSmith')
- assert.equal(rolodex.getAddresses('JohnDoe').length, 1)
- assert.equal(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_0)
- assert.equal(rolodex.getAddresses('JaneSmith').length, 1)
- assert.equal(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_1)
+ await test('export returns empty array for empty rolodex (delete db if not already empty)', async () => {
+ const result = await Rolodex.getAllNames()
+
+ assert.ok(Array.isArray(result))
+ assert.equal(result.length, 0)
})
- await test('should get a name from an address', async () => {
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- assert.equal(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0), 'JohnDoe')
+ await test('add two contacts, then delete them', async () => {
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+ await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1))
+
+ let names = await Rolodex.getAllNames()
+ assert.ok(Array.isArray(names))
+ assert.equal(names.length, 2)
+ assert.equal(names[0], 'JaneSmith')
+ assert.equal(names[1], 'JohnDoe')
+
+ const addressesJohnDoe = await Rolodex.getAddresses('JohnDoe')
+ const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
+
+ assert.ok(Array.isArray(addressesJohnDoe))
+ assert.equal(addressesJohnDoe.length, 1)
+ assert.equal(addressesJohnDoe[0], NANO_TEST_VECTORS.ADDRESS_0)
+ assert.ok(Array.isArray(addressesJaneSmith))
+ assert.equal(addressesJaneSmith.length, 1)
+ assert.equal(addressesJaneSmith[0], NANO_TEST_VECTORS.ADDRESS_1)
+
+ const deleteJohnDoe = await Rolodex.deleteName('JohnDoe')
+ const deleteJaneSmith = await Rolodex.deleteName('JaneSmith')
+ assert.equal(deleteJohnDoe, true)
+ assert.equal(deleteJaneSmith, true)
+
+ names = await Rolodex.getAllNames()
+ assert.ok(Array.isArray(names))
+ assert.equal(names.length, 0)
})
- await test('should add three addresses to the same contact', async () => {
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1)
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2)
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- assert.equal(rolodex.getAddresses('JohnDoe').length, 3)
- assert.equal(rolodex.getAddresses('JohnDoe')[0], NANO_TEST_VECTORS.ADDRESS_1)
- assert.equal(rolodex.getAddresses('JohnDoe')[1], NANO_TEST_VECTORS.ADDRESS_2)
- assert.equal(rolodex.getAddresses('JohnDoe')[2], NANO_TEST_VECTORS.ADDRESS_0)
+ await test('get a name from an address', async () => {
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+
+ const name = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0)
+ assert.equal(name, 'JohnDoe')
+
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
})
- await test('should update the name on an existing entry', async () => {
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0)
- assert.equal(rolodex.getAddresses('JohnDoe').length, 0)
- assert.equal(rolodex.getAddresses('JaneSmith').length, 1)
- assert.equal(rolodex.getAddresses('JaneSmith')[0], NANO_TEST_VECTORS.ADDRESS_0)
+ await test('add three addresses to the same contact, then delete one address, then delete the contact', async () => {
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_1))
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_2))
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+
+ let addresses = await Rolodex.getAddresses('JohnDoe')
+ assert.ok(Array.isArray(addresses))
+ assert.equal(addresses.length, 3)
+ assert.equal(addresses[0], NANO_TEST_VECTORS.ADDRESS_0)
+ assert.equal(addresses[1], NANO_TEST_VECTORS.ADDRESS_2)
+ assert.equal(addresses[2], NANO_TEST_VECTORS.ADDRESS_1)
+
+ await assert.resolves(Rolodex.deleteAddress(NANO_TEST_VECTORS.ADDRESS_1))
+ addresses = await Rolodex.getAddresses('JohnDoe')
+ assert.ok(Array.isArray(addresses))
+ assert.equal(addresses.length, 2)
+ assert.equal(addresses[0], NANO_TEST_VECTORS.ADDRESS_0)
+ assert.equal(addresses[1], NANO_TEST_VECTORS.ADDRESS_2)
+
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
+ addresses = await Rolodex.getAddresses('JohnDoe')
+ const address0 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_0)
+ const address1 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1)
+ const address2 = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_2)
+
+ assert.ok(Array.isArray(addresses))
+ assert.equal(addresses.length, 0)
+ assert.nullish(address0)
+ assert.nullish(address1)
+ assert.nullish(address2)
})
- await test('should return empty address array for an unknown contact', async () => {
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- assert.equal(Array.isArray(rolodex.getAddresses('JaneSmith')), true)
- assert.equal(rolodex.getAddresses('JaneSmith').length, 0)
+ await test('update the name on an existing address', async () => {
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+ await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_0))
+ const addressesJohnDoe = await Rolodex.getAddresses('JohnDoe')
+ const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
+
+ assert.ok(Array.isArray(addressesJohnDoe))
+ assert.equal(addressesJohnDoe.length, 0)
+ assert.ok(Array.isArray(addressesJaneSmith))
+ assert.equal(addressesJaneSmith.length, 1)
+ assert.equal(addressesJaneSmith[0], NANO_TEST_VECTORS.ADDRESS_0)
+
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
+ await assert.resolves(Rolodex.deleteName('JaneSmith'))
})
- await test('should return empty address array for blank contact names', () => {
- const rolodex = new Rolodex()
- //@ts-expect-error
- assert.equal(Array.isArray(rolodex.getAddresses(undefined)), true)
- //@ts-expect-error
- assert.equal(rolodex.getAddresses(undefined).length, 0)
+ await test('return empty address array for an unknown contact', async () => {
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+ const addressesJaneSmith = await Rolodex.getAddresses('JaneSmith')
+
+ assert.equal(Array.isArray(addressesJaneSmith), true)
+ assert.equal(addressesJaneSmith.length, 0)
+
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
+ })
+
+ await test('return empty address array for blank contact names', async () => {
//@ts-expect-error
- assert.equal(Array.isArray(rolodex.getAddresses(null)), true)
+ const addressesUndefined = await Rolodex.getAddresses(undefined)
//@ts-expect-error
- assert.equal(rolodex.getAddresses(null).length, 0)
- assert.equal(Array.isArray(rolodex.getAddresses('')), true)
- assert.equal(rolodex.getAddresses('').length, 0)
+ const addressesNull = await Rolodex.getAddresses(null)
+ const addressesBlank = await Rolodex.getAddresses('')
+
+ assert.equal(Array.isArray(addressesUndefined), true)
+ assert.equal(addressesUndefined.length, 0)
+ assert.equal(Array.isArray(addressesNull), true)
+ assert.equal(addressesNull.length, 0)
+ assert.equal(Array.isArray(addressesBlank), true)
+ assert.equal(addressesBlank.length, 0)
})
await test('should return null for an unknown address', async () => {
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- assert.ok(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1) === null)
- assert.ok(rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1) !== undefined)
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+ const addressUnknown = await Rolodex.getName(NANO_TEST_VECTORS.ADDRESS_1)
+
+ assert.ok(addressUnknown === null)
+ assert.ok(addressUnknown !== undefined)
+
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
})
await test('should return null for a blank address', async () => {
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- //@ts-expect-error
- assert.ok(rolodex.getName(undefined) === null)
- //@ts-expect-error
- assert.ok(rolodex.getName(undefined) !== undefined)
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
//@ts-expect-error
- assert.ok(rolodex.getName(null) === null)
+ const nameUndefined = await Rolodex.getName(undefined)
//@ts-expect-error
- assert.ok(rolodex.getName(null) !== undefined)
- assert.ok(rolodex.getName('') === null)
- assert.ok(rolodex.getName('') !== undefined)
- })
-})
+ const nameNull = await Rolodex.getName(null)
+ const nameBlank = await Rolodex.getName('')
-await suite('Rolodex exceptions', async () => {
+ assert.ok(nameUndefined === null)
+ assert.ok(nameUndefined !== undefined)
+ assert.ok(nameNull === null)
+ assert.ok(nameNull !== undefined)
+ assert.ok(nameBlank === null)
+ assert.ok(nameBlank !== undefined)
+
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
+ })
- await test('should throw if adding no data', async () => {
- const rolodex = new Rolodex()
+ await test('throw if adding no data', async () => {
//@ts-expect-error
- await assert.rejects(rolodex.add())
+ await assert.rejects(Rolodex.add())
})
- await test('should throw if passed no address', async () => {
- const rolodex = new Rolodex()
+ await test('throw if passed no address', async () => {
//@ts-expect-error
- await assert.rejects(rolodex.add('JohnDoe'))
+ await assert.rejects(Rolodex.add('JohnDoe'))
//@ts-expect-error
- await assert.rejects(rolodex.add('JohnDoe', undefined))
+ await assert.rejects(Rolodex.add('JohnDoe', undefined))
//@ts-expect-error
- await assert.rejects(rolodex.add('JohnDoe', null))
- await assert.rejects(rolodex.add('JohnDoe', ''))
+ await assert.rejects(Rolodex.add('JohnDoe', null))
+ await assert.rejects(Rolodex.add('JohnDoe', ''))
})
- await test('should throw if name is blank', async () => {
- const rolodex = new Rolodex()
+ await test('throw if name is blank', async () => {
//@ts-expect-error
- await assert.rejects(rolodex.add(undefined, NANO_TEST_VECTORS.ADDRESS_0))
+ await assert.rejects(Rolodex.add(undefined, NANO_TEST_VECTORS.ADDRESS_0))
//@ts-expect-error
- await assert.rejects(rolodex.add(null, NANO_TEST_VECTORS.ADDRESS_0))
- await assert.rejects(rolodex.add('', NANO_TEST_VECTORS.ADDRESS_0))
+ await assert.rejects(Rolodex.add(null, NANO_TEST_VECTORS.ADDRESS_0))
+ await assert.rejects(Rolodex.add('', NANO_TEST_VECTORS.ADDRESS_0))
})
})
await test('should verify valid data and signature', async () => {
const data = 'Test data'
const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
- const rolodex = new Rolodex()
- await rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0)
- const result = await rolodex.verify('JohnDoe', signature, data)
+ await assert.resolves(Rolodex.add('JohnDoe', NANO_TEST_VECTORS.ADDRESS_0))
+ const result = await Rolodex.verify('JohnDoe', signature, data)
+ await assert.resolves(Rolodex.deleteName('JohnDoe'))
assert.equal(result, true)
})
await test('should reject incorrect contact for signature', async () => {
const data = 'Test data'
const signature = await Tools.sign(NANO_TEST_VECTORS.PRIVATE_0, data)
- const rolodex = new Rolodex()
- await rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1)
- const result = await rolodex.verify('JaneSmith', signature, data)
+ await assert.resolves(Rolodex.add('JaneSmith', NANO_TEST_VECTORS.ADDRESS_1))
+ const result = await Rolodex.verify('JaneSmith', signature, data)
+ await assert.resolves(Rolodex.deleteName('JaneSmith'))
assert.equal(result, false)
})
})