npm package: @mintify/ordinals-library
Description: Ordinals market place Javascript library.
Author: kakashigr
Latest version: 1.2.5

# Ordinals library 📝

An Ordinals marketplace Javascript library.

Supported Features

1. Consolidate all UTXOs in a wallet to reduce future transaction fees
2. Dummy UTXO management
    1. Check if an address have dummy UTXOs to execute ordinals sales
    2. Generate dummy UTXOs in a wallet to execute ordinals sales
3. Create listing PSBTs, so an user can approve an ordinal transfer in exchange for a locked payment
4. Create buy PSBTs, so an user can approve an ordinal transfer, providing the requested payment and the required fees for the marketplace
5. Create bid PSBTs, so an user can propose an ordinal transfer in exchange for a locked payment, providing the required fees for the marketplace
6. Complete a sale from a listing or a bid, consolidating the required signatures and broadcasting the transaction to the Bitcoin network
7. Network fees management, using one of the following estimates
    1. fastestFee: pay more fees, complete the transaction as quick as possible
    2. halfHourFee: try to complete the transaction in around 30 minutes
    3. hourFee: try to complete the transaction in around 1 hour
    4. minimumFee: pay less fees, complete the transaction slowly

The library will manage the required scripts and signatures to support payments from all wallet types: Legacy (P2PKH), Nested Segwit (P2SH-P2WPKH), Native segwit (P2WPKH) and Taproot (P2TR). Taking into account filtering out UTXOs that hold Ordinals, BRC-20s and Runes.

## Get Started 🚀

Run `yarn` to install dependancies

Run `yarn build` to build the new library.

Need to push changes before publishing

Run `yarn publish --access restricted` to publish to npm. Will ask to update version number if you have not done so.

Run `yarn test` to run unit tests.

## Using the library

### Add to project

Run ```yarn add @mintify/ordinals-library@*```

The `@*` makes sure that the latest version is always intalled.

#### Use developer branch in projects
To use your dev branch in your projects, replace the library version in your package.json from `*` to `https://github.com/Mintify-Inc/ordinals-library.git#<branch>` where `<branch>` is your branch name.

### Initialize market

``` Javascript
import { OrdinalsMarketplace } from '@mintify/ordinals-library';

export const ordinalsMarketplace = new OrdinalsMarketplace({
  // Quicknode URLs to connect, it will rotate requests between the specified
  // URLs, it rotates between Bitcoin, Blockbook and Ordinals rpc methods
  // https://www.quicknode.com/docs/bitcoin
  rpcUrls: ['rpcUrl', 'rpcUrl'],

  // Mempool URL to connect to, is only used for fees, and they are cached
  // and refreshed every 10 seconds
  mempoolUrl: 'mempoolUrl',

  fees: {
    // Minimum amount to be paid in fees to the marketplace
    minAmount: 580,

    // Percentage from the transfer price, charged to the person
    // that proposed the transaction
    makerPercentage: 0.5,

    // Percentage from the transfer price, charged to the person
    // that accepted the transaction
    takerPercentage: 2,

    // Marketplace address that will receive the fees
    receiveAddress: '3AsJ5dUGLerZhFfLzWbeWWR1rEhFxLG1Nj',
  },
});
```

### Dummy UTXOs management

In order to complete listings, an address should have enough dummy UTXOs to complete the transaction, this will be the amount of ordinals to purchase, plus one. For example, if an user wants to purchase 3 listed ordinals in a single transaction, they need to have at least 4 dummy UTXOs on their wallet

#### Verify how many dummy UTXOs an user have on their wallet, use the following method
``` Javascript
// Address to check, use the payment address of the user
const address = '3KiVEio8GykaPGkMGbdCWTQCMCoZ4zgnbt'

// Amount to retrieve
const amount = 2

// utxos will be an array containing the current dummy utxos found in the
// wallet, which will be at most the provided amount 
const utxos = ordinalsMarketplace.getDummyUtxos(address, amount)

```

#### Create more dummy UTXOs
``` Javascript
// Payment address signer
const signer: Signer = {
  address: '3KiVEio8GykaPGkMGbdCWTQCMCoZ4zgnbt',
  publicKey: '03dbf06b240cf027451f716b5710f5867a6c73f52d5a59f84413383aa59d284ee0'
}

// Amount of dummy UTXOs to ensure the wallet will have, is important to note
// that if a wallet already have UTXOs, only the remaining amount will be
// generated, for example, if you request to generate 10, and the address
// already have 6, a PSBT to generate 4 more will be created.
const amount = 10;

// Fee rate
const feeRate = 'halfHourFee'

const psbt = await ordinalsMarketplace.buildGenerateDummyUTXOs(
  signer,
  amount,
  feeRate
);
```
Once the transaction is broadcasted and confirmed, the new UTXOs for the user will be created

