npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

micro-ordinals

v0.1.1

Published

Manage ordinals, inscriptions and runes using scure-btc-signer

Downloads

733

Readme

micro-ordinals

Minimal JS library for ordinals and inscriptions on top of scure-btc-signer.

Use it as a library in your JS code, or run an included CLI tool. Inscriptions allow uploading random files on BTC blockchain.

Experimental: can lead to loss of funds until tested thoroughly.

Usage

npm install micro-ordinals

Creating inscription

// npm install micro-ordinals @scure/btc-signer @scure/base
import * as btc from '@scure/btc-signer';
import * as ordinals from 'micro-ordinals';
import { hex, utf8 } from '@scure/base';

const TESTNET = btc.utils.TEST_NETWORK;
const privKey = hex.decode('0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a');
const pubKey = btc.utils.pubSchnorr(privKey);
const customScripts = [ordinals.OutOrdinalReveal]; // Enable custom scripts outside

// This inscribes on first satoshi of first input (default)
const inscription = {
  tags: {
    contentType: 'application/json', // can be any format (MIME type)
    // ContentEncoding: 'br', // compression: only brotli supported
  },
  body: utf8.decode(JSON.stringify({ some: 1, test: 2, inscription: true, in: 'json' })),
  // One can use previously inscribed js scripts in html
  // utf8.decode(`<html><head></head><body><script src="/content/script_inscription_id"></script>test</html>`)
};

const revealPayment = btc.p2tr(
  undefined, // internalPubKey
  ordinals.p2tr_ord_reveal(pubKey, [inscription]), // TaprootScriptTree
  TESTNET, // mainnet or testnet
  false, // allowUnknownOutputs, safety feature
  customScripts // how to handle custom scripts
);

// We need to send some bitcoins to this address before reveal.
// Also, there should be enough to cover reveal tx fee.
console.log('Address', revealPayment.address); // 'tb1p5mykwcq5ly7y2ctph9r2wfgldq94eccm2t83dd58k785p0zqzwkspyjkp5'

// Be extra careful: it's possible to accidentally send an inscription as a fee.
// Also, rarity is only available with ordinal wallet.
// But you can parse other inscriptions and create a common one using this.
const changeAddr = revealPayment.address; // can be different
const revealAmount = 2000n;
const fee = 500n;

const tx = new btc.Transaction({ customScripts });
tx.addInput({
  ...revealPayment,
  // This is txid of tx with bitcoins we sent (replace)
  txid: '75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858',
  index: 0,
  witnessUtxo: { script: revealPayment.script, amount: revealAmount },
});
tx.addOutputAddress(changeAddr, revealAmount - fee, TESTNET);
tx.sign(privKey, undefined, new Uint8Array(32));
tx.finalize();

const txHex = hex.encode(tx.extract());
console.log(txHex); // Hex of reveal tx to broadcast
const tx2 = btc.Transaction.fromRaw(hex.decode(txHex)); // Parsing inscriptions
console.log('parsed', ordinals.parseWitness(tx2.inputs[0].finalScriptWitness));
console.log('vsize', tx2.vsize); // Reveal tx should pay at least this much fee

TypeScript API

import { Coder } from '@scure/base';
import * as P from 'micro-packed';
import { ScriptType, OptScript, CustomScript } from '@scure/btc-signer';
type Bytes = Uint8Array;
export declare const InscriptionId: P.Coder<string, Bytes>;
type TagRaw = {
    tag: Bytes;
    data: Bytes;
};
declare const TagCoders: {
    pointer: P.CoderType<bigint>;
    contentType: P.CoderType<string>;
    parent: P.Coder<string, Uint8Array>;
    metadata: P.CoderType<any>;
    metaprotocol: P.CoderType<string>;
    contentEncoding: P.CoderType<string>;
    delegate: P.Coder<string, Uint8Array>;
    rune: P.CoderType<bigint>;
    note: P.CoderType<string>;
};
export type Tags = Partial<{
    [K in keyof typeof TagCoders]: P.UnwrapCoder<(typeof TagCoders)[K]>;
}> & {
    unknown?: [Bytes, Bytes][];
};
export type Inscription = { tags: Tags; body: Bytes; cursed?: boolean; };
type OutOrdinalRevealType = { type: 'tr_ord_reveal'; pubkey: Bytes; inscriptions: Inscription[]; };
export declare const OutOrdinalReveal: Coder<OptScript, OutOrdinalRevealType | undefined> & CustomScript;
export declare function parseInscriptions(script: ScriptType, strict?: boolean): Inscription[] | undefined;
/**
 * Parse inscriptions from reveal tx input witness (tx.inputs[0].finalScriptWitness)
 */
export declare function parseWitness(witness: Bytes[]): Inscription[] | undefined;
/**
 * Create reveal transaction. Inscription created on spending output from this address by
 * revealing taproot script.
 */
export declare function p2tr_ord_reveal(pubkey: Bytes, inscriptions: Inscription[]): {
    type: string;
    script: Uint8Array;
};

CLI

npm install -g micro-ordinals ord file.jpg

Usage: ord [--net mainnet|testnet] [--priv key] [--recovery key] [--compress=on|off] [--fee 10.1] [--addr address]

  • net: bitcoin network
  • priv: taproot private key in WIF format, will be used for reveal transaction Don't use your wallet, priv should be a new one. We generate a temporary key, if none is provided
  • recovery: taproot private key in WIF format, can be used to recover any bitcoins sent to inscription address by accident without paying full inscription fee.
  • compress: inscriptions compressed with brotli. Compatible with explorers. default=on
  • fee: bitcoin network fee in satoshis
  • addr: address where inscription will be sent after reveal Important: first sat is always inscribed. Batch inscriptions are not supported.

Design

There is no network code. It makes package safer, but decreases developer experience.

We can probably fetch fees automatically, but utxo selection would become more complex. For example if user previously inscribed something or has rare ordinals, we need access to ordinal node to know that. Also, we don't know anything about frozen outputs in wallet: it is inside of a wallet only.

Edge cases to keep in mind:

  1. user added wrong txid/index or quit application after sending
    • we print temporary private key, user can restart by providing it with '--priv'
    • as long fee/network/path is same, you can restart process
  2. user sent less than amount or multiple UTXO.
    • this is actually harder, because any spend will require full inscription fee
    • for this we add recovery

Testing

Exporers

Use mempool and ordinalsbot.

Getting testnet coins

There are several faucets: uo1, eu, pump

3rd-party wallets

To use sparrow on mac:

open /Applications/Sparrow.app --args -n testnet

License

MIT (c) Paul Miller (https://paulmillr.com), see LICENSE file.