Skip to content

Commit

Permalink
Prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillr committed Jun 28, 2024
1 parent a2be9aa commit ecea568
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 58 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"name": "micro-ordinals",
"version": "0.1.1",
"description": "Manage ordinals, inscriptions and runes using scure-btc-signer",
"files": ["lib", "src"],
"files": [
"lib",
"src"
],
"bin": {
"ord": "lib/esm/cli.js"
},
Expand All @@ -21,7 +24,7 @@
"@types/node": "20.12.7",
"micro-bmark": "0.3.1",
"micro-should": "0.4.0",
"prettier": "3.1.1",
"prettier": "3.3.2",
"typescript": "5.3.2"
},
"scripts": {
Expand All @@ -31,6 +34,7 @@
"format": "prettier --print-width 100 --single-quote --write src",
"test": "node test/index.test.js"
},
"sideEffects": false,
"keywords": [
"ordinal",
"inscription",
Expand Down
86 changes: 34 additions & 52 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Coder, hex, utf8 } from "@scure/base";
import * as P from "micro-packed";
import { Coder, hex, utf8 } from '@scure/base';
import * as P from 'micro-packed';
import {
Script,
ScriptType,
OptScript,
CustomScript,
MAX_SCRIPT_BYTE_LENGTH,
utils,
} from "@scure/btc-signer";
import { CBOR } from "./cbor.js";
} from '@scure/btc-signer';
import { CBOR } from './cbor.js';

type Bytes = Uint8Array;
const PROTOCOL_ID = /* @__PURE__ */ utf8.decode("ord");
const PROTOCOL_ID = /* @__PURE__ */ utf8.decode('ord');

