Skip to content

Commit

Permalink
implement search for AddressBookIdentityProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
topocount committed Sep 23, 2019
1 parent 4aa6065 commit 1f538bb
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const addressBookAppIds = [
/**
* An identity provider for Address Book Entries
*
* @class AddressIdentityProvider
* @extends AddressIdentityProvider
*/
export default class AddressBookIdentityProvider extends AddressIdentityProvider {
constructor (apps, cache) {
Expand Down Expand Up @@ -51,6 +51,42 @@ export default class AddressBookIdentityProvider extends AddressIdentityProvider
}, null)
}

async search (searchTerm = '') {
const isAddressSearch = searchTerm.substring(0, 2).toLowerCase() === '0x'
const identities = await this.getAll()
const results = Object.entries(identities)
.filter(
([address, { name }]) =>
(isAddressSearch &&
searchTerm.length > 3 &&
address.toLowerCase().indexOf(searchTerm.toLowerCase()) === 0) ||
name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1
)
.map(([address, { name }]) => ({ name, address }))
return results
}

/**
* get all identities from all installed address book instances
*/
async getAll () {
const addressBookApps = await this.apps.pipe(
first(),
map(apps => apps.filter(app => addressBookAppIds.includes(app.appId)))
).toPromise()

return addressBookApps.reduce(async (allEntries, app) => {
const cacheKey = getCacheKey(app.proxyAddress, 'state')
const { entries = [] } = await this.cache.get(cacheKey)
const allEntriesResolved = await allEntries
const entriesObject = entries.reduce((obj, entry) => {
return { ...obj, [entry.addr.toLowerCase()]: entry.data }
}, {})
// ensure the entries retrieved from the first-installed address book aren't overwritten
return { ...entriesObject, ...allEntriesResolved }
}, Promise.resolve({}))
}

