import { asyncForEach } from '@imtbl/utils' ; import { Provider } from 'ethers/providers' ; import fs from 'fs-extra' ; import dependencies from './dependencies' ; import { DeploymentEnvironment , DeploymentNetwork } from './params' ; export class BookData { environments : any ; constructor ( ) { this . environments = new Map < string , BookEnvironment > ( ) ; } } export class BookEnvironment { public readonly addresses : any ; public readonly dependencies : any ; constructor ( ) { this . addresses = { } ; this . dependencies = { } ; } } export class AddressBook { readonly root : string ; private env : DeploymentEnvironment ; private network_id : DeploymentNetwork ; constructor ( root , env , network_id ) { this . root = root ; this . env = env ; this . network_id = network_id ; } public use ( env , network_id ) { this . env = env ; this . network_id = network_id ; } public async set ( name , address ) { const book = await this . load ( ) ; const env = book . environments [ this . env ] ; if ( ! env ) { book . environments [ this . env ] = new BookEnvironment ( ) ; } book . environments [ this . env ] . addresses [ name ] = address ; this . save ( book ) ; } public async setDependency ( name , address ) { const book = await this . load ( ) ; const env = book . environments [ this . env ] ; if ( ! env ) { book . environments [ this . env ] = new BookEnvironment ( ) ; } book . environments [ this . env ] . dependencies [ name ] = address ; this . save ( book ) ; } public async remove ( name ) { const book = await this . load ( ) ; const env = book . environments [ this . env ] ; if ( ! env ) { return false ; } env . addresses [ name ] = null ; this . save ( book ) ; return true ; } public async removeDependency ( name ) { const book = await this . load ( ) ; const env = book . environments [ this . env ] ; if ( ! env ) { return false ; } env . dependencies [ name ] = null ; this . save ( book ) ; return true ; } public async get ( name ) { const book = await this . load ( ) ; const env = book . environments [ this . env ] ; if ( ! env ) { return null ; } return env . addresses [ name ] ; } public async getDependency ( name ) { let dependencyValue = dependencies [ name ] ; if ( dependencyValue ) { dependencyValue = dependencyValue [ this . network_id ] ; return dependencyValue ; } const book = await this . load ( ) ; const env = book . environments [ this . env ] ; if ( ! env ) { return null ; } return env . dependencies [ name ] ; } public async clear ( ) { let book = await this . load ( ) ; book . environments [ this . env ] = null ; this . save ( book ) ; } public async validate ( provider ) { const book = await this . load ( ) ; if ( ! book . environments [ this . env ] ) { return ; } const entries = Object . entries ( book . environments [ this . env ] . addresses ) ; await asyncForEach ( entries , async ( [ name , address ] ) => { const code = await provider . getCode ( address ) ; if ( code . length < 3 ) { await this . remove ( name ) ; } } ) ; } private async load ( ) { await fs . ensureFile ( this . root ) ; let data ; try { data = await fs . readJson ( this . root , { throws : true } ) ; } catch ( error ) { data = new BookData ( ) ; } return data ; } private async save ( book ) { await fs . outputFile ( this . root , JSON . stringify ( book , null , 2 ) ) ; } }