From 3c09a9f26be0debabb157630e225947a2db50569 Mon Sep 17 00:00:00 2001 From: topether21 Date: Mon, 20 May 2024 17:45:05 -0600 Subject: [PATCH] chore: add runes support --- package.json | 2 +- src/app/psbt.ts | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 602c3a0..f90bb9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nosft-core", - "version": "2.5.11", + "version": "2.5.12", "private": false, "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/src/app/psbt.ts b/src/app/psbt.ts index af57ccf..4939e45 100644 --- a/src/app/psbt.ts +++ b/src/app/psbt.ts @@ -18,7 +18,7 @@ import { Utxo } from './utxo'; type Metadata = { inputs: { index: number; type: 'Ordinal' | 'Cardinal' }[]; - outputs: { type: 'Ordinal' | 'Change' | 'Cardinal' }[]; + outputs: { type: 'Ordinal' | 'Change' | 'Cardinal' | 'Cardinal - Runes' | 'Ordinal - Runes' }[]; }; bitcoin.initEccLib(ecc); @@ -53,6 +53,35 @@ const Psbt = function (config) { const cryptoModule = Crypto(config); const utxoModule = Utxo(config); + const checkForRunes = async (utxos) => { + for (const utxo of utxos) { + try { + const output = await utxoModule.getOutput(`${utxo.txid}:${utxo.vout}`); + if (output.runes && output.runes.length > 0) { + return true; + } + } catch (e) { + console.log(`Error fetching output for ${utxo.txid}:${utxo.vout}`, e); + } + } + return false; + }; + + const filterCardinalUtxos = async (utxos) => { + const filteredUtxos = []; + for (const utxo of utxos) { + try { + const output = await utxoModule.getOutput(`${utxo.txid}:${utxo.vout}`); + if (!output.runes || output.runes.length === 0) { + filteredUtxos.push(utxo); + } + } catch (e) { + console.log(`Error fetching output for ${utxo.txid}:${utxo.vout}`, e); + } + } + return filteredUtxos; + }; + const psbtModule = { getPsbt, getPsbtBase64, @@ -356,12 +385,15 @@ const Psbt = function (config) { } // only used if selectedCardinalAmount is not large enough to cover fees - const cardinalUtxos = ownedUtxos.filter(utxo => !selectedUtxos.some(ownedUtxo => ownedUtxo.txid === utxo.txid)) + const availableCardinalUtxos = ownedUtxos.filter(utxo => !selectedUtxos.some(ownedUtxo => ownedUtxo.txid === utxo.txid)) .filter((x) => x.status.confirmed) .filter((x) => x.value > 10000) .filter(utxo => !utxo.inscriptionId) .sort((a, b) => b.value - a.value); + const hasRunes = await checkForRunes(utxosWithoutInscription); + const cardinalUtxos = await filterCardinalUtxos(availableCardinalUtxos); + const selectedCardinalAmount = utxosWithoutInscription.reduce((acc, utxo) => acc + utxo.value, 0); const inputs = [...utxosWithInscription, ...utxosWithoutInscription]; @@ -445,6 +477,10 @@ const Psbt = function (config) { metadata.outputs.push({ type: 'Cardinal' }); } + if (metadata.outputs[0] && hasRunes) { + metadata.outputs[0].type = metadata.outputs[0].type + `${hasRunes ? ' - Runes' : ''}`; + } + return { unsignedPsbtHex: psbt.toHex(), metadata