@nfps.dev/runtime
Version:
Runtime library for NFPs
143 lines • 5.32 kB
JavaScript
import { ofe, } from '@blake.regalia/belt';
import { SecretContract, } from '@solar-republic/neutrino';
import { load_script } from './connectivity';
import { P_NS_NFP } from './constants';
import { ls_read_json, ls_write_json } from './dom';
let k_contract;
let a_location;
let z_auth;
let si_storage_auth;
let xc_busy = 0;
export const nfp_tags = (si_tag) => document.getElementsByTagNameNS(P_NS_NFP, si_tag);
export const nfp_attr = (dm_element, si_attr) => dm_element.getAttributeNS(P_NS_NFP, si_attr);
const import_query_key_prompt = () => {
// prompt for key
const sx_import = prompt(`NFP requires either (1) the owner's viewing key or (2) a query permit signed by the token owner; paste one here to unlock\n\nPermits should be JSON in shape of '{"params":..,"signature":..}'`)?.trim();
// something was entered
if (sx_import) {
// attempt to parse as json
let h_input;
try {
h_input = JSON.parse(sx_import);
}
catch (e_parse) { }
// parsed as JSON object; use as permit
if ('object' === typeof h_input) {
z_auth = h_input;
}
// treat text as viewing key
else {
z_auth = [sx_import];
}
}
};
const hydrate_nfp = async () => {
// find scripts
const a_srcs = Array.from(nfp_tags('script'))
.map(dm => [dm, nfp_attr(dm, 'src')?.split('?')]);
const a_load = [];
for (const [dm_element, [si_package, sx_params]] of a_srcs) {
const dm_script = await load_script(si_package, ofe(new URLSearchParams(sx_params || '').entries()), k_contract, a_location, z_auth);
// auth worked, save it to local storage
ls_write_json(si_storage_auth, z_auth);
// replace script
if (dm_script) {
a_load.push(() => dm_element.replaceWith(dm_script));
}
// fail
else {
return;
}
}
return () => a_load.map(f => f());
};
const resolve_permit = async () => {
// storage item key
si_storage_auth = a_location.join(':') + ':auth';
// check local storage for auth
z_auth ||= ls_read_json(si_storage_auth);
// use prompt as fallback
if (!z_auth)
import_query_key_prompt();
// something was loaded, hydrate; query succeeded
if (z_auth) {
return await hydrate_nfp();
}
};
export const boot = async () => {
// do not boot while loading
if (xc_busy)
return;
// select the first metadata tag
const dm_metadata = document.querySelector(':root>metadata');
if (dm_metadata) {
// first nfp:web tag
const dm_web = nfp_tags('web')[0];
// first nfp:self tag
const dm_self = nfp_tags('self')[0];
// missing requisite tag(s)
if (!dm_web || !dm_self)
throw new Error('Missing requisite NFP tags');
// parse lcds attribute
const a_lcds = nfp_attr(dm_web, 'lcds')?.split(',');
if (!a_lcds?.length)
throw new Error('Missing nfp:lcds attribute');
// destructure nfp:self attribute values
a_location = ['chain', 'contract', 'token']
.map(si_attr => nfp_attr(dm_self, si_attr));
// auth is baked into contract
const dm_auth = nfp_tags('auth')[0];
if (dm_auth && !z_auth) {
const sh_vk = nfp_attr(dm_auth, 'vk');
if (sh_vk) {
z_auth = [sh_vk, nfp_attr(dm_auth, 'addr')];
}
}
// // secret via localStorage
// for(const dm_secret of nfp_tags('secret')) {
// const p_comc = nfp_attr(dm_secret, 'comc');
// const sh_key = nfp_attr(dm_secret, 'key');
// if(!p_comc || !sh_key) continue;
// const dm_portal = await comcPortal(p_comc as HttpsUrl, document.documentElement);
// const k_comc = await comcClient(dm_portal);
// await ({
// async auth() {
// z_auth = await k_comc.post(XC_CMD_FETCH_DATA, [sh_key]) as AuthSecret;
// },
// } as Dict<() => Promise<void>>)[nfp_attr(dm_secret, 'context')+'']?.();
// // discard portal
// dm_portal.remove();
// }
// set busy state
xc_busy = 1;
// try each endpoint in order
for (const p_lcd of a_lcds) {
try {
// attempt to instantiate contract
k_contract = await SecretContract(p_lcd, a_location[1]);
// free
xc_busy = 0;
// done
let f_inject;
// eslint-disable-next-line @typescript-eslint/no-extra-parens
if ((f_inject = await resolve_permit())) {
// return boot info
return [
f_inject,
a_location,
k_contract.lcd,
k_contract,
z_auth,
];
}
}
catch (e_query) {
// free
xc_busy = 0;
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.warn(`Endpoint offline: ${p_lcd}; ${e_query.stack}`);
}
}
}
};
//# sourceMappingURL=boot.js.map