-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0958e8f
Showing
21 changed files
with
2,504 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
github: paulmillr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Run node.js tests | ||
on: | ||
- push | ||
- pull_request | ||
jobs: | ||
test: | ||
name: v${{ matrix.node }} @ ubuntu-latest | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
node: | ||
- 18 | ||
- 20 | ||
steps: | ||
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 | ||
- name: Use Node.js ${{ matrix.node }} | ||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 | ||
with: | ||
node-version: ${{ matrix.node }} | ||
- run: npm install | ||
- run: npm run build --if-present | ||
- run: npm test | ||
- run: npm run lint --if-present |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Publish package to npm | ||
on: | ||
release: | ||
types: [created] | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
id-token: write | ||
steps: | ||
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 | ||
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 | ||
with: | ||
node-version: 20 | ||
registry-url: 'https://registry.npmjs.org' | ||
cache: npm | ||
- run: npm install -g npm | ||
- run: npm ci | ||
- run: npm run build | ||
- run: npm publish --provenance --access public | ||
env: | ||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules | ||
/build/micro-eth-signer.js | ||
/lib | ||
/index.js | ||
/index.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2024 Paul Miller (https://paulmillr.com) | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the “Software”), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# micro-ordinals | ||
|
||
Minimal JS library for [ordinals](https://ordinals.com) and inscriptions on top of | ||
[scure-btc-signer](https://github.com/paulmillr/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](#creating-inscription) | ||
- [TypeScript API](#typescript-api) | ||
- [CLI](#cli) | ||
|
||
### Creating inscription | ||
|
||
```js | ||
// 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 | ||
|
||
```ts | ||
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] <path> | ||
|
||
- 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](https://mempool.space/testnet) and | ||
[ordinalsbot](https://testnet-explorer.ordinalsbot.com). | ||
|
||
### Getting testnet coins | ||
|
||
There are several faucets: | ||
[uo1](https://bitcoinfaucet.uo1.net/send.php), | ||
[eu](https://coinfaucet.eu/en/btc-testnet/), | ||
[pump](https://cryptopump.info/send.php) | ||
|
||
### 3rd-party wallets | ||
|
||
To use [sparrow](https://sparrowwallet.com) on mac: | ||
|
||
open /Applications/Sparrow.app --args -n testnet | ||
|
||
## License | ||
|
||
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"type": "module", | ||
"sideEffects": false, | ||
"browser": { | ||
"node:crypto": false | ||
}, | ||
"node": { | ||
"./crypto": "./esm/cryptoNode.js" | ||
} | ||
} |
Oops, something went wrong.