/ common / features / ens / helpers.ts
helpers.ts
  1  import { SagaIterator } from 'redux-saga';
  2  import { select, apply, call } from 'redux-saga/effects';
  3  import ethUtil from 'ethereumjs-util';
  4  
  5  import networkConfigs from 'libs/ens/networkConfigs';
  6  import { INode } from 'libs/nodes/INode';
  7  import ENS from 'libs/ens/contracts';
  8  import { IDomainData, NameState, getNameHash, IBaseDomainRequest } from 'libs/ens';
  9  import * as configNodesSelectors from 'features/config/nodes/selectors';
 10  
 11  //#region Make & Decode
 12  interface Params {
 13    to: any;
 14    data: any;
 15    decoder: any;
 16  }
 17  
 18  export function* makeEthCallAndDecode({ to, data, decoder }: Params): SagaIterator {
 19    const node: INode = yield select(configNodesSelectors.getNodeLib);
 20    const result: string = yield apply(node, node.sendCallRequest, [{ data, to }]);
 21    const decodedResult = yield call(decoder, result);
 22    return decodedResult;
 23  }
 24  //#endregion Make & Decode
 25  
 26  //#region Mode Map
 27  const { main } = networkConfigs;
 28  
 29  function* nameStateOwned({ deedAddress }: IDomainData<NameState.Owned>, nameHash: string) {
 30    // Return the owner's address, and the resolved address if it exists
 31    const { ownerAddress }: typeof ENS.deed.owner.outputType = yield call(makeEthCallAndDecode, {
 32      to: deedAddress,
 33      data: ENS.deed.owner.encodeInput(),
 34      decoder: ENS.deed.owner.decodeOutput
 35    });
 36  
 37    const { resolverAddress }: typeof ENS.registry.resolver.outputType = yield call(
 38      makeEthCallAndDecode,
 39      {
 40        to: main.registry,
 41        decoder: ENS.registry.resolver.decodeOutput,
 42        data: ENS.registry.resolver.encodeInput({
 43          node: nameHash
 44        })
 45      }
 46    );
 47  
 48    let resolvedAddress = '0x0';
 49  
 50    if (resolverAddress !== '0x0') {
 51      const result: typeof ENS.resolver.addr.outputType = yield call(makeEthCallAndDecode, {
 52        to: resolverAddress,
 53        data: ENS.resolver.addr.encodeInput({ node: nameHash }),
 54        decoder: ENS.resolver.addr.decodeOutput
 55      });
 56  
 57      resolvedAddress = result.ret;
 58    }
 59  
 60    return { ownerAddress, resolvedAddress };
 61  }
 62  
 63  function* nameStateReveal({ deedAddress }: IDomainData<NameState.Reveal>): SagaIterator {
 64    const { ownerAddress }: typeof ENS.deed.owner.outputType = yield call(makeEthCallAndDecode, {
 65      to: deedAddress,
 66      data: ENS.deed.owner.encodeInput(),
 67      decoder: ENS.deed.owner.decodeOutput
 68    });
 69    return { ownerAddress };
 70  }
 71  
 72  interface IModeMap {
 73    [x: string]: (
 74      domainData: IDomainData<NameState>,
 75      nameHash?: string,
 76      hash?: Buffer
 77    ) =>
 78      | {}
 79      | { ownerAddress: string; resolvedAddress: string }
 80      | { auctionCloseTime: string; revealBidTime: string };
 81  }
 82  
 83  const modeMap: IModeMap = {
 84    [NameState.Open]: (_: IDomainData<NameState.Open>) => ({}),
 85    [NameState.Auction]: (_: IDomainData<NameState.Auction>) => ({}),
 86    [NameState.Owned]: nameStateOwned,
 87    [NameState.Forbidden]: (_: IDomainData<NameState.Forbidden>) => ({}),
 88    [NameState.Reveal]: nameStateReveal,
 89    [NameState.NotYetAvailable]: (_: IDomainData<NameState.NotYetAvailable>) => ({})
 90  };
 91  
 92  export function* resolveDomainRequest(name: string): SagaIterator {
 93    const hash = ethUtil.sha3(name);
 94    const nameHash = getNameHash(`${name}.eth`);
 95  
 96    const domainData: typeof ENS.auction.entries.outputType = yield call(makeEthCallAndDecode, {
 97      to: main.public.ethAuction,
 98      data: ENS.auction.entries.encodeInput({ _hash: hash }),
 99      decoder: ENS.auction.entries.decodeOutput
100    });
101    const nameStateHandler = modeMap[domainData.mode];
102    const result = yield call(nameStateHandler, domainData, nameHash);
103  
104    const returnValue: IBaseDomainRequest = {
105      name,
106      ...domainData,
107      ...result,
108      labelHash: ethUtil.addHexPrefix(hash.toString('hex')),
109      nameHash
110    };
111    return returnValue;
112  }
113  //#endregion Mode Map