@stacks/auth
Version:
Authentication for Stacks apps.
82 lines (75 loc) • 2.76 kB
text/typescript
import { NetworkClientParam, clientFromNetwork, networkFrom } from '@stacks/network';
import { resolveZoneFileToProfile } from '@stacks/profile';
export interface ProfileLookupOptions {
username: string;
zoneFileLookupURL?: string;
}
/**
* Look up a user profile by blockstack ID
*
* @param {string} username - The Blockstack ID of the profile to look up
* @param {string} [zoneFileLookupURL=null] - The URL
* to use for zonefile lookup. If falsey, lookupProfile will use the
* blockstack.js [[getNameInfo]] function.
* @returns {Promise} that resolves to a profile object
*/
export function lookupProfile(
options: ProfileLookupOptions & NetworkClientParam
): Promise<Record<string, any>> {
if (!options.username) {
return Promise.reject(new Error('No username provided'));
}
const network = networkFrom(options.network ?? 'mainnet');
const client = Object.assign({}, clientFromNetwork(network), options.client);
let lookupPromise;
if (options.zoneFileLookupURL) {
const url = `${options.zoneFileLookupURL.replace(/\/$/, '')}/${options.username}`;
lookupPromise = client.fetch(url).then(response => response.json());
} else {
lookupPromise = getNameInfo({ name: options.username });
}
return lookupPromise.then((responseJSON: any) => {
if (responseJSON.hasOwnProperty('zonefile') && responseJSON.hasOwnProperty('address')) {
return resolveZoneFileToProfile({
zoneFile: responseJSON.zonefile,
publicKeyOrAddress: responseJSON.address,
client,
});
} else {
throw new Error(
'Invalid zonefile lookup response: did not contain `address`' + ' or `zonefile` field'
);
}
});
}
export function getNameInfo(
opts: {
/** Fully qualified name */
name: string;
} & NetworkClientParam
) {
const network = networkFrom(opts.network ?? 'mainnet');
const client = Object.assign({}, clientFromNetwork(network), opts.client);
const nameLookupURL = `${client.baseUrl}/v1/names/${opts.name}`;
return client
.fetch(nameLookupURL)
.then((resp: any) => {
if (resp.status === 404) {
throw new Error('Name not found');
} else if (resp.status !== 200) {
throw new Error(`Bad response status: ${resp.status}`);
} else {
return resp.json();
}
})
.then((nameInfo: any) => {
// the returned address _should_ be in the correct network ---
// stacks node gets into trouble because it tries to coerce back to mainnet
// and the regtest transaction generation libraries want to use testnet addresses
if (nameInfo.address) {
return Object.assign({}, nameInfo, { address: nameInfo.address });
} else {
return nameInfo;
}
});
}