### List Ordinals

After the listing is created, remember to have broadcast as false, that way the library will return the signed version of the listing PSBT. After that, store in the database both the listingData and the signed PSBT, since they will be required to later complete the sale

``` Javascript
// Ordinal inscription ID to list
const inscriptionId = 'ded04890c42cd96d353620088fd11eaba9003697e2f58e61bb424d91d1eda492i0'

// Signer of the current holder of the ordinal
const sellerOrdinalsSigner: Signer = {
  address: 'bc1p7zh4lfdgym6cs6ptndfmg0u93s7d5vqdt0ll94nlrg9c500ez93qrscanv',
  publicKey: 'f5d4359fffbc7c581dc1927a94a99c357d3443d0f3ac08b23adfa223e946ba74'
}

// Address to send the payment once the sale is completed
const sellerPaymentsAddress = '38mjuTFnpL21zDe4TwPRoLhAEi5L6NrPZW'

// Listing price in sats
const price = 10000

const listingData = {
  inscriptionId,
  sellerOrdinalsSigner,
  sellerPaymentsAddress,
  price,
}

const psbt = ordinalsMarketplace.buildListing(listingData);
```

### Buying Ordinals
While buying ordinals, you would need the same listingData used to create the listing, you can send multiple at the same time in order to purchase multiple ordinals in a single transaction.

#### Create Purchase PSPT
``` Javascript
// Array of listings to purchase (same information utilized to
// create the listings)
const listings = [listingAData, listingBData]

// Address from the buyer to execute the payment
const buyerPaymentsSigner = {...}

// Address where the buyer will receive the ordinals
const buyerOrdinalsAddress '...'

// Fee rate
const feeRate = 'halfHourFee'

const psbt = await ordinalsMarketplace.buildBuyPsbt(
  listings,
  buyerPaymentsSigner,
  buyerOrdinalsAddress,
  feeRate
);
```

At this stage, you will have both the signed version of the listings PSBT and the signed version of the buy PSBT, in order to complete the sale,
#### Validate transaction and broadcast 

``` Javascript
// An array with signed PSBTs created in the listing step
const signedListingsPsbt = ['...', '...']

// The signed buy PSBT
const signedBuyPsbt = '...'

// When broadcast is set as true, the sale will be broadcasted to the network
// and executed, transfering the ordinals from the sellet to the buyer, 
// the due payment to the seller, and the fees to the marketplace, for
// facilitating the sale

// When broadcast is set as false, a validation against the sale will happen,
// this can be used to test the sale workflow without paying fees, since you
// will know if the transaction will succeed without broadcasting to the
// blockchain
const broadcast = true

// If broadcast is set the false, the validation result will be returned from
// the function, or an error will be thrown if the transaction is not valid
const validationResult = await ordinalsMarketplace.completeSale(
  [listing.signedBase64Psbt],
  signedBase64Psbt,
  broadcast // false
);

// If broadcast is true, the transaction ID will be returned 
const transactionId = await ordinalsMarketplace.completeSale(
  [listing.signedBase64Psbt],
  signedBase64Psbt,
  broadcast // true
);
```

### Making Bids

The buyer can propose a different price than the current listing, by making a bid,in this process no dummy UTXOs are required. 
#### Create a bid PSBT. 
In order to bid, you will need to know beforehand the address and public key of the seller


``` Javascript
// The price inside the listingData should be the new price that the buyer
// is proposing
const listingData = {...}

// Address from the buyer to execute the payment
const buyerPaymentsSigner = {...}

// Address where the buyer will receive the ordinal
const buyerOrdinalsAddress = '...'

// Fee rate
const feeRateTier = 'halfHourFee'

const psbt = await ordinalsMarketplace.buildBidPsbt(
    listingData,
    buyerPaymentsSigner,
    buyerOrdinalsAddress,
    feeRateTier
)
```

After that sign the PSBT using the buyer address with the usual workflow, and store the signed PSBT in the database, then, propose the bid to the seller, for them to accept, just sign the same PSBT but now using the seller address, you can have broadcast as true, since at this stage the transaction will be valid