src/dash-platform-user.js
/**
     * Finds the registered username on the network
     * @static DashPlatformUser#findByName
     * @param {string|Object|Array<{string}|{Object}>} query Either:
     * For a single user query,either
     * - a single string containing a username, or
     * - an single object with properties of `name` and `options` to apply to the query for that user
     * OR For a multiple user query
     * - an array with a combination of the above
     * @param {Object} options Optional dashjs client. If the object is not passed it will be constructed by the function.
     * 
     */
Finds the registered username on the network
@static DashPlatformUser#findByName
@param {string|Object|Array<{string}|{Object}>} query Either:
For a single user query,either
- a single string containing a username, or
- an single object with properties of `name` and `options` to apply to the query for that user
OR For a multiple user query
- an array with a combination of the above
@param {Object} options Optional dashjs client. If the object is not passed it will be constructed by the function.
Finds the registered username on the network @static DashPlatformUser#findByName @param { string|Object|Array< { string } | { Object } > } query Either : For a single user query either - a single string containing a username or - an single object with properties of ` name ` and ` options ` to apply to the query for that user OR For a multiple user query - an array with a combination of the above @param { Object } options Optional dashjs client . If the object is not passed it will be constructed by the function .
static async findByName(query, options) {
        try {
            debug(`options: ${options}`);
            if (options == undefined) options = {};
            debug(`options now: ${options}`);
            const returnType = options.returnType || this.returnTypes.OBJECT;
            const returnAllRecords = options.returnAllRecords || false;
            const connOptions = options.connection_options || {};
            const client = options.client ||
                new DashConnection(connOptions).client
            debug(`Client is ready...`);
            let clientHasMnemonic = false;
            if (client.options.wallet != undefined) {
                if (client.options.wallet.mnemonic != undefined) {
                    clientHasMnemonic = true;
                }
            }
            debug(`Client passed with a mnemonic?: ${clientHasMnemonic} `);
            let arrQuery = [];
            let multiUserQuery = false;
            let arrUsersWithOptions = [];
            switch (typeof query) {
                case 'string':
                    arrQuery.push(query)
                    break;
                case 'object':
                    if (Array.isArray(query)) {
                        multiUserQuery = true
                        arrQuery = query.map(n => {
                            if (typeof n == 'object') {
                                arrUsersWithOptions.push(n);
                                return n.name;
                            }
                            else if (typeof n == 'string') {
                                return n;
                            }
                        })
                    }
                    else {
                        arrQuery.push(query.name);
                        arrUsersWithOptions.push(query);
                    }
                    break;
            }
            const processUserOptions = arrUsersWithOptions.length > 0;
            debug(`array of queries with options: ${arrUsersWithOptions}`);
            if (processUserOptions && !clientHasMnemonic) throw new Error('user options are not valid. options.returnPrivateKey requires a mnemonic to be supplied')
            let arrFindPrivateKey = arrUsersWithOptions.map(f => {
                if (f.options.returnPrivateKey) return f.name;
            })
            if (processUserOptions && !arrFindPrivateKey.length) throw new Error('user options are not valid. options.returnPrivateKey is the only valid user level option')
            debug(`array of names to query: ${arrQuery}`);
            debug(`expect multiple user results?: ${multiUserQuery}`);
            debug(`process options?: ${processUserOptions}`);
            debug(`array of users to returnPrivateKey for: ${arrFindPrivateKey}`);
            debug(`Find user DPNS Docuemnt Id`);
            const foundUsers = await DPNSDocument.find(
                client,
                'dpns.domain',
                {
                    where: [
                        ['normalizedParentDomainName', '==', 'dash'],
                        ['normalizedLabel', 'in', arrQuery],
                    ],
                    startAt: 1,
                },
            );
            debug(`Found document(s): ${JSON.stringify(foundUsers)}`);
            let arrResults = [];
            let qResults = arrQuery.map(async aq => {
                let rObj = {};
                rObj.query = aq;
                rObj.results = foundUsers.filter((f) => f.data.data.normalizedLabel == aq) || [];
                debug(`${rObj.results.length} results for user ${aq}:\n ${JSON.stringify(rObj.results)}`);
                let mappedResults = [{}];
                if (rObj.results.length > 0) {
                    mappedResults = rObj.results.map(async r => {
                        let foundUser = new this();
                        foundUser.name = aq;
                        foundUser.id = r._id;
                        foundUser.identityId = r._data.data.records.dashUniqueIdentityId;
                        debug(`Fetching Identity record for id ${foundUser.identityId}`);
                        foundUser.identity = await client.platform.identities.get(
                            foundUser.identityId,
                        );
                        debug(`Found identity ${JSON.stringify(foundUser.identity)}`);
                        foundUser.publicKeyBinary = foundUser.identity.publicKeys[0].data;
                        debug(`User public key binary ${foundUser.publicKeyBinary}`);
                        foundUser.publicKey = foundUser.publicKeyBinary.toString('base64');
                        debug(`User public key ${foundUser.publicKey}`);
                        if (processUserOptions && arrFindPrivateKey.indexOf(aq) > -1) {
                            debug(`Finding private key for user  ${aq}`);
                            client.account = await client.wallet.getAccount({ index: 0 });
                            foundUser.privateKey = client.account.getIdentityHDKeyByIndex(0, 0).privateKey.toString();
                            debug(`user privateKey: ${foundUser.privateKey}`)
                        }
                        let returnUser;
                        switch (returnType) {
                            case this.returnTypes.OBJECT:
                                returnUser = toObject(foundUser);
                                break;
                            case this.returnTypes.JSON:
                                returnUser = JSON.stringify(toObject(foundUser));
                                break;
                            case this.returnTypes.INSTANCE:
                                returnUser = foundUser;
                                break;
                            default:
                                throw new Error('Invalid return Type enum specified');
                        }
                        return returnUser;
                    })
                } 
                let promisedMappedResults = await Promise.all(mappedResults)
                if (returnAllRecords) {
                    rObj.results = promisedMappedResults;
                }
                else {
                    rObj.results = promisedMappedResults[0];
                }
                return rObj
            }) 
            let finalResults = await Promise.all(qResults);
            let resultToReturn;
            if (multiUserQuery) {
                debug(`RETURN *MULIPLE USER* OBJ RESULTS`);
                resultToReturn = finalResults;
            }
            else {
                debug(`RETURN *SINGLE USER* OBJ RESULTS`);
                resultToReturn = finalResults[0];
            }
            debug(`** FINISHED ** RETURNING RESULT: ${JSON.stringify(resultToReturn)}`);
            return resultToReturn
        } catch (e) {
            debug(`find name error: ${e}`);
            throw new Error(e.message)
        }
    }
