import * as KeetaNet from '@keetanetwork/keetanet-client';
import { Certificate } from '../certificates.js';
import { KeetaAnchorCertificateRequiredError } from '../error.js';
/**
 * Verify that the supplied account has at least one on-chain certificate
 * whose chain terminates at one of the supplied trusted issuers.
 */
export async function verifyAccountCertificateChain(args) {
    const { account, client, trustedIssuers } = args;
    const records = await client.getAllCertificates(account);
    if (records.length === 0) {
        return ('no-certs');
    }
    if (trustedIssuers.length === 0) {
        return ('untrusted');
    }
    const rootSet = new Set(trustedIssuers);
    for (const record of records) {
        let intermediate;
        if (record.intermediates === null) {
            intermediate = new Set();
        }
        else {
            intermediate = new Set(record.intermediates.getCertificates());
        }
        let candidate;
        try {
            candidate = new Certificate(record.certificate.toPEM(), {
                store: { root: rootSet, intermediate }
            });
        }
        catch {
            continue;
        }
        if (candidate.trusted) {
            return ('trusted');
        }
    }
    return ('untrusted');
}
/**
 * Validate and freeze a `CertificateChainConfig`.
 */
export function resolveCertificateChainConfig(config) {
    if (config === undefined) {
        return (undefined);
    }
    if (config.trustedIssuers.length === 0) {
        throw (new Error('requireCertificateChain.trustedIssuers must contain at least one issuer'));
    }
    return ({
        trustedIssuers: config.trustedIssuers,
        client: config.client,
        acceptedIssuerDNs: config.trustedIssuers.map(function (cert) { return (cert.subjectDN); })
    });
}
/**
 * Default delimiter used by {@link certificateChainConfigFromBundle} to
 * separate concatenated PEM-encoded certificates in a single string.
 */
export const DEFAULT_CERTIFICATE_BUNDLE_DELIMITER = '|';
/**
 * Build a {@link CertificateChainConfig} from a delimited PEM bundle and a network.
 */
export function certificateChainConfigFromBundle(args) {
    const delimiter = args.delimiter ?? DEFAULT_CERTIFICATE_BUNDLE_DELIMITER;
    const trustedIssuers = args.pemBundle
        .split(delimiter)
        .map(function (pem) { return (pem.trim()); })
        .filter(function (pem) { return (pem.length > 0); })
        .map(function (pem) { return (new Certificate(pem)); });
    if (trustedIssuers.length === 0) {
        throw (new Error('pemBundle contains no certificates'));
    }
    const client = KeetaNet.Client.fromNetwork(args.network);
    return ({ trustedIssuers, client });
}
/**
 * Verify the signing account's on-chain certificate chain against the
 * resolved requirement. Throws `KeetaAnchorCertificateRequiredError` when
 * the gate is configured and the account fails it.
 */
export async function assertAccountCertificateChain(account, requirement) {
    if (requirement === undefined) {
        return;
    }
    const status = await verifyAccountCertificateChain({
        account,
        client: requirement.client,
        trustedIssuers: requirement.trustedIssuers
    });
    if (status === 'trusted') {
        return;
    }
    let kind;
    if (status === 'no-certs') {
        kind = 'missing';
    }
    else {
        kind = 'untrusted';
    }
    throw (new KeetaAnchorCertificateRequiredError({ acceptedIssuers: requirement.acceptedIssuerDNs, kind }));
}
//# sourceMappingURL=certificate-network.js.map