UNPKG

@bitgo/utxo-ord

Version:

Utilities for building ordinals with BitGo utxo-lib

89 lines (87 loc) 14.5 kB
/* 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==