Last active
May 16, 2025 03:05
-
-
Save losh11/e37b51d29491b9578d6cdb388eddb905 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
const selectUtxosForConversion = ( | |
utxos: Utxo[], | |
amount: number, | |
): Accumulator => { | |
return utxos.reduce<Accumulator>( | |
({selectedUtxos, totalAmountSat}, utxo) => { | |
if (totalAmountSat >= amount) { | |
return {selectedUtxos, totalAmountSat}; | |
} | |
return { | |
selectedUtxos: [...selectedUtxos, utxo], | |
totalAmountSat: totalAmountSat + Number(utxo.amountSat), | |
}; | |
}, | |
{selectedUtxos: [], totalAmountSat: 0}, | |
); | |
}; | |
export const sendConvertPsbtTransaction = async ( | |
amount: number, | |
destination: 'regular' | 'private', | |
) => { | |
try { | |
// new destination address | |
let type: number; | |
if (destination === 'private') { | |
type = 7; | |
} else { | |
type = 2; | |
} | |
const destinationAddress = await newLndAddress({type}); | |
// lookup utxos | |
const listUnspentResponse = await walletKitListUnspent({}); | |
if (!listUnspentResponse || !listUnspentResponse.utxos) { | |
throw new Error('Invalid response from ListUnspent'); | |
} | |
const {utxos} = listUnspentResponse; | |
console.log(listUnspentResponse.utxos); | |
// filter mweb and non mweb utxos, sort by largest | |
// coin selection will use first largest available | |
const mwebUtxos = utxos | |
.filter(utxo => utxo.addressType === 6) | |
.sort((a, b) => Number(b.amountSat) - Number(a.amountSat)); | |
const nonMwebUtxos = utxos | |
.filter(utxo => utxo.addressType !== 6) | |
.sort((a, b) => Number(b.amountSat) - Number(a.amountSat)); | |
const {selectedUtxos, totalAmountSat} = selectUtxosForConversion( | |
destination === 'regular' ? mwebUtxos : nonMwebUtxos, | |
amount, | |
); | |
// check if selected UTXOs satisfy the amount | |
if (totalAmountSat < amount) { | |
throw new Error('Insufficient funds in UTXOs'); | |
} | |
const outpointsArray = selectedUtxos | |
.map(utxo => utxo.outpoint) | |
.filter((outpoint): outpoint is OutPoint => outpoint !== undefined); | |
if (outpointsArray.length < 1 || outpointsArray === undefined) { | |
throw new Error('Outpoints empty!'); | |
} | |
const psbt = await walletKitFundPsbt({ | |
template: { | |
case: 'raw', | |
value: { | |
inputs: outpointsArray, | |
outputs: { | |
[destinationAddress.address]: BigInt(amount), | |
}, | |
}, | |
}, | |
fees: { | |
case: 'targetConf', | |
value: 3, | |
}, | |
}); | |
console.log(psbt); | |
const psbtBytes = objectToUint8Array(psbt.fundedPsbt); | |
const psbtString = new TextDecoder().decode(psbtBytes); | |
console.log('PSBT as string:', psbtString); | |
const psbtBase64 = bytesToBase64(psbtBytes); | |
console.log('PSBT as base64:', psbtBase64); | |
const signedPsbt = await walletKitFinalizePsbt({ | |
fundedPsbt: psbt.fundedPsbt, | |
}); | |
const txHex = Buffer.from(signedPsbt.rawFinalTx).toString('hex'); | |
const finalPsbt = Buffer.from(signedPsbt.signedPsbt).toString('base64'); | |
console.log('txhex'); | |
console.log(txHex); | |
console.log(finalPsbt); | |
console.log(destinationAddress.address); | |
// transaction.ts:270 Error: rpc error: code = Unknown desc = error finalizing PSBT: found UTXO tx cde375a5aaa7d6878e44d502e04af28f34af3836ebb139242ae7f8adbfea1662 but it doesn't match PSBT's input 7e237d4d7a8fdfe941f6caa8aaec5fffcb70ce3084e0f8d99a12a87aa0f37059 | |
// await publishTransaction(txHex); | |
} catch (error) { | |
// if walletKitFundPsbt is called, utxo is locked for 10mins | |
// in case of error, we want to free the utxo with ReleaseOutput | |
console.error(error); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment