@bitgo/utxo-ord
Version:
Utilities for building ordinals with BitGo utxo-lib
89 lines (87 loc) • 14.5 kB
JavaScript
/*
Functions for dealing with inscriptions.
Wrapper around @bitgo/wasm-utxo inscription functions for utxo-ord consumers.
See https://docs.ordinals.com/inscriptions.html
*/
import { inscriptions as wasmInscriptions, address as wasmAddress, Transaction, ECPair, } from '@bitgo/wasm-utxo';
// default "postage" amount
// https://github.com/ordinals/ord/blob/0.24.2/src/lib.rs#L149
const DEFAULT_POSTAGE_SATS = BigInt(10000);
function isBIP32Like(key) {
return typeof key === 'object' && key !== null && 'publicKey' in key && !ArrayBuffer.isView(key);
}
/**
* Extract compressed public key from key input.
* Handles BIP32-like objects and raw pubkey bytes (32 or 33 bytes).
*/
function getCompressedPublicKey(key) {
const pubkey = isBIP32Like(key) ? key.publicKey : key;
if (pubkey.length === 33) {
return pubkey;
}
if (pubkey.length === 32) {
// x-only pubkey - prepend 0x02 parity byte to make compressed
const compressedPubkey = new Uint8Array(33);
compressedPubkey[0] = 0x02;
compressedPubkey.set(pubkey, 1);
return compressedPubkey;
}
throw new Error(`Invalid public key length: ${pubkey.length}. Expected 32 or 33 bytes.`);
}
/**
* Create the P2TR output script for an inscription.
*
* @param key - BIP32 key or public key bytes (32-byte x-only or 33-byte compressed)
* @param contentType - MIME type of the inscription (e.g., "text/plain", "image/png")
* @param inscriptionData - The inscription data bytes
* @returns The P2TR output script for the inscription commit address
*/
export function createOutputScriptForInscription(key, contentType, inscriptionData) {
const compressedPubkey = getCompressedPublicKey(key);
const ecpair = ECPair.fromPublicKey(compressedPubkey);
const result = wasmInscriptions.createInscriptionRevealData(ecpair, contentType, inscriptionData);
return result.outputScript;
}
/**
* Create inscription reveal data including the commit address and tap leaf script.
*
* @param key - BIP32 key or public key bytes (32-byte x-only or 33-byte compressed)
* @param contentType - MIME type of the inscription (e.g., "text/plain", "image/png")
* @param inscriptionData - The inscription data bytes
* @param coinName - Coin name (e.g., "btc", "tbtc")
* @returns PreparedInscriptionRevealData with address, vsize estimate, and tap leaf script
*/
export function createInscriptionRevealData(key, contentType, inscriptionData, coinName) {
const compressedPubkey = getCompressedPublicKey(key);
const ecpair = ECPair.fromPublicKey(compressedPubkey);
const wasmResult = wasmInscriptions.createInscriptionRevealData(ecpair, contentType, inscriptionData);
// Convert outputScript to address for the given network
const address = wasmAddress.fromOutputScriptWithCoin(wasmResult.outputScript, coinName);
return {
address,
revealTransactionVSize: wasmResult.revealTransactionVSize,
tapLeafScript: wasmResult.tapLeafScript,
};
}
/**
* Sign a reveal transaction.
*
* Creates and signs the reveal transaction that spends from the commit output
* and sends the inscription to the recipient.
*
* @param privateKey - 32-byte private key
* @param tapLeafScript - The tap leaf script from createInscriptionRevealData
* @param commitAddress - The commit address
* @param recipientAddress - Where to send the inscription
* @param unsignedCommitTx - The unsigned commit transaction bytes
* @param coinName - Coin name (e.g., "btc", "tbtc")
* @returns The signed PSBT as bytes
*/
export function signRevealTransaction(privateKey, tapLeafScript, commitAddress, recipientAddress, unsignedCommitTx, coinName) {
const ecpair = ECPair.fromPrivateKey(privateKey);
const commitTx = Transaction.fromBytes(unsignedCommitTx);
const commitOutputScript = wasmAddress.toOutputScriptWithCoin(commitAddress, coinName);
const recipientOutputScript = wasmAddress.toOutputScriptWithCoin(recipientAddress, coinName);
return wasmInscriptions.signRevealTransaction(ecpair, tapLeafScript, commitTx, commitOutputScript, recipientOutputScript, DEFAULT_POSTAGE_SATS);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zY3JpcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2luc2NyaXB0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0VBTUU7QUFFRixPQUFPLEVBQ0wsWUFBWSxJQUFJLGdCQUFnQixFQUNoQyxPQUFPLElBQUksV0FBVyxFQUN0QixXQUFXLEVBQ1gsTUFBTSxHQUdQLE1BQU0sa0JBQWtCLENBQUM7QUFJMUIsMkJBQTJCO0FBQzNCLDhEQUE4RDtBQUM5RCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxLQUFNLENBQUMsQ0FBQztBQTBCNUMsU0FBUyxXQUFXLENBQUMsR0FBYTtJQUNoQyxPQUFPLE9BQU8sR0FBRyxLQUFLLFFBQVEsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLFdBQVcsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ25HLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLHNCQUFzQixDQUFDLEdBQWE7SUFDM0MsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFFdEQsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ3pCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDekIsOERBQThEO1FBQzlELE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQzNCLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDaEMsT0FBTyxnQkFBZ0IsQ0FBQztJQUMxQixDQUFDO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLENBQUMsQ0FBQztBQUMzRixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxnQ0FBZ0MsQ0FDOUMsR0FBYSxFQUNiLFdBQW1CLEVBQ25CLGVBQTJCO0lBRTNCLE1BQU0sZ0JBQWdCLEdBQUcsc0JBQXNCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3RELE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLDJCQUEyQixDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDbEcsT0FBTyxNQUFNLENBQUMsWUFBWSxDQUFDO0FBQzdCLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSwyQkFBMkIsQ0FDekMsR0FBYSxFQUNiLFdBQW1CLEVBQ25CLGVBQTJCLEVBQzNCLFFBQWtCO0lBRWxCLE1BQU0sZ0JBQWdCLEdBQUcsc0JBQXNCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBRXRELE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDLDJCQUEyQixDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFFdEcsd0RBQXdEO0lBQ3hELE1BQU0sT0FBTyxHQUFHLFdBQVcsQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBRXhGLE9BQU87UUFDTCxPQUFPO1FBQ1Asc0JBQXNCLEVBQUUsVUFBVSxDQUFDLHNCQUFzQjtRQUN6RCxhQUFhLEVBQUUsVUFBVSxDQUFDLGFBQWE7S0FDeEMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUNuQyxVQUFzQixFQUN0QixhQUE0QixFQUM1QixhQUFxQixFQUNyQixnQkFBd0IsRUFDeEIsZ0JBQTRCLEVBQzVCLFFBQWtCO0lBRWxCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDakQsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sa0JBQWtCLEdBQUcsV0FBVyxDQUFDLHNCQUFzQixDQUFDLGFBQWEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN2RixNQUFNLHFCQUFxQixHQUFHLFdBQVcsQ0FBQyxzQkFBc0IsQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUU3RixPQUFPLGdCQUFnQixDQUFDLHFCQUFxQixDQUMzQyxNQUFNLEVBQ04sYUFBYSxFQUNiLFFBQVEsRUFDUixrQkFBa0IsRUFDbEIscUJBQXFCLEVBQ3JCLG9CQUFvQixDQUNyQixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5GdW5jdGlvbnMgZm9yIGRlYWxpbmcgd2l0aCBpbnNjcmlwdGlvbnMuXG5cbldyYXBwZXIgYXJvdW5kIEBiaXRnby93YXNtLXV0eG8gaW5zY3JpcHRpb24gZnVuY3Rpb25zIGZvciB1dHhvLW9yZCBjb25zdW1lcnMuXG5cblNlZSBodHRwczovL2RvY3Mub3JkaW5hbHMuY29tL2luc2NyaXB0aW9ucy5odG1sXG4qL1xuXG5pbXBvcnQge1xuICBpbnNjcmlwdGlvbnMgYXMgd2FzbUluc2NyaXB0aW9ucyxcbiAgYWRkcmVzcyBhcyB3YXNtQWRkcmVzcyxcbiAgVHJhbnNhY3Rpb24sXG4gIEVDUGFpcixcbiAgdHlwZSBUYXBMZWFmU2NyaXB0LFxuICB0eXBlIENvaW5OYW1lLFxufSBmcm9tICdAYml0Z28vd2FzbS11dHhvJztcblxuZXhwb3J0IHR5cGUgeyBUYXBMZWFmU2NyaXB0IH07XG5cbi8vIGRlZmF1bHQgXCJwb3N0YWdlXCIgYW1vdW50XG4vLyBodHRwczovL2dpdGh1Yi5jb20vb3JkaW5hbHMvb3JkL2Jsb2IvMC4yNC4yL3NyYy9saWIucnMjTDE0OVxuY29uc3QgREVGQVVMVF9QT1NUQUdFX1NBVFMgPSBCaWdJbnQoMTBfMDAwKTtcblxuLyoqXG4gKiBQcmVwYXJlZCBkYXRhIGZvciBhbiBpbnNjcmlwdGlvbiByZXZlYWwgdHJhbnNhY3Rpb24uXG4gKiBDb21wYXRpYmxlIHdpdGggc2RrLWNvcmUncyBQcmVwYXJlZEluc2NyaXB0aW9uUmV2ZWFsRGF0YS5cbiAqL1xuZXhwb3J0IHR5cGUgUHJlcGFyZWRJbnNjcmlwdGlvblJldmVhbERhdGEgPSB7XG4gIC8qKiBUaGUgY29tbWl0IGFkZHJlc3MgKGRlcml2ZWQgZnJvbSBvdXRwdXRTY3JpcHQgZm9yIHRoZSBnaXZlbiBuZXR3b3JrKSAqL1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIC8qKiBFc3RpbWF0ZWQgdmlydHVhbCBzaXplIG9mIHRoZSByZXZlYWwgdHJhbnNhY3Rpb24gKi9cbiAgcmV2ZWFsVHJhbnNhY3Rpb25WU2l6ZTogbnVtYmVyO1xuICAvKiogVGFwIGxlYWYgc2NyaXB0IGZvciBzcGVuZGluZyB0aGUgY29tbWl0IG91dHB1dCAqL1xuICB0YXBMZWFmU2NyaXB0OiBUYXBMZWFmU2NyaXB0O1xufTtcblxuLyoqXG4gKiBCSVAzMi1saWtlIGludGVyZmFjZSBjb21wYXRpYmxlIHdpdGggYm90aCB1dHhvLWxpYiBhbmQgd2FzbS11dHhvIEJJUDMyIHR5cGVzLlxuICogVGhlIHB1YmxpY0tleSBjYW4gYmUgQnVmZmVyICh1dHhvLWxpYikgb3IgVWludDhBcnJheSAod2FzbS11dHhvKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCSVAzMkxpa2Uge1xuICBwdWJsaWNLZXk6IFVpbnQ4QXJyYXk7XG59XG5cbi8qKiBJbnB1dCB0eXBlIGZvciBpbnNjcmlwdGlvbiBmdW5jdGlvbnMgLSBlaXRoZXIgYSBCSVAzMi1saWtlIGtleSBvciByYXcgcHVibGljIGtleSBieXRlcyAqL1xuZXhwb3J0IHR5cGUgS2V5SW5wdXQgPSBCSVAzMkxpa2UgfCBVaW50OEFycmF5O1xuXG5mdW5jdGlvbiBpc0JJUDMyTGlrZShrZXk6IEtleUlucHV0KToga2V5IGlzIEJJUDMyTGlrZSB7XG4gIHJldHVybiB0eXBlb2Yga2V5ID09PSAnb2JqZWN0JyAmJiBrZXkgIT09IG51bGwgJiYgJ3B1YmxpY0tleScgaW4ga2V5ICYmICFBcnJheUJ1ZmZlci5pc1ZpZXcoa2V5KTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGNvbXByZXNzZWQgcHVibGljIGtleSBmcm9tIGtleSBpbnB1dC5cbiAqIEhhbmRsZXMgQklQMzItbGlrZSBvYmplY3RzIGFuZCByYXcgcHVia2V5IGJ5dGVzICgzMiBvciAzMyBieXRlcykuXG4gKi9cbmZ1bmN0aW9uIGdldENvbXByZXNzZWRQdWJsaWNLZXkoa2V5OiBLZXlJbnB1dCk6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBwdWJrZXkgPSBpc0JJUDMyTGlrZShrZXkpID8ga2V5LnB1YmxpY0tleSA6IGtleTtcblxuICBpZiAocHVia2V5Lmxlbmd0aCA9PT0gMzMpIHtcbiAgICByZXR1cm4gcHVia2V5O1xuICB9XG4gIGlmIChwdWJrZXkubGVuZ3RoID09PSAzMikge1xuICAgIC8vIHgtb25seSBwdWJrZXkgLSBwcmVwZW5kIDB4MDIgcGFyaXR5IGJ5dGUgdG8gbWFrZSBjb21wcmVzc2VkXG4gICAgY29uc3QgY29tcHJlc3NlZFB1YmtleSA9IG5ldyBVaW50OEFycmF5KDMzKTtcbiAgICBjb21wcmVzc2VkUHVia2V5WzBdID0gMHgwMjtcbiAgICBjb21wcmVzc2VkUHVia2V5LnNldChwdWJrZXksIDEpO1xuICAgIHJldHVybiBjb21wcmVzc2VkUHVia2V5O1xuICB9XG4gIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwdWJsaWMga2V5IGxlbmd0aDogJHtwdWJrZXkubGVuZ3RofS4gRXhwZWN0ZWQgMzIgb3IgMzMgYnl0ZXMuYCk7XG59XG5cbi8qKlxuICogQ3JlYXRlIHRoZSBQMlRSIG91dHB1dCBzY3JpcHQgZm9yIGFuIGluc2NyaXB0aW9uLlxuICpcbiAqIEBwYXJhbSBrZXkgLSBCSVAzMiBrZXkgb3IgcHVibGljIGtleSBieXRlcyAoMzItYnl0ZSB4LW9ubHkgb3IgMzMtYnl0ZSBjb21wcmVzc2VkKVxuICogQHBhcmFtIGNvbnRlbnRUeXBlIC0gTUlNRSB0eXBlIG9mIHRoZSBpbnNjcmlwdGlvbiAoZS5nLiwgXCJ0ZXh0L3BsYWluXCIsIFwiaW1hZ2UvcG5nXCIpXG4gKiBAcGFyYW0gaW5zY3JpcHRpb25EYXRhIC0gVGhlIGluc2NyaXB0aW9uIGRhdGEgYnl0ZXNcbiAqIEByZXR1cm5zIFRoZSBQMlRSIG91dHB1dCBzY3JpcHQgZm9yIHRoZSBpbnNjcmlwdGlvbiBjb21taXQgYWRkcmVzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlT3V0cHV0U2NyaXB0Rm9ySW5zY3JpcHRpb24oXG4gIGtleTogS2V5SW5wdXQsXG4gIGNvbnRlbnRUeXBlOiBzdHJpbmcsXG4gIGluc2NyaXB0aW9uRGF0YTogVWludDhBcnJheVxuKTogVWludDhBcnJheSB7XG4gIGNvbnN0IGNvbXByZXNzZWRQdWJrZXkgPSBnZXRDb21wcmVzc2VkUHVibGljS2V5KGtleSk7XG4gIGNvbnN0IGVjcGFpciA9IEVDUGFpci5mcm9tUHVibGljS2V5KGNvbXByZXNzZWRQdWJrZXkpO1xuICBjb25zdCByZXN1bHQgPSB3YXNtSW5zY3JpcHRpb25zLmNyZWF0ZUluc2NyaXB0aW9uUmV2ZWFsRGF0YShlY3BhaXIsIGNvbnRlbnRUeXBlLCBpbnNjcmlwdGlvbkRhdGEpO1xuICByZXR1cm4gcmVzdWx0Lm91dHB1dFNjcmlwdDtcbn1cblxuLyoqXG4gKiBDcmVhdGUgaW5zY3JpcHRpb24gcmV2ZWFsIGRhdGEgaW5jbHVkaW5nIHRoZSBjb21taXQgYWRkcmVzcyBhbmQgdGFwIGxlYWYgc2NyaXB0LlxuICpcbiAqIEBwYXJhbSBrZXkgLSBCSVAzMiBrZXkgb3IgcHVibGljIGtleSBieXRlcyAoMzItYnl0ZSB4LW9ubHkgb3IgMzMtYnl0ZSBjb21wcmVzc2VkKVxuICogQHBhcmFtIGNvbnRlbnRUeXBlIC0gTUlNRSB0eXBlIG9mIHRoZSBpbnNjcmlwdGlvbiAoZS5nLiwgXCJ0ZXh0L3BsYWluXCIsIFwiaW1hZ2UvcG5nXCIpXG4gKiBAcGFyYW0gaW5zY3JpcHRpb25EYXRhIC0gVGhlIGluc2NyaXB0aW9uIGRhdGEgYnl0ZXNcbiAqIEBwYXJhbSBjb2luTmFtZSAtIENvaW4gbmFtZSAoZS5nLiwgXCJidGNcIiwgXCJ0YnRjXCIpXG4gKiBAcmV0dXJucyBQcmVwYXJlZEluc2NyaXB0aW9uUmV2ZWFsRGF0YSB3aXRoIGFkZHJlc3MsIHZzaXplIGVzdGltYXRlLCBhbmQgdGFwIGxlYWYgc2NyaXB0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVJbnNjcmlwdGlvblJldmVhbERhdGEoXG4gIGtleTogS2V5SW5wdXQsXG4gIGNvbnRlbnRUeXBlOiBzdHJpbmcsXG4gIGluc2NyaXB0aW9uRGF0YTogVWludDhBcnJheSxcbiAgY29pbk5hbWU6IENvaW5OYW1lXG4pOiBQcmVwYXJlZEluc2NyaXB0aW9uUmV2ZWFsRGF0YSB7XG4gIGNvbnN0IGNvbXByZXNzZWRQdWJrZXkgPSBnZXRDb21wcmVzc2VkUHVibGljS2V5KGtleSk7XG4gIGNvbnN0IGVjcGFpciA9IEVDUGFpci5mcm9tUHVibGljS2V5KGNvbXByZXNzZWRQdWJrZXkpO1xuXG4gIGNvbnN0IHdhc21SZXN1bHQgPSB3YXNtSW5zY3JpcHRpb25zLmNyZWF0ZUluc2NyaXB0aW9uUmV2ZWFsRGF0YShlY3BhaXIsIGNvbnRlbnRUeXBlLCBpbnNjcmlwdGlvbkRhdGEpO1xuXG4gIC8vIENvbnZlcnQgb3V0cHV0U2NyaXB0IHRvIGFkZHJlc3MgZm9yIHRoZSBnaXZlbiBuZXR3b3JrXG4gIGNvbnN0IGFkZHJlc3MgPSB3YXNtQWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0V2l0aENvaW4od2FzbVJlc3VsdC5vdXRwdXRTY3JpcHQsIGNvaW5OYW1lKTtcblxuICByZXR1cm4ge1xuICAgIGFkZHJlc3MsXG4gICAgcmV2ZWFsVHJhbnNhY3Rpb25WU2l6ZTogd2FzbVJlc3VsdC5yZXZlYWxUcmFuc2FjdGlvblZTaXplLFxuICAgIHRhcExlYWZTY3JpcHQ6IHdhc21SZXN1bHQudGFwTGVhZlNjcmlwdCxcbiAgfTtcbn1cblxuLyoqXG4gKiBTaWduIGEgcmV2ZWFsIHRyYW5zYWN0aW9uLlxuICpcbiAqIENyZWF0ZXMgYW5kIHNpZ25zIHRoZSByZXZlYWwgdHJhbnNhY3Rpb24gdGhhdCBzcGVuZHMgZnJvbSB0aGUgY29tbWl0IG91dHB1dFxuICogYW5kIHNlbmRzIHRoZSBpbnNjcmlwdGlvbiB0byB0aGUgcmVjaXBpZW50LlxuICpcbiAqIEBwYXJhbSBwcml2YXRlS2V5IC0gMzItYnl0ZSBwcml2YXRlIGtleVxuICogQHBhcmFtIHRhcExlYWZTY3JpcHQgLSBUaGUgdGFwIGxlYWYgc2NyaXB0IGZyb20gY3JlYXRlSW5zY3JpcHRpb25SZXZlYWxEYXRhXG4gKiBAcGFyYW0gY29tbWl0QWRkcmVzcyAtIFRoZSBjb21taXQgYWRkcmVzc1xuICogQHBhcmFtIHJlY2lwaWVudEFkZHJlc3MgLSBXaGVyZSB0byBzZW5kIHRoZSBpbnNjcmlwdGlvblxuICogQHBhcmFtIHVuc2lnbmVkQ29tbWl0VHggLSBUaGUgdW5zaWduZWQgY29tbWl0IHRyYW5zYWN0aW9uIGJ5dGVzXG4gKiBAcGFyYW0gY29pbk5hbWUgLSBDb2luIG5hbWUgKGUuZy4sIFwiYnRjXCIsIFwidGJ0Y1wiKVxuICogQHJldHVybnMgVGhlIHNpZ25lZCBQU0JUIGFzIGJ5dGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduUmV2ZWFsVHJhbnNhY3Rpb24oXG4gIHByaXZhdGVLZXk6IFVpbnQ4QXJyYXksXG4gIHRhcExlYWZTY3JpcHQ6IFRhcExlYWZTY3JpcHQsXG4gIGNvbW1pdEFkZHJlc3M6IHN0cmluZyxcbiAgcmVjaXBpZW50QWRkcmVzczogc3RyaW5nLFxuICB1bnNpZ25lZENvbW1pdFR4OiBVaW50OEFycmF5LFxuICBjb2luTmFtZTogQ29pbk5hbWVcbik6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBlY3BhaXIgPSBFQ1BhaXIuZnJvbVByaXZhdGVLZXkocHJpdmF0ZUtleSk7XG4gIGNvbnN0IGNvbW1pdFR4ID0gVHJhbnNhY3Rpb24uZnJvbUJ5dGVzKHVuc2lnbmVkQ29tbWl0VHgpO1xuICBjb25zdCBjb21taXRPdXRwdXRTY3JpcHQgPSB3YXNtQWRkcmVzcy50b091dHB1dFNjcmlwdFdpdGhDb2luKGNvbW1pdEFkZHJlc3MsIGNvaW5OYW1lKTtcbiAgY29uc3QgcmVjaXBpZW50T3V0cHV0U2NyaXB0ID0gd2FzbUFkZHJlc3MudG9PdXRwdXRTY3JpcHRXaXRoQ29pbihyZWNpcGllbnRBZGRyZXNzLCBjb2luTmFtZSk7XG5cbiAgcmV0dXJuIHdhc21JbnNjcmlwdGlvbnMuc2lnblJldmVhbFRyYW5zYWN0aW9uKFxuICAgIGVjcGFpcixcbiAgICB0YXBMZWFmU2NyaXB0LFxuICAgIGNvbW1pdFR4LFxuICAgIGNvbW1pdE91dHB1dFNjcmlwdCxcbiAgICByZWNpcGllbnRPdXRwdXRTY3JpcHQsXG4gICAgREVGQVVMVF9QT1NUQUdFX1NBVFNcbiAgKTtcbn1cbiJdfQ==