static async findByName ( query , options ) { try { debug ( ` ${ options } ` ) ; if ( options == undefined ) options = { } ; debug ( ` ${ options } ` ) ; const returnType = options . returnType || this . returnTypes . OBJECT ; const returnAllRecords = options . returnAllRecords || false ; const connOptions = options . connection_options || { } ; const client = options . client || new DashConnection ( connOptions ) . client debug ( ` ` ) ; let clientHasMnemonic = false ; if ( client . options . wallet != undefined ) { if ( client . options . wallet . mnemonic != undefined ) { clientHasMnemonic = true ; } } debug ( ` ${ clientHasMnemonic } ` ) ; let arrQuery = [ ] ; let multiUserQuery = false ; let arrUsersWithOptions = [ ] ; switch ( typeof query ) { case 'string' : arrQuery . push ( query ) break ; case 'object' : if ( Array . isArray ( query ) ) { multiUserQuery = true arrQuery = query . map ( n => { if ( typeof n == 'object' ) { arrUsersWithOptions . push ( n ) ; return n . name ; } else if ( typeof n == 'string' ) { return n ; } } ) } else { arrQuery . push ( query . name ) ; arrUsersWithOptions . push ( query ) ; } break ; } const processUserOptions = arrUsersWithOptions . length > 0 ; debug ( ` ${ arrUsersWithOptions } ` ) ; if ( processUserOptions && ! clientHasMnemonic ) throw new Error ( 'user options are not valid. options.returnPrivateKey requires a mnemonic to be supplied' ) let arrFindPrivateKey = arrUsersWithOptions . map ( f => { if ( f . options . returnPrivateKey ) return f . name ; } ) if ( processUserOptions && ! arrFindPrivateKey . length ) throw new Error ( 'user options are not valid. options.returnPrivateKey is the only valid user level option' ) debug ( ` ${ arrQuery } ` ) ; debug ( ` ${ multiUserQuery } ` ) ; debug ( ` ${ processUserOptions } ` ) ; debug ( ` ${ arrFindPrivateKey } ` ) ; debug ( ` ` ) ; const foundUsers = await DPNSDocument . find ( client , 'dpns.domain' , { where : [ [ 'normalizedParentDomainName' , '==' , 'dash' ] , [ 'normalizedLabel' , 'in' , arrQuery ] , ] , startAt : 1 , } , ) ; debug ( ` ${ JSON . stringify ( foundUsers ) } ` ) ; let arrResults = [ ] ; let qResults = arrQuery . map ( async aq => { let rObj = { } ; rObj . query = aq ; rObj . results = foundUsers . filter ( ( f ) => f . data . data . normalizedLabel == aq ) || [ ] ; debug ( ` ${ rObj . results . length } ${ aq } \n ${ JSON . stringify ( rObj . results ) } ` ) ; let mappedResults = [ { } ] ; if ( rObj . results . length > 0 ) { mappedResults = rObj . results . map ( async r => { let foundUser = new this ( ) ; foundUser . name = aq ; foundUser . id = r . _id ; foundUser . identityId = r . _data . data . records . dashUniqueIdentityId ; debug ( ` ${ foundUser . identityId } ` ) ; foundUser . identity = await client . platform . identities . get ( foundUser . identityId , ) ; debug ( ` ${ JSON . stringify ( foundUser . identity ) } ` ) ; foundUser . publicKeyBinary = foundUser . identity . publicKeys [ 0 ] . data ; debug ( ` ${ foundUser . publicKeyBinary } ` ) ; foundUser . publicKey = foundUser . publicKeyBinary . toString ( 'base64' ) ; debug ( ` ${ foundUser . publicKey } ` ) ; if ( processUserOptions && arrFindPrivateKey . indexOf ( aq ) > - 1 ) { debug ( ` ${ aq } ` ) ; client . account = await client . wallet . getAccount ( { index : 0 } ) ; foundUser . privateKey = client . account . getIdentityHDKeyByIndex ( 0 , 0 ) . privateKey . toString ( ) ; debug ( ` ${ foundUser . privateKey } ` ) } let returnUser ; switch ( returnType ) { case this . returnTypes . OBJECT : returnUser = toObject ( foundUser ) ; break ; case this . returnTypes . JSON : returnUser = JSON . stringify ( toObject ( foundUser ) ) ; break ; case this . returnTypes . INSTANCE : returnUser = foundUser ; break ; default : throw new Error ( 'Invalid return Type enum specified' ) ; } return returnUser ; } ) } let promisedMappedResults = await Promise . all ( mappedResults ) if ( returnAllRecords ) { rObj . results = promisedMappedResults ; } else { rObj . results = promisedMappedResults [ 0 ] ; } return rObj } ) let finalResults = await Promise . all ( qResults ) ; let resultToReturn ; if ( multiUserQuery ) { debug ( ` ` ) ; resultToReturn = finalResults ; } else { debug ( ` ` ) ; resultToReturn = finalResults [ 0 ] ; } debug ( ` ${ JSON . stringify ( resultToReturn ) } ` ) ; return resultToReturn } catch ( e ) { debug ( ` ${ e } ` ) ; throw new Error ( e . message ) } }
Finds the registered username on the network
 @static DashPlatformUser#findByName
 @param {string|Object|Array<{string}|{Object}>} query Either:
 For a single user query,either
 - a single string containing a username, or
 - an single object with properties of `name` and `options` to apply to the query for that user
 OR For a multiple user query
 - an array with a combination of the above
 @param {Object} options Optional dashjs client.
