@bsv/wallet-toolbox-client
Version:
Client only Wallet Storage
116 lines • 5.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseResults = exports.queryOverlay = exports.transformVerifiableCertificatesWithTrust = void 0;
const sdk_1 = require("@bsv/sdk");
const OUTPUT_INDEX = 0;
/**
* Transforms an array of VerifiableCertificate instances according to the trust settings.
* Only certificates whose grouped total trust meets the threshold are returned,
* and each certificate is augmented with a certifierInfo property.
*
* @param trustSettings - the user's trust settings including trustLevel and trusted certifiers.
* @param certificates - an array of VerifiableCertificate objects.
* @returns a DiscoverCertificatesResult with totalCertificates and ordered certificates.
*/
const transformVerifiableCertificatesWithTrust = (trustSettings, certificates) => {
// Group certificates by subject while accumulating trust.
const identityGroups = {};
// Cache certifier lookups.
const certifierCache = {};
certificates.forEach(cert => {
const { subject, certifier } = cert;
if (!subject || !certifier)
return;
// Lookup and cache certifier details from trustSettings.
if (!certifierCache[certifier]) {
const found = trustSettings.trustedCertifiers.find(x => x.identityKey === certifier);
if (!found)
return; // Skip this certificate if its certifier is not trusted.
certifierCache[certifier] = found;
}
// Create the IdentityCertifier object that we want to attach.
const certifierInfo = {
name: certifierCache[certifier].name,
iconUrl: certifierCache[certifier].iconUrl || '',
description: certifierCache[certifier].description,
trust: certifierCache[certifier].trust
};
// Create an extended certificate that includes certifierInfo.
// Note: We use object spread to copy over all properties from the original certificate.
const extendedCert = {
...cert,
signature: cert.signature, // We know it exists at this point
decryptedFields: cert.decryptedFields,
publiclyRevealedKeyring: cert.keyring,
certifierInfo
};
// Group certificates by subject.
if (!identityGroups[subject]) {
identityGroups[subject] = { totalTrust: 0, members: [] };
}
identityGroups[subject].totalTrust += certifierInfo.trust;
identityGroups[subject].members.push(extendedCert);
});
// Filter out groups that do not meet the trust threshold and flatten the results.
const finalResults = [];
Object.values(identityGroups).forEach(group => {
if (group.totalTrust >= trustSettings.trustLevel) {
finalResults.push(...group.members);
}
});
// Sort the certificates by their certifier trust in descending order.
finalResults.sort((a, b) => b.certifierInfo.trust - a.certifierInfo.trust);
return {
totalCertificates: finalResults.length,
certificates: finalResults
};
};
exports.transformVerifiableCertificatesWithTrust = transformVerifiableCertificatesWithTrust;
/**
* Performs an identity overlay service lookup query and returns the parsed results
*
* @param query
* @returns
*/
const queryOverlay = async (query, resolver) => {
const results = await resolver.query({
service: 'ls_identity',
query
});
return await (0, exports.parseResults)(results);
};
exports.queryOverlay = queryOverlay;
/**
* Internal func: Parse the returned UTXOs Decrypt and verify the certificates and signatures Return the set of identity keys, certificates and decrypted certificate fields
*
* @param {Output[]} outputs
* @returns {Promise<VerifiableCertificate[]>}
*/
const parseResults = async (lookupResult) => {
if (lookupResult.type === 'output-list') {
const parsedResults = [];
for (const output of lookupResult.outputs) {
try {
const tx = sdk_1.Transaction.fromBEEF(output.beef);
// Decode the Identity token fields from the Bitcoin outputScript
const decodedOutput = sdk_1.PushDrop.decode(tx.outputs[output.outputIndex].lockingScript);
// Parse out the certificate and relevant data
const certificate = JSON.parse(sdk_1.Utils.toUTF8(decodedOutput.fields[0])); // TEST
const verifiableCert = new sdk_1.VerifiableCertificate(certificate.type, certificate.serialNumber, certificate.subject, certificate.certifier, certificate.revocationOutpoint, certificate.fields, certificate.keyring, certificate.signature);
const decryptedFields = await verifiableCert.decryptFields(new sdk_1.ProtoWallet('anyone'));
// Verify the certificate signature is correct
await verifiableCert.verify();
verifiableCert.decryptedFields = decryptedFields;
parsedResults.push(verifiableCert);
}
catch (error) {
console.error(error);
// do nothing
}
}
return parsedResults;
}
return [];
};
exports.parseResults = parseResults;
//# sourceMappingURL=identityUtils.js.map