/**
* Modify the identity metadata of an address
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ test.before(async t => {

cache = new Cache('stubbedAddressBook')
await cache.init()
cache.set('0x0.state', { entries: [{ addr: '0x3', data: { name: 'testEntity' } }] })
cache.set('0x11.state', { entries: [{ addr: '0x3', data: { name: 'testEntity2' } }] })
cache.set('0x0.state', { entries: [{ addr: '0x3a', data: { name: 'testEntity' } }, { addr: '0x33', data: { name: 'testDude' } } ] })
cache.set('0x11.state', { entries: [{ addr: '0x3a', data: { name: 'testEntity2' } }] })
})

test.beforeEach(async t => {
Expand All @@ -33,7 +33,7 @@ test.beforeEach(async t => {

test('should resolve identity from first address book in app array', async t => {
const provider = t.context.addressBookIdentityProvider
const identityMetadata = await provider.resolve('0x3')
const identityMetadata = await provider.resolve('0x3a')
t.is(identityMetadata.name, 'testEntity')
})

Expand All @@ -47,3 +47,26 @@ test('should throw error on any modify attempt', async t => {
const provider = t.context.addressBookIdentityProvider
await t.throwsAsync(() => provider.modify('0x9', { name: 'newEntity' }))
})

test('getAll should return a combined Object containing all entries', async t => {
const provider = t.context.addressBookIdentityProvider
const allIdentities = await provider.getAll()
t.deepEqual(allIdentities, {
'0x3a': { name: 'testEntity' },
'0x33': { name: 'testDude' }
})
})

test('search should return an aray of results of freely matching identities', async t => {
t.plan(3)
const provider = t.context.addressBookIdentityProvider
let result = await provider.search('0x3a')
t.deepEqual(result, [ { name: 'testEntity', address: '0x3a' } ])

result = await provider.search('test')
t.deepEqual(result, [ { name: 'testEntity', address: '0x3a' },
{ name: 'testDude', address: '0x33' } ])

result = await provider.search('testd')
t.deepEqual(result, [{ name: 'testDude', address: '0x33' } ])
})
24 changes: 17 additions & 7 deletions packages/aragon-wrapper/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -946,13 +946,23 @@ export default class Aragon {
* @param {string} searchTerm
* @return {Promise} Resolves with the identity or null if not found
*/
searchIdentities (searchTerm) {
const providerName = 'local' // TODO - get provider
const provider = this.identityProviderRegistrar.get(providerName)
if (provider && typeof provider.search === 'function') {
return provider.search(searchTerm)
}
return Promise.reject(new Error(`Provider (${providerName}) not installed`))
async searchIdentities (searchTerm) {
const providerNames = [ 'local', 'addressBook' ] // TODO - get provider
const resolvedResults = await Promise.all(
providerNames.map( (providerName) => {
const provider = this.identityProviderRegistrar.get(providerName)
if (provider && typeof provider.search === 'function') {
return provider.search(searchTerm)
}
return Promise.reject(new Error(`Provider (${providerName}) not installed`))
})
)
return resolvedResults.reduce(
(combinedResults, providerResult) => {
return [ ...combinedResults, ...providerResult ]
},
[]
)
}

/**
Expand Down
80 changes: 80 additions & 0 deletions packages/aragon-wrapper/src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,86 @@ test('should init the identity providers correctly', async (t) => {
t.is(instance.identityProviderRegistrar.size, 2, 'Should have only two providers')
})

test('should search identities correctly', async (t) => {
const { createAragon } = t.context

t.plan(2)
// arrange
const instance = createAragon()
instance.apps = of([
{
appId: '0x32ec8cc9f3136797e0ae30e7bf3740905b0417b81ff6d4a74f6100f9037425de',
proxyAddress: '0x001'
}, {
appId: 'votingApp',
isForwarder: false
}
])
await instance.cache.init()
await instance.cache.set('0x001.state', {
entries: [
{ addr: '0x789', data: { name: 'testEntity' } },
{ addr: '0x456', data: { name: 'testDude' } }
]
})
await instance.initIdentityProviders()

// act
await instance.modifyAddressIdentity('0x123', { name: 'testperson' })
await instance.modifyAddressIdentity('0x456', { name: 'testDao' })
// assert
//console.log(await instance.cache.get('0x001.state'))
let result = await instance.searchIdentities('test')

t.deepEqual(result, [ { name: 'testperson', address: '0x123' },
{ name: 'testDao', address: '0x456' },
{ name: 'testEntity', address: '0x789' },
{ name: 'testDude', address: '0x456' } ])

result = await instance.searchIdentities('0x456')
t.deepEqual(result, [
{ name: 'testDao', address: '0x456' },
{ name: 'testDude', address: '0x456' }
])
})

test('should resolve identity correctly', async (t) => {
const { createAragon } = t.context

t.plan(2)
// arrange
const instance = createAragon()
instance.apps = of([
{
appId: '0x32ec8cc9f3136797e0ae30e7bf3740905b0417b81ff6d4a74f6100f9037425de',
proxyAddress: '0x001'
}, {
appId: 'votingApp',
isForwarder: false
}
])
await instance.cache.init()
await instance.cache.set('0x001.state', {
entries: [
{ addr: '0x789', data: { name: 'testEntity' } },
{ addr: '0x456', data: { name: 'testDude' } }
]
})
await instance.initIdentityProviders()

// act
await instance.modifyAddressIdentity('0x123', { name: 'testperson' })
await instance.modifyAddressIdentity('0x456', { name: 'testDao' })
// assert
//console.log(await instance.cache.get('0x001.state'))
let result = await instance.resolveAddressIdentity('0x456')
console.log('wrapper result: ', result)
t.is(result.name, 'testDao', 'should resolve to local label')

result = await instance.resolveAddressIdentity('0x789')
t.is(result.name, 'testEntity', 'should resolve to address book entry')
})

test('should emit an intent when requesting address identity modification', async (t) => {
const { createAragon } = t.context
const expectedAddress = '0x123'
Expand Down

0 comments on commit 1f538bb

Please sign in to comment.