@bitgo/utxo-ord
Version:
Utilities for building ordinals with BitGo utxo-lib
61 lines (58 loc) • 7.13 kB
JavaScript
/*
https://github.com/casey/ord/blob/master/bip.mediawiki#terminology-and-notation
> A satpoint may be used to indicate the location of a sat within an output.
> A satpoint consists of an outpoint, i.e., a transaction ID and output index, with the addition of
> the offset of the ordinal within that output. For example, if the sat in question is at offset 6
> in the first output of a transaction, its satpoint is:
> `680df1e4d43016571e504b0b142ee43c5c0b83398a97bdcfd94ea6f287322d22:0:6`
*/
/**
* Parse an output ID (txid:vout) into its components.
*/
export function parseOutputId(outputId) {
const colonIndex = outputId.lastIndexOf(':');
if (colonIndex === -1) {
throw new Error(`Invalid output id format: missing colon`);
}
const txid = outputId.slice(0, colonIndex);
const voutStr = outputId.slice(colonIndex + 1);
if (txid.length !== 64 || !/^[0-9a-fA-F]+$/.test(txid)) {
throw new Error(`Invalid txid: must be 64 hex characters`);
}
const vout = parseInt(voutStr, 10);
if (isNaN(vout) || vout < 0) {
throw new Error(`Invalid vout: must be non-negative integer`);
}
return { txid, vout };
}
export function parseSatPoint(p) {
const parts = p.split(':');
if (parts.length !== 3) {
throw new Error(`expected format txid:vout:sat`);
}
const [txid, vout, offsetStr] = parts;
const offset = BigInt(offsetStr);
if (offset.toString() !== offsetStr) {
throw new Error(`SatPoint offset must be base-10`);
}
if (offset < 0) {
throw new Error(`SatPoint offset must be positive`);
}
return {
...parseOutputId([txid, vout].join(':')),
offset,
};
}
export function formatSatPoint(p) {
return `${p.txid}:${p.vout}:${p.offset}`;
}
export function isSatPoint(v) {
try {
parseSatPoint(v);
return true;
}
catch {
return false;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2F0UG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvU2F0UG9pbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7RUFVRTtBQUlGOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxRQUFnQjtJQUM1QyxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzdDLElBQUksVUFBVSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUMzQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDdkQsTUFBTSxJQUFJLEtBQUssQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFDeEIsQ0FBQztBQUVELE1BQU0sVUFBVSxhQUFhLENBQUMsQ0FBVztJQUN2QyxNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUNELE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUN0QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDakMsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFDRCxJQUFJLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBQ0QsT0FBTztRQUNMLEdBQUcsYUFBYSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QyxNQUFNO0tBQ1AsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLFVBQVUsY0FBYyxDQUFDLENBQWlEO0lBQzlFLE9BQU8sR0FBRyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBVyxDQUFDO0FBQ3BELENBQUM7QUFFRCxNQUFNLFVBQVUsVUFBVSxDQUFDLENBQVM7SUFDbEMsSUFBSSxDQUFDO1FBQ0gsYUFBYSxDQUFDLENBQWEsQ0FBQyxDQUFDO1FBQzdCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuXG5odHRwczovL2dpdGh1Yi5jb20vY2FzZXkvb3JkL2Jsb2IvbWFzdGVyL2JpcC5tZWRpYXdpa2kjdGVybWlub2xvZ3ktYW5kLW5vdGF0aW9uXG5cbj4gQSBzYXRwb2ludCBtYXkgYmUgdXNlZCB0byBpbmRpY2F0ZSB0aGUgbG9jYXRpb24gb2YgYSBzYXQgd2l0aGluIGFuIG91dHB1dC5cbj4gQSBzYXRwb2ludCBjb25zaXN0cyBvZiBhbiBvdXRwb2ludCwgaS5lLiwgYSB0cmFuc2FjdGlvbiBJRCBhbmQgb3V0cHV0IGluZGV4LCB3aXRoIHRoZSBhZGRpdGlvbiBvZlxuPiB0aGUgb2Zmc2V0IG9mIHRoZSBvcmRpbmFsIHdpdGhpbiB0aGF0IG91dHB1dC4gRm9yIGV4YW1wbGUsIGlmIHRoZSBzYXQgaW4gcXVlc3Rpb24gaXMgYXQgb2Zmc2V0IDZcbj4gaW4gdGhlIGZpcnN0IG91dHB1dCBvZiBhIHRyYW5zYWN0aW9uLCBpdHMgc2F0cG9pbnQgaXM6XG4+IGA2ODBkZjFlNGQ0MzAxNjU3MWU1MDRiMGIxNDJlZTQzYzVjMGI4MzM5OGE5N2JkY2ZkOTRlYTZmMjg3MzIyZDIyOjA6NmBcblxuKi9cblxuZXhwb3J0IHR5cGUgU2F0UG9pbnQgPSBgJHtzdHJpbmd9OiR7bnVtYmVyfToke2JpZ2ludH1gO1xuXG4vKipcbiAqIFBhcnNlIGFuIG91dHB1dCBJRCAodHhpZDp2b3V0KSBpbnRvIGl0cyBjb21wb25lbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VPdXRwdXRJZChvdXRwdXRJZDogc3RyaW5nKTogeyB0eGlkOiBzdHJpbmc7IHZvdXQ6IG51bWJlciB9IHtcbiAgY29uc3QgY29sb25JbmRleCA9IG91dHB1dElkLmxhc3RJbmRleE9mKCc6Jyk7XG4gIGlmIChjb2xvbkluZGV4ID09PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBvdXRwdXQgaWQgZm9ybWF0OiBtaXNzaW5nIGNvbG9uYCk7XG4gIH1cbiAgY29uc3QgdHhpZCA9IG91dHB1dElkLnNsaWNlKDAsIGNvbG9uSW5kZXgpO1xuICBjb25zdCB2b3V0U3RyID0gb3V0cHV0SWQuc2xpY2UoY29sb25JbmRleCArIDEpO1xuICBpZiAodHhpZC5sZW5ndGggIT09IDY0IHx8ICEvXlswLTlhLWZBLUZdKyQvLnRlc3QodHhpZCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdHhpZDogbXVzdCBiZSA2NCBoZXggY2hhcmFjdGVyc2ApO1xuICB9XG4gIGNvbnN0IHZvdXQgPSBwYXJzZUludCh2b3V0U3RyLCAxMCk7XG4gIGlmIChpc05hTih2b3V0KSB8fCB2b3V0IDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2b3V0OiBtdXN0IGJlIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyYCk7XG4gIH1cbiAgcmV0dXJuIHsgdHhpZCwgdm91dCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTYXRQb2ludChwOiBTYXRQb2ludCk6IHsgdHhpZDogc3RyaW5nOyB2b3V0OiBudW1iZXI7IG9mZnNldDogYmlnaW50IH0ge1xuICBjb25zdCBwYXJ0cyA9IHAuc3BsaXQoJzonKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcihgZXhwZWN0ZWQgZm9ybWF0IHR4aWQ6dm91dDpzYXRgKTtcbiAgfVxuICBjb25zdCBbdHhpZCwgdm91dCwgb2Zmc2V0U3RyXSA9IHBhcnRzO1xuICBjb25zdCBvZmZzZXQgPSBCaWdJbnQob2Zmc2V0U3RyKTtcbiAgaWYgKG9mZnNldC50b1N0cmluZygpICE9PSBvZmZzZXRTdHIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFNhdFBvaW50IG9mZnNldCBtdXN0IGJlIGJhc2UtMTBgKTtcbiAgfVxuICBpZiAob2Zmc2V0IDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgU2F0UG9pbnQgb2Zmc2V0IG11c3QgYmUgcG9zaXRpdmVgKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIC4uLnBhcnNlT3V0cHV0SWQoW3R4aWQsIHZvdXRdLmpvaW4oJzonKSksXG4gICAgb2Zmc2V0LFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0U2F0UG9pbnQocDogeyB0eGlkOiBzdHJpbmc7IHZvdXQ6IG51bWJlcjsgb2Zmc2V0OiBiaWdpbnQgfSk6IFNhdFBvaW50IHtcbiAgcmV0dXJuIGAke3AudHhpZH06JHtwLnZvdXR9OiR7cC5vZmZzZXR9YCBhcyBjb25zdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU2F0UG9pbnQodjogc3RyaW5nKTogdiBpcyBTYXRQb2ludCB7XG4gIHRyeSB7XG4gICAgcGFyc2VTYXRQb2ludCh2IGFzIFNhdFBvaW50KTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG4iXX0=