Skip to content

Commit

Permalink
add EnsController and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rekmarks committed Sep 5, 2019
1 parent d680065 commit a181468
Show file tree
Hide file tree
Showing 4 changed files with 367 additions and 0 deletions.
14 changes: 14 additions & 0 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

125 changes: 125 additions & 0 deletions src/third-party/EnsController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import BaseController, { BaseConfig, BaseState } from '../BaseController';
import { isValidAddress, toChecksumAddress } from 'ethereumjs-util';

/**
* @type EnsEntry
*
* ENS entry representation
*
* @property chainId - Id of the associated chain
* @property ensName - The ENS name
* @property address - Hex address with the ENS name
*/
export interface EnsEntry {
chainId: string;
ensName: string;
address: string | null;
}

/**
* @type EnsState
*
* ENS controller state
*
* @property ensEntries - Object of ENS entry objects
*/
export interface EnsState extends BaseState {
ensEntries: { [chainId: string]: { [ensName: string]: EnsEntry } };
}

/**
* Controller that manages a list ENS names and their resolved addresses
* by chainId
*/
export class EnsController extends BaseController<BaseConfig, EnsState> {
/**
* Name of this controller used during composition
*/
name = 'EnsController';

/**
* Creates an EnsController instance
*
* @param config - Initial options used to configure this controller
* @param state - Initial state to set on this controller
*/
constructor(config?: Partial<BaseConfig>, state?: Partial<EnsState>) {
super(config, state);

this.defaultState = { ensEntries: {} };

this.initialize();
}

/**
* Remove all chain Ids and ENS entries from state
*/
clear() {
this.update({ ensEntries: {} });
}

/**
* Remove a contract entry by address
*
* @param chainId - Parent chain of the ENS entry to delete
* @param ensName - Name of the ENS entry to delete
*/
delete(chainId: string, ensName: string) {
if (!this.state.ensEntries[chainId] || !this.state.ensEntries[chainId][ensName]) {
return false;
}

const ensEntries = Object.assign({}, this.state.ensEntries);
delete ensEntries[chainId][ensName];

if (Object.keys(ensEntries[chainId]).length === 0) {
delete ensEntries[chainId];
}

this.update({ ensEntries });
return true;
}

/**
* Add or update an ENS entry by chainId and ensName
*
* @param chainId - Id of the associated chain
* @param ensName - The ENS name
* @param address - Associated address to add or update
* @returns - Boolean indicating whether the entry was set
*/
set(chainId: string, ensName: string, address: string | null): boolean {
if (
!Number.isInteger(Number.parseInt(chainId, 10)) ||
!ensName ||
typeof ensName !== 'string' ||
(address && !isValidAddress(address))
) {
throw new Error(`Invalid ENS entry: { chainId:${chainId}, ensName:${ensName}, address:${address}}`);
}

const normalizedAddress = address ? toChecksumAddress(address) : null;
const subState = this.state.ensEntries[chainId];

if (subState && subState[ensName] && subState[ensName].address === normalizedAddress) {
return false;
}

this.update({
ensEntries: {
...this.state.ensEntries,
[chainId]: {
...this.state.ensEntries[chainId],
[ensName]: {
address: normalizedAddress,
chainId,
ensName
}
}
}
});
return true;
}
}

export default EnsController;
9 changes: 9 additions & 0 deletions tests/ComposableController.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { stub } from 'sinon';
import AddressBookController from '../src/user/AddressBookController';
import EnsController from '../src/third-party/EnsController';
import ComposableController from '../src/ComposableController';
import PreferencesController from '../src/user/PreferencesController';
import TokenRatesController from '../src/assets/TokenRatesController';
Expand All @@ -14,6 +15,7 @@ describe('ComposableController', () => {
new AddressBookController(),
new AssetsController(),
new AssetsContractController(),
new EnsController(),
new CurrencyRateController(),
new NetworkController(),
new PreferencesController(),
Expand All @@ -39,6 +41,9 @@ describe('ComposableController', () => {
currentCurrency: 'usd',
nativeCurrency: 'ETH'
},
EnsController: {
ensEntries: {}
},
NetworkController: {
network: 'loading',
provider: { type: 'mainnet' }
Expand All @@ -60,6 +65,7 @@ describe('ComposableController', () => {
new AddressBookController(),
new AssetsController(),
new AssetsContractController(),
new EnsController(),
new CurrencyRateController(),
new NetworkController(),
new PreferencesController(),
Expand All @@ -76,6 +82,7 @@ describe('ComposableController', () => {
conversionDate: 0,
conversionRate: 0,
currentCurrency: 'usd',
ensEntries: {},
featureFlags: {},
frequentRpcList: [],
identities: {},
Expand All @@ -98,6 +105,7 @@ describe('ComposableController', () => {
new AssetsController(),
new AssetsContractController(),
new CurrencyRateController(),
new EnsController(),
new NetworkController(),
new PreferencesController(),
new TokenRatesController()
Expand Down Expand Up @@ -127,6 +135,7 @@ describe('ComposableController', () => {
conversionDate: 0,
conversionRate: 0,
currentCurrency: 'usd',
ensEntries: {},
featureFlags: {},
frequentRpcList: [],
identities: {},
Expand Down
Loading

0 comments on commit a181468

Please sign in to comment.