PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-ord/test
Просмотр файла: psbt.ts
import * as assert from 'assert';
import {
InscriptionTransactionOutputs,
createPsbtForSingleInscriptionPassingTransaction,
createPsbtFromOutputLayout,
findOutputLayoutForWalletUnspents,
WalletInputBuilder,
toArray,
} from '../src';
import { isSatPoint, OutputLayout, toParameters } from '../src';
import { bitgo, networks, testutil } from '@bitgo/utxo-lib';
function assertValidPsbt(
psbt: bitgo.UtxoPsbt,
s: bitgo.WalletUnspentSigner<bitgo.RootWalletKeys>,
expectedOutputs: number,
expectedFee: bigint
) {
psbt.signAllInputsHD(s.signer);
psbt.signAllInputsHD(s.cosigner);
psbt.finalizeAllInputs();
assert.strictEqual(psbt.txOutputs.length, expectedOutputs);
assert.strictEqual(psbt.getFee(), expectedFee);
}
describe('OutputLayout to PSBT conversion', function () {
const network = networks.bitcoin;
const walletKeys = testutil.getDefaultWalletKeys();
const signer = bitgo.WalletUnspentSigner.from(walletKeys, walletKeys.user, walletKeys.bitgo);
const inscriptionRecipient = bitgo.outputScripts.createOutputScript2of3(
walletKeys.deriveForChainAndIndex(0, 0).publicKeys,
'p2sh'
).scriptPubKey;
const walletUnspent = testutil.mockWalletUnspent(network, BigInt(20_000), { keys: walletKeys });
const inputBuilder: WalletInputBuilder = {
walletKeys,
signer: 'user',
cosigner: 'bitgo',
};
const outputs: InscriptionTransactionOutputs = {
changeOutputs: [
{ chain: 40, index: 0 },
{ chain: 40, index: 1 },
],
inscriptionRecipient,
};
function testInscriptionTxWithLayout(layout: OutputLayout, expectedOutputs: number) {
assertValidPsbt(
createPsbtFromOutputLayout(network, inputBuilder, [walletUnspent], outputs, layout),
signer,
expectedOutputs,
layout.feeOutput
);
}
it('can convert zero-padding layout to psbt', function () {
testInscriptionTxWithLayout(toParameters(BigInt(0), BigInt(19_800), BigInt(0), BigInt(200)), 1);
});
it('can convert start-padding layout to psbt', function () {
testInscriptionTxWithLayout(toParameters(BigInt(1_000), BigInt(18_800), BigInt(0), BigInt(200)), 2);
});
it('can convert end-padding layout to psbt', function () {
testInscriptionTxWithLayout(toParameters(BigInt(0), BigInt(18_800), BigInt(1_000), BigInt(200)), 2);
});
it('can convert double-padding layout to psbt', function () {
testInscriptionTxWithLayout(toParameters(BigInt(1_000), BigInt(17_800), BigInt(1_000), BigInt(200)), 3);
});
function testWithUnspents(
inscriptionUnspent: bitgo.WalletUnspent<bigint>,
supplementaryUnspents: bitgo.WalletUnspent<bigint>[],
expectedUnspentSelection: bitgo.WalletUnspent<bigint>[],
expectedResult: OutputLayout | undefined,
{ minimizeInputs }: { minimizeInputs?: boolean } = {}
) {
const values = [inscriptionUnspent, ...supplementaryUnspents].map((u) => u.value);
it(`finds layout for unspents [${values}, {minimizeInputs=${minimizeInputs}]`, function () {
const satPoint = inscriptionUnspent.id + ':0';
assert(isSatPoint(satPoint));
const f = () =>
createPsbtForSingleInscriptionPassingTransaction(
network,
inputBuilder,
[inscriptionUnspent],
satPoint,
outputs,
{
feeRateSatKB: 1000,
},
{
supplementaryUnspents,
minimizeInputs,
}
);
if (expectedResult === undefined) {
assert.throws(f);
return;
}
const psbt1 = f();
assert.deepStrictEqual(
psbt1.txInputs.map((i) => bitgo.formatOutputId(bitgo.getOutputIdForInput(i))),
expectedUnspentSelection.map((u) => u.id)
);
const result = findOutputLayoutForWalletUnspents(expectedUnspentSelection, satPoint, outputs, {
feeRateSatKB: 1000,
});
assert(result);
assert.deepStrictEqual(result.layout, expectedResult);
const expectedOutputs = toArray(expectedResult).filter((v) => v !== BigInt(0)).length - 1;
const psbt = createPsbtFromOutputLayout(network, inputBuilder, expectedUnspentSelection, outputs, result.layout);
assertValidPsbt(psbt, signer, expectedOutputs, expectedResult.feeOutput);
assertValidPsbt(psbt1, signer, expectedOutputs, expectedResult.feeOutput);
assert.strictEqual(
psbt.extractTransaction().toBuffer().toString('hex'),
psbt1.extractTransaction().toBuffer().toString('hex')
);
});
}
let nUnspent = 0;
function unspent(v: number): bitgo.WalletUnspent<bigint> {
return testutil.mockWalletUnspent(network, BigInt(v), { vout: nUnspent++ });
}
const u1k = unspent(1_000);
const u5k1 = unspent(5_000);
const u5k2 = unspent(5_000);
const u10k = unspent(10_000);
const u20k = unspent(20_000);
const u100m1 = unspent(100_000_000);
const u100m2 = unspent(100_000_000);
testWithUnspents(u20k, [], [u20k], {
firstChangeOutput: BigInt(0),
inscriptionOutput: BigInt(19648),
secondChangeOutput: BigInt(0),
feeOutput: BigInt(352),
});
testWithUnspents(u1k, [], [u1k], undefined);
testWithUnspents(
u1k,
[u100m1, u100m2],
[u1k, u100m1, u100m2],
{
firstChangeOutput: BigInt(0),
inscriptionOutput: BigInt(10_000),
secondChangeOutput: BigInt(199990009),
feeOutput: BigInt(991),
},
{ minimizeInputs: false }
);
testWithUnspents(u1k, [u5k1, u5k2, u10k], [u1k, u10k], {
firstChangeOutput: BigInt(0),
inscriptionOutput: BigInt(10_350),
secondChangeOutput: BigInt(0),
feeOutput: BigInt(650),
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!