Finds the registered username on the network @static DashPlatformUser#findByName @param { string|Object|Array< { string } | { Object } > } query Either : For a single user query either - a single string containing a username or - an single object with properties of ` name ` and ` options ` to apply to the query for that user OR For a multiple user query - an array with a combination of the above @param { Object } options Optional dashjs client .
/* options:
            @param  {(0|1|2)} returnType
        */ //options.returnAllRecords //If this option is set to true, the full document history for each name is returned in an array // If false (default) only the current record / registration is returned as an object /*
            NOTE: CURRENTLY DOMAIN TRANSFERS ARE NOT PERMITTED, THERE SHOULD ONLY EVER BE ONE RECORED RETURNED
            THERE IS CURRENTLY NO MEANS OF ORDERING RECORDS BY TIMESTAMP, SO BY DEFAULT DPNS DOCUMENTS ARE RETURNED
            AS AN ARRAY AND THE FIRST ELEMENT IS RETRUNED AS THE RESULT OBJECT
            */ //debug(`client: ${client}`); //console.dir(client); //look for single string, single object, or array // array to store queries which are objects (have options) //single string //?? if the user passes in an array they get array back even if a single element //if (arrQuery.length > 1) multiUserQuery = true; //map array to pull out strings and objects with options //and push to array of queries with options //single object - push name to arrQuery //only current user option is for returnPrivateKey // TODO: refine / refactor // throw error of no mnmonic //get a map of the usernames to find privcate key for  // TODO: check that the connection.apps property uses dpns to reference the dpns contract //['normalizedLabel', '==', query.toLowerCase()], // TODO: ORDER BY REGISTRATION DATE - not currently possible  // Refactor if/when document transfer becomes available /*
            if (foundUsers.error) {
              return { error: true, message: foundUsers.message };
            } 
            */ /*
            //REM: Document#find will return empty array if no user(s) found (or throw error)
            if (!foundUsers.success) {
                return { success: false, message: 'Name not found' };
            }
            */ //else if ((foundUsers.data.length = 1)) { //map results to identity etc. //get public key (async) //? returnPublicKey for this user // TODO : (a) why is getAccount so slow...? (b)  // HOW TO KNOW THE INDEX OF THE CORRECT KEY //use getIdentityHDKeyById ?? //foundUser.privateKey = client.account.getIdentityHDKeyById(foundUser.identityId,0).privateKey.toString(); // format results depending on options.returnType (default this.returnTypes.OBJECT) // end only process records with query results // end map each name in query array //?? check there is only 1 result