function splitChunks(buf: Bytes): Bytes[] {
const res = [];
Expand All @@ -27,9 +27,8 @@ const RawInscriptionId = /* @__PURE__ */ P.tuple([

export const InscriptionId: P.Coder<string, Bytes> = {
encode(data: string) {
const [txId, index] = data.split("i", 2);
if (`${+index}` !== index)
throw new Error(`InscriptionId wrong index: ${index}`);
const [txId, index] = data.split('i', 2);
if (`${+index}` !== index) throw new Error(`InscriptionId wrong index: ${index}`);
return RawInscriptionId.encode([hex.decode(txId), +index]);
},
decode(data: Bytes) {
Expand Down Expand Up @@ -97,34 +96,28 @@ const TagCoder: P.Coder<TagRaw[], Tags> = {
const res: Partial<Tags> = {};
if (unknown.length) res.unknown = unknown;
for (const field in tmp) {
if (field === "parent" && tmp[field].length > 1) {
res[field as TagName] = tmp[field].map((i) =>
TagCoders.parent.decode(i),
);
if (field === 'parent' && tmp[field].length > 1) {
res[field as TagName] = tmp[field].map((i) => TagCoders.parent.decode(i));
continue;
}
res[field as TagName] = TagCoders[field as TagName].decode(
utils.concatBytes(...tmp[field]),
);
res[field as TagName] = TagCoders[field as TagName].decode(utils.concatBytes(...tmp[field]));
}
return res as Tags;
},
decode(to: Tags): TagRaw[] {
const res: TagRaw[] = [];
for (const field in to) {
if (field === "unknown") continue;
if (field === 'unknown') continue;
const tagName = TagCoderInternal.encode(field);
if (field === "parent" && Array.isArray(to.parent)) {
for (const p of to.parent)
res.push({ tag: tagName, data: TagCoders.parent.encode(p) });
if (field === 'parent' && Array.isArray(to.parent)) {
for (const p of to.parent) res.push({ tag: tagName, data: TagCoders.parent.encode(p) });
continue;
}
const bytes = TagCoders[field as TagName].encode(to[field as TagName]);
for (const data of splitChunks(bytes)) res.push({ tag: tagName, data });
}
if (to.unknown) {
if (!Array.isArray(to.unknown))
throw new Error("ordinals/TagCoder: unknown should be array");
if (!Array.isArray(to.unknown)) throw new Error('ordinals/TagCoder: unknown should be array');
for (const [tag, data] of to.unknown) res.push({ tag, data });
}
return res;
Expand All @@ -133,21 +126,20 @@ const TagCoder: P.Coder<TagRaw[], Tags> = {

export type Inscription = { tags: Tags; body: Bytes; cursed?: boolean };
type OutOrdinalRevealType = {
type: "tr_ord_reveal";
type: 'tr_ord_reveal';
pubkey: Bytes;
inscriptions: Inscription[];
};

const parseEnvelopes = (script: ScriptType, pos = 0) => {
if (!Number.isSafeInteger(pos))
throw new Error(`parseInscription: wrong pos=${typeof pos}`);
if (!Number.isSafeInteger(pos)) throw new Error(`parseInscription: wrong pos=${typeof pos}`);
const envelopes = [];
// Inscriptions with broken parsing are called 'cursed' (stutter or pushnum)
let stutter = false;
main: for (; pos < script.length; pos++) {
const instr = script[pos];
if (instr !== 0) continue;
if (script[pos + 1] !== "IF") {
if (script[pos + 1] !== 'IF') {
if (script[pos + 1] === 0) stutter = true;
continue main;
}
Expand All @@ -163,17 +155,17 @@ const parseEnvelopes = (script: ScriptType, pos = 0) => {
for (let j = pos + 3; j < script.length; j++) {
const op = script[j];
// done
if (op === "ENDIF") {
if (op === 'ENDIF') {
envelopes.push({ start: pos + 3, end: j, pushnum, payload, stutter });
pos = j;
break;
}
if (op === "1NEGATE") {
if (op === '1NEGATE') {
pushnum = true;
payload.push(new Uint8Array([0x81]));
continue;
}
if (typeof op === "number" && 1 <= op && op <= 16) {
if (typeof op === 'number' && 1 <= op && op <= 16) {
pushnum = true;
payload.push(new Uint8Array([op]));
continue;
Expand All @@ -190,12 +182,9 @@ const parseEnvelopes = (script: ScriptType, pos = 0) => {
};

// Additional API for parsing inscriptions
export function parseInscriptions(
script: ScriptType,
strict = false,
): Inscription[] | undefined {
export function parseInscriptions(script: ScriptType, strict = false): Inscription[] | undefined {
if (strict && (!utils.isBytes(script[0]) || script[0].length !== 32)) return;
if (strict && script[1] !== "CHECKSIG") return;
if (strict && script[1] !== 'CHECKSIG') return;

const envelopes = parseEnvelopes(script);
const inscriptions: Inscription[] = [];
Expand All @@ -210,10 +199,8 @@ export function parseInscriptions(
for (; i < payload.length && payload[i] !== 0; i += 2) {
const tag = payload[i];
const data = payload[i + 1];
if (!utils.isBytes(tag))
throw new Error("parseInscription: non-bytes tag");
if (!utils.isBytes(data))
throw new Error("parseInscription: non-bytes tag data");
if (!utils.isBytes(tag)) throw new Error('parseInscription: non-bytes tag');
if (!utils.isBytes(data)) throw new Error('parseInscription: non-bytes tag data');
tags.push({ tag, data });
}
while (payload[i] === 0 && i < payload.length) i++;
Expand All @@ -238,19 +225,15 @@ export function parseInscriptions(
* Parse inscriptions from reveal tx input witness (tx.inputs[0].finalScriptWitness)
*/
export function parseWitness(witness: Bytes[]): Inscription[] | undefined {
if (witness.length !== 3) throw new Error("Wrong witness");
if (witness.length !== 3) throw new Error('Wrong witness');
// We don't validate other parts of witness here since we want to parse
// as much stuff as possible. When creating inscription, it is done more strictly
return parseInscriptions(Script.decode(witness[1]));
}

export const OutOrdinalReveal: Coder<
OptScript,
OutOrdinalRevealType | undefined
> &
CustomScript = {
export const OutOrdinalReveal: Coder<OptScript, OutOrdinalRevealType | undefined> & CustomScript = {
encode(from: ScriptType): OutOrdinalRevealType | undefined {
const res: Partial<OutOrdinalRevealType> = { type: "tr_ord_reveal" };
const res: Partial<OutOrdinalRevealType> = { type: 'tr_ord_reveal' };
try {
res.inscriptions = parseInscriptions(from, true);
res.pubkey = from[0] as Bytes;
Expand All @@ -260,22 +243,21 @@ export const OutOrdinalReveal: Coder<
return res as OutOrdinalRevealType;
},
decode: (to: OutOrdinalRevealType): OptScript => {
if (to.type !== "tr_ord_reveal") return;
const out: ScriptType = [to.pubkey, "CHECKSIG"];
if (to.type !== 'tr_ord_reveal') return;
const out: ScriptType = [to.pubkey, 'CHECKSIG'];
for (const { tags, body } of to.inscriptions) {
out.push(0, "IF", PROTOCOL_ID);
out.push(0, 'IF', PROTOCOL_ID);
const rawTags = TagCoder.decode(tags);
for (const tag of rawTags) out.push(tag.tag, tag.data);
// Body
out.push(0);
for (const c of splitChunks(body)) out.push(c);
out.push("ENDIF");
out.push('ENDIF');
}
return out as any;
},
finalizeTaproot: (script: any, parsed: any, signatures: any) => {
if (signatures.length !== 1)
throw new Error("tr_ord_reveal/finalize: wrong signatures array");
if (signatures.length !== 1) throw new Error('tr_ord_reveal/finalize: wrong signatures array');
const [{ pubKey }, sig] = signatures[0];
if (!P.utils.equalBytes(pubKey, parsed.pubkey)) return;
return [sig, script];
Expand All @@ -288,9 +270,9 @@ export const OutOrdinalReveal: Coder<
*/
export function p2tr_ord_reveal(pubkey: Bytes, inscriptions: Inscription[]) {
return {
type: "tr_ord_reveal",
type: 'tr_ord_reveal',
script: P.apply(Script, P.coders.match([OutOrdinalReveal])).encode({
type: "tr_ord_reveal",
type: 'tr_ord_reveal',
pubkey,
inscriptions,
}),
Expand Down

0 comments on commit ecea568

Please sign in to comment.