const lwk = require('lwk_node');
async function runMultisigTest() {
try {
const network = lwk.Network.testnet();
const bip = lwk.Bip.bip87();
if (false) { const mnemonic_a = lwk.Mnemonic.fromRandom(12);
} const mnemonic_a = new lwk.Mnemonic("kind they sing appear whip boil divorce essence mask alien teach wire"); const signer_a = new lwk.Signer(mnemonic_a, network);
const xpub_a = signer_a.keyoriginXpub(bip);
if (false) { const mnemonic_b = lwk.Mnemonic.fromRandom(12);
} const mnemonic_b = new lwk.Mnemonic("vast response truth other mansion skull hold amused capital satoshi oxygen brass"); const signer_b = new lwk.Signer(mnemonic_b, network);
const xpub_b = signer_b.keyoriginXpub(bip);
if (false) { const mnemonic_c = lwk.Mnemonic.fromRandom(12);
} const mnemonic_c = new lwk.Mnemonic("fresh inner begin grid symbol congress wall outer mass enable coil repeat"); const signer_c = new lwk.Signer(mnemonic_c, network);
const xpub_c = signer_c.keyoriginXpub(bip);
if (false) { const slip77_rand_key = "<random-64-hex-chars>";
} const slip77_rand_key = "1111111111111111111111111111111111111111111111111111111111111111"; const desc_blinding_key = `slip77(${slip77_rand_key})`;
const threshold = 2;
const desc = `ct(${desc_blinding_key},elwsh(multi(${threshold},${xpub_a}/<0;1>/*,${xpub_b}/<0;1>/*,${xpub_c}/<0;1>/*)))`;
const wd = new lwk.WolletDescriptor(desc);
const wollet_c = new lwk.Wollet(network, wd);
const addr = wollet_c.address(null).address().toString();
const txs = wollet_c.transactions();
const balance = wollet_c.balance();
const url = "https://waterfalls.liquidwebwallet.org/liquidtestnet/api";
const client = new lwk.EsploraClient(network, url, true, 4, false);
const update = await client.fullScan(wollet_c);
if (update) {
wollet_c.applyUpdate(update);
}
const lbtc = network.policyAsset().toString();
const lbtc_balance = wollet_c.balance().entries().get(lbtc) || 0n;
if (lbtc_balance < 500n) {
console.log(`Balance is insufficient to make a transaction, send some tLBTC to ${addr}`);
return;
}
const sats = BigInt(1000);
if (false) { const address = new lwk.Address("<address>");
const asset = new lwk.AssetId("<asset>");
} const address = new lwk.Address("tlq1qq2g07nju42l0nlx0erqa3wsel2l8prnq96rlnhml262mcj7pe8w6ndvvyg237japt83z24m8gu4v3yfhaqvrqxydadc9scsmw"); const asset = network.policyAsset();
var builder = new lwk.TxBuilder(network)
builder = builder.addRecipient(address, sats, asset)
var pset = builder.finish(wollet_c)
pset = signer_c.sign(pset)
const wd_b = new lwk.WolletDescriptor(desc);
const wollet_b = new lwk.Wollet(network, wd_b);
const update_b = await client.fullScan(wollet_b);
if (update_b) {
wollet_b.applyUpdate(update_b);
}
const details = wollet_b.psetDetails(pset);
console.assert(details.balance().fee() < 100);
console.assert(details.fingerprintsHas().length === 1);
console.assert(details.fingerprintsHas().includes(signer_c.fingerprint()));
console.assert(details.fingerprintsMissing().length === 2);
console.assert(details.fingerprintsMissing().includes(signer_a.fingerprint()));
console.assert(details.fingerprintsMissing().includes(signer_b.fingerprint()));
console.assert(details.balance().recipients().length === 1);
const recipient = details.balance().recipients()[0];
console.assert(recipient.address().toString() === address.toString());
console.assert(recipient.asset().toString() === asset.toString());
console.assert(recipient.value() === sats);
pset = signer_b.sign(pset)
const details_b = wollet_b.psetDetails(pset);
console.assert(details_b.fingerprintsHas().length === 2);
pset = wollet_c.finalize(pset)
const tx = pset.extractTx();
const txid = await client.broadcastTx(tx);
console.log(txid.toString());
} catch (error) {
console.error("Basics test failed:", error);
throw error;
}
}
if (require.main === module) {
runMultisigTest();
}
module.exports = { runMultisigTest };