import { autorun , flow , makeObservable , observable , toJS } from "mobx" ; import { KVStore , toGenerator } from "@keplr-wallet/common" ; import { ChainInfo } from "@keplr-wallet/types" ; import { ChainGetter , HasMapStore } from "@keplr-wallet/stores" ; import { DeepReadonly } from "utility-types" ; import { useState } from "react" ; export interface AddressBookSelectHandler { setRecipient ( recipient ) : void ; setMemo ( memo ) : void ; } export interface AddressBookData { name : string ; address : string ; memo : string ; } export class AddressBookConfig { @ observable protected _addressBookDatas : AddressBookData [ ] = [ ] ; @ observable protected _isLoaded : boolean = false ; protected _selectHandler ? : AddressBookSelectHandler ; constructor ( protected readonly kvStore , protected readonly chainGetter , protected readonly chainId ) { makeObservable ( this ) ; this . loadAddressBookDatas ( ) ; } get isLoaded ( ) : boolean { return this . _isLoaded ; } get addressBookDatas ( ) : DeepReadonly < AddressBookData [ ] > { return this . _addressBookDatas ; } setSelectHandler ( handler ) { this . _selectHandler = handler ; } selectAddressAt ( index ) { const data = this . addressBookDatas [ index ] ; if ( this . _selectHandler ) { this . _selectHandler . setRecipient ( data . address ) ; this . _selectHandler . setMemo ( data . memo ) ; } } @ flow * addAddressBook ( data ) { yield this . loadAddressBookDatas ( ) ; this . _addressBookDatas . push ( data ) ; yield this . saveAddressBookDatas ( ) ; } @ flow * removeAddressBook ( index ) { yield this . loadAddressBookDatas ( ) ; this . _addressBookDatas . splice ( index , 1 ) ; yield this . saveAddressBookDatas ( ) ; } @ flow * editAddressBookAt ( index , data ) { yield this . loadAddressBookDatas ( ) ; this . _addressBookDatas [ index ] = data ; yield this . saveAddressBookDatas ( ) ; } async saveAddressBookDatas ( ) { const chainInfo = this . chainGetter . getChain ( this . chainId ) ; await this . kvStore . set ( AddressBookConfig . keyForChainInfo ( chainInfo ) , toJS ( this . _addressBookDatas ) ) ; } @ flow * loadAddressBookDatas ( ) { const chainInfo = this . chainGetter . getChain ( this . chainId ) ; const datas = yield * toGenerator ( this . kvStore . get < AddressBookData [ ] > ( AddressBookConfig . keyForChainInfo ( chainInfo ) ) ) ; if ( ! datas ) { this . _addressBookDatas = [ ] ; } else { this . _addressBookDatas = datas ; } this . _isLoaded = true ; } async waitLoaded ( ) { if ( this . _isLoaded ) { return ; } return new Promise < void > ( ( resolve ) => { const disposer = autorun ( ( ) => { if ( this . _isLoaded ) { resolve ( ) ; if ( disposer ) { disposer ( ) ; } } } ) ; } ) ; } static keyForChainInfo ( chainInfo ) { return `${ chainInfo . chainName }` ; } } export class AddressBookConfigMap extends HasMapStore < AddressBookConfig > { constructor ( protected readonly kvStore , protected readonly chainGetter ) { super ( ( chainId ) => { return new AddressBookConfig ( kvStore , chainGetter , chainId ) ; } ) ; } getAddressBookConfig ( chainId ) { return this . get ( chainId ) ; } } export const useAddressBookConfig = ( kvStore , chainGetter , chainId , handler ) => { const [ configMap ] = useState ( ( ) => new AddressBookConfigMap ( kvStore , chainGetter ) ) ; const config = configMap . getAddressBookConfig ( chainId ) ; config . setSelectHandler ( handler ) ; return config ; } ;