import { Envelope } from 'univrse';
import { hex, sha256, sha512, generateSaltToDeriveKey } from '../../utils.js';
/**
 * This uses the UNIVRSE protocol, hash type is distinguished by the header { meta: { type: 'hash }}
 */
// TODO:
// - Return op_hex instead of envelope.
/**
 * @category Envelopes
 */
export class Hash {
    info;
    envelope = null;
    constructor({ info }) {
        this.info = info;
    }
    static async create(options) {
        if ((options.sign || options.encrypt) && !options.key) {
            throw new Error('Invalid options. Please provide a key to sign and/or encrypt.');
        }
        const digest = options.algorithm === 'SHA-256' ? await sha256(options.data) : await sha512(options.data);
        const digestHex = hex.bufToHex(digest);
        const hash = new Hash({
            info: {
                type: 'hash',
                algorithm: options.algorithm,
                digestHex,
                digest,
            },
        });
        await hash.createEnvelope(options);
        return hash;
    }
    async createEnvelope({ sign, encrypt, key }) {
        const nonce = generateSaltToDeriveKey(16);
        const headers = {
            proto: 'mintBlue',
            meta: { type: 'hash' },
        };
        // Use Uint8Array digest only
        const data = { digest: this.info.digest, algorithm: this.info.algorithm };
        const env = Envelope.wrap(data, headers);
        if (sign) {
            if (!key)
                throw new Error('sign is true but no key provided');
            await env.sign(key, { alg: 'ES256K' });
        }
        if (encrypt) {
            if (!key)
                throw new Error('encrypt is true but no key provided');
            await env.encrypt(key.toPublic(), { alg: 'ECDH-ES+A128GCM', nonce });
        }
        this.envelope = env;
    }
    toOpReturnScriptHex() {
        return this.envelope?.toScript().toHex();
    }
    static async fromOpReturnScript(script, key) {
        let envelope = Envelope.fromScript(script);
        const info = {};
        if (envelope.recipient) {
            if (!key) {
                throw new Error('Cannot decrypt Script without a key.');
            }
            envelope = await envelope.decrypt(key);
            info.encrypt = true;
        }
        if (envelope.signature) {
            info.sign = true;
        }
        return new Hash({
            info: {
                type: 'hash',
                ...envelope.payload,
                digestHex: hex.bufToHex(envelope.payload.digest),
                ...info, // sign, encrypt
            },
        });
    }
}
//# sourceMappingURL=v1.js.map