import { expect, assert } from 'chai';
import { generate_block_headers } from './utils';
import * as ergo from "..";
let ergo_wasm;
beforeEach(async () => {
ergo_wasm = await ergo;
});
it('TxBuilder test', async () => {
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = ergo_wasm.ErgoBoxes.from_boxes_json([
{
"boxId": "e56847ed19b3dc6b72828fcfb992fdf7310828cf291221269b7ffc72fd66706e",
"value": 67500000000,
"ergoTree": "100204a00b08cd021dde34603426402615658f1d970cfa7c7bd92ac81a8b16eeebff264d59ce4604ea02d192a39a8cc7a70173007301",
"assets": [],
"creationHeight": 284761,
"additionalRegisters": {},
"transactionId": "9148408c04c2e38a6402a7950d6157730fa7d49e9ab3b9cadec481d7769918e9",
"index": 1
}
]);
const contract = ergo_wasm.Contract.pay_to_address(recipient);
const outbox_value = ergo_wasm.BoxValue.SAFE_USER_MIN();
const outbox = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0).build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const data_inputs = new ergo_wasm.DataInputs();
const box_selector = new ergo_wasm.SimpleBoxSelector();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
const box_selection = box_selector.select(unspent_boxes, target_balance, new ergo_wasm.Tokens());
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
tx_builder.set_data_inputs(data_inputs);
const tx = tx_builder.build();
assert(tx != null);
});
it('sign transaction', async () => {
const sk = ergo_wasm.SecretKey.random_dlog();
// simulate existing box guarded by the sk key
const input_contract = ergo_wasm.Contract.pay_to_address(sk.get_address());
const input_box = new ergo_wasm.ErgoBox(ergo_wasm.BoxValue.from_i64(ergo_wasm.I64.from_str('1000000000')), 0, input_contract, ergo_wasm.TxId.zero(), 0, new ergo_wasm.Tokens());
// create a transaction that spends the "simulated" box
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = new ergo_wasm.ErgoBoxes(input_box);
const contract = ergo_wasm.Contract.pay_to_address(recipient);
const outbox_value = ergo_wasm.BoxValue.SAFE_USER_MIN();
const outbox = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0).build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const box_selector = new ergo_wasm.SimpleBoxSelector();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
const box_selection = box_selector.select(unspent_boxes, target_balance, new ergo_wasm.Tokens());
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
const tx = tx_builder.build();
// smoke test for to_js_eip12
assert(tx.to_js_eip12() != null);
const tx_data_inputs = ergo_wasm.ErgoBoxes.from_boxes_json([]);
const block_headers = generate_block_headers();
const pre_header = ergo_wasm.PreHeader.from_block_header(block_headers.get(0));
const ctx = new ergo_wasm.ErgoStateContext(pre_header, block_headers, ergo_wasm.Parameters.default_parameters());
const sks = new ergo_wasm.SecretKeys();
sks.add(sk);
const wallet = ergo_wasm.Wallet.from_secrets(sks);
const signed_tx = wallet.sign_transaction(ctx, tx, unspent_boxes, tx_data_inputs);
assert(signed_tx != null);
// smoke test for to_js_eip12
assert(signed_tx.to_js_eip12() != null);
});
it('TxBuilder mint token test', async () => {
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = ergo_wasm.ErgoBoxes.from_boxes_json([
{
"boxId": "e56847ed19b3dc6b72828fcfb992fdf7310828cf291221269b7ffc72fd66706e",
"value": 67500000000,
"ergoTree": "100204a00b08cd021dde34603426402615658f1d970cfa7c7bd92ac81a8b16eeebff264d59ce4604ea02d192a39a8cc7a70173007301",
"assets": [],
"creationHeight": 284761,
"additionalRegisters": {},
"transactionId": "9148408c04c2e38a6402a7950d6157730fa7d49e9ab3b9cadec481d7769918e9",
"index": 1
}
]);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const outbox_value = ergo_wasm.BoxValue.SAFE_USER_MIN();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
const box_selector = new ergo_wasm.SimpleBoxSelector();
const box_selection = box_selector.select(unspent_boxes, target_balance, new ergo_wasm.Tokens());
const contract = ergo_wasm.Contract.pay_to_address(recipient);
const token_id = ergo_wasm.TokenId.from_box_id(box_selection.boxes().get(0).box_id());
const box_builder = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0);
const token = new ergo_wasm.Token(token_id, ergo_wasm.TokenAmount.from_i64(ergo_wasm.I64.from_str('1')));
box_builder.mint_token(token, "TKN", "token desc", 2)
const outbox = box_builder.build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const data_inputs = new ergo_wasm.DataInputs();
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
tx_builder.set_data_inputs(data_inputs);
const tx = tx_builder.build();
assert(tx != null);
});
it('TxBuilder burn token test', async () => {
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = ergo_wasm.ErgoBoxes.from_boxes_json([
{
"boxId": "0cf7b9e71961cc473242de389c8e594a4e5d630ddd2e4e590083fb0afb386341",
"value": 11491500000,
"ergoTree": "100f040005c801056404000e2019719268d230fd9093e4db0e2e42a07883ffe976e77c7419efc1bb218a05d4ba04000500043c040204c096b10204020101040205c096b1020400d805d601b2a5730000d602e4c6a70405d6039c9d720273017302d604b5db6501fed9010463ededed93e4c67204050ec5a7938cb2db6308720473030001730492e4c672040605997202720390e4c6720406059a72027203d605b17204ea02d1edededededed93cbc27201e4c6a7060e917205730593db63087201db6308a793e4c6720104059db072047306d9010641639a8c720601e4c68c72060206057e72050593e4c6720105049ae4c6a70504730792c1720199c1a77e9c9a720573087309058cb072048602730a730bd901063c400163d802d6088c720601d6098c72080186029a7209730ceded8c72080293c2b2a5720900d0cde4c68c720602040792c1b2a5720900730d02b2ad7204d9010663cde4c672060407730e00",
"assets": [
{
"tokenId": "19475d9a78377ff0f36e9826cec439727bea522f6ffa3bda32e20d2f8b3103ac",
"amount": 1
}
],
"creationHeight": 348198,
"additionalRegisters": {
"R4": "059acd9109",
"R5": "04f2c02a",
"R6": "0e20277c78751ff6f68d4dcd082eeea9506324911a875b6b9cd4d177d4fcab061327"
},
"transactionId": "5ed0e572a8c097b053965519a696f413f7be02754345e8ed650377e29a6dedb3",
"index": 0
}
]);
const token_id = ergo_wasm.TokenId.from_str("19475d9a78377ff0f36e9826cec439727bea522f6ffa3bda32e20d2f8b3103ac");
const token = new ergo_wasm.Token(token_id, ergo_wasm.TokenAmount.from_i64(ergo_wasm.I64.from_str('1')));
const box_selector = new ergo_wasm.SimpleBoxSelector();
let tokens = new ergo_wasm.Tokens();
tokens.add(token);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const outbox_value = ergo_wasm.BoxValue.SAFE_USER_MIN();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
// select tokens from inputs
const box_selection = box_selector.select(unspent_boxes, target_balance, tokens);
const contract = ergo_wasm.Contract.pay_to_address(recipient);
// but don't put selected tokens in the output box (burn them)
const box_builder = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0);
const outbox = box_builder.build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const data_inputs = new ergo_wasm.DataInputs();
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
tx_builder.set_data_inputs(data_inputs);
tx_builder.set_token_burn_permit(tokens);
const tx = tx_builder.build();
assert(tx != null);
});
it('use signed tx outputs as inputs in a new tx', async () => {
const sk = ergo_wasm.SecretKey.random_dlog();
// simulate existing box guarded by the sk key
const input_contract = ergo_wasm.Contract.pay_to_address(sk.get_address());
const input_box = new ergo_wasm.ErgoBox(ergo_wasm.BoxValue.from_i64(ergo_wasm.I64.from_str('100000000000')), 0, input_contract, ergo_wasm.TxId.zero(), 0, new ergo_wasm.Tokens());
// create a transaction that spends the "simulated" box
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = new ergo_wasm.ErgoBoxes(input_box);
const contract = ergo_wasm.Contract.pay_to_address(recipient);
const outbox_value = ergo_wasm.BoxValue.from_i64(ergo_wasm.I64.from_str('10000000000'));
const outbox = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0).build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const box_selector = new ergo_wasm.SimpleBoxSelector();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
const box_selection = box_selector.select(unspent_boxes, target_balance, new ergo_wasm.Tokens());
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
const tx = tx_builder.build();
const tx_data_inputs = ergo_wasm.ErgoBoxes.from_boxes_json([]);
const block_headers = generate_block_headers();
const pre_header = ergo_wasm.PreHeader.from_block_header(block_headers.get(0));
const ctx = new ergo_wasm.ErgoStateContext(pre_header, block_headers, ergo_wasm.Parameters.default_parameters());
const sks = new ergo_wasm.SecretKeys();
sks.add(sk);
const wallet = ergo_wasm.Wallet.from_secrets(sks);
const signed_tx = wallet.sign_transaction(ctx, tx, unspent_boxes, tx_data_inputs);
assert(signed_tx != null);
// new tx
const new_outbox_value = ergo_wasm.BoxValue.from_i64(ergo_wasm.I64.from_str('1000000000'));
const new_target_balance = ergo_wasm.BoxValue.from_i64(new_outbox_value.as_i64().checked_add(fee.as_i64()));
const new_box_selection = box_selector.select(signed_tx.outputs(), new_target_balance, new ergo_wasm.Tokens());
const new_outbox = new ergo_wasm.ErgoBoxCandidateBuilder(new_outbox_value, contract, 0).build();
const new_tx_outputs = new ergo_wasm.ErgoBoxCandidates(new_outbox);
const new_tx_builder = ergo_wasm.TxBuilder.new(new_box_selection, new_tx_outputs, 0, fee, change_address);
const new_tx = new_tx_builder.build();
assert(new_tx != null);
});
it('Transaction::from_unsigned_tx test', async () => {
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = ergo_wasm.ErgoBoxes.from_boxes_json([
{
"boxId": "e56847ed19b3dc6b72828fcfb992fdf7310828cf291221269b7ffc72fd66706e",
"value": 67500000000,
"ergoTree": "100204a00b08cd021dde34603426402615658f1d970cfa7c7bd92ac81a8b16eeebff264d59ce4604ea02d192a39a8cc7a70173007301",
"assets": [],
"creationHeight": 284761,
"additionalRegisters": {},
"transactionId": "9148408c04c2e38a6402a7950d6157730fa7d49e9ab3b9cadec481d7769918e9",
"index": 1
}
]);
const contract = ergo_wasm.Contract.pay_to_address(recipient);
const outbox_value = ergo_wasm.BoxValue.SAFE_USER_MIN();
const outbox = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0).build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const data_inputs = new ergo_wasm.DataInputs();
const box_selector = new ergo_wasm.SimpleBoxSelector();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
const box_selection = box_selector.select(unspent_boxes, target_balance, new ergo_wasm.Tokens());
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
tx_builder.set_data_inputs(data_inputs);
const tx = tx_builder.build();
assert(tx != null);
const proof = new Uint8Array([1, 1, 2, 255]);
const signed_tx = ergo_wasm.Transaction.from_unsigned_tx(tx, [proof]);
assert(signed_tx != null);
assert(signed_tx.inputs().get(0).spending_proof().proof().toString() == proof.toString());
});
it('signing multi signature transaction', async () => {
const alice_secret = ergo_wasm.SecretKey.dlog_from_bytes(Uint8Array.from(Buffer.from("e726ad60a073a49f7851f4d11a83de6c9c7f99e17314fcce560f00a51a8a3d18", "hex")));
const bob_secret = ergo_wasm.SecretKey.dlog_from_bytes(Uint8Array.from(Buffer.from("9e6616b4e44818d21b8dfdd5ea87eb822480e7856ab910d00f5834dc64db79b3", "hex")));
const alice_pk_bytes = Uint8Array.from(Buffer.from("cd03c8e1527efae4be9868cea6767157fcccac66489842738efed0a302e4f81710d0", "hex"));
const bob_pk_bytes = Uint8Array.from(Buffer.from("cd0247eb7cf009addc51892932c05c2a237c86c92f4982307a1af240a08c88270348", "hex"));
// Pay 2 Script address of a multi_sig contract with contract { alicePK && bobPK }
const multi_sig_address = ergo_wasm.Address.from_testnet_str('JryiCXrc7x5D8AhS9DYX1TDzW5C5mT6QyTMQaptF76EQkM15cetxtYKq3u6LymLZLVCyjtgbTKFcfuuX9LLi49Ec5m2p6cwsg5NyEsCQ7na83yEPN');
const input_contract = ergo_wasm.Contract.pay_to_address(multi_sig_address);
const input_box = new ergo_wasm.ErgoBox(ergo_wasm.BoxValue.from_i64(ergo_wasm.I64.from_str('1000000000')), 0, input_contract, ergo_wasm.TxId.zero(), 0, new ergo_wasm.Tokens());
// create a transaction that spends the "simulated" box
const recipient = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const unspent_boxes = new ergo_wasm.ErgoBoxes(input_box);
const contract = ergo_wasm.Contract.pay_to_address(recipient);
const outbox_value = ergo_wasm.BoxValue.SAFE_USER_MIN();
const outbox = new ergo_wasm.ErgoBoxCandidateBuilder(outbox_value, contract, 0).build();
const tx_outputs = new ergo_wasm.ErgoBoxCandidates(outbox);
const fee = ergo_wasm.TxBuilder.SUGGESTED_TX_FEE();
const change_address = ergo_wasm.Address.from_testnet_str('3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN');
const box_selector = new ergo_wasm.SimpleBoxSelector();
const target_balance = ergo_wasm.BoxValue.from_i64(outbox_value.as_i64().checked_add(fee.as_i64()));
const box_selection = box_selector.select(unspent_boxes, target_balance, new ergo_wasm.Tokens());
const tx_builder = ergo_wasm.TxBuilder.new(box_selection, tx_outputs, 0, fee, change_address);
const tx = tx_builder.build();
const tx_data_inputs = ergo_wasm.ErgoBoxes.from_boxes_json([]);
const block_headers = generate_block_headers();
const pre_header = ergo_wasm.PreHeader.from_block_header(block_headers.get(0));
const ctx = new ergo_wasm.ErgoStateContext(pre_header, block_headers, ergo_wasm.Parameters.default_parameters());
const sks_alice = new ergo_wasm.SecretKeys();
sks_alice.add(alice_secret);
const wallet_alice = ergo_wasm.Wallet.from_secrets(sks_alice);
const sks_bob = new ergo_wasm.SecretKeys();
sks_bob.add(bob_secret);
const wallet_bob = ergo_wasm.Wallet.from_secrets(sks_bob);
const bob_hints = wallet_bob.generate_commitments(ctx, tx, unspent_boxes, tx_data_inputs).all_hints_for_input(0);
const bob_known = bob_hints.get(0);
const bob_own = bob_hints.get(1);
let hints_bag = ergo_wasm.HintsBag.empty();
hints_bag.add_commitment(bob_known);
const alice_tx_hints_bag = ergo_wasm.TransactionHintsBag.empty()
alice_tx_hints_bag.add_hints_for_input(0, hints_bag);
const partial_signed = wallet_alice.sign_transaction_multi(ctx, tx, unspent_boxes, tx_data_inputs, alice_tx_hints_bag);
const real_propositions = new ergo_wasm.Propositions;
const simulated_proposition = new ergo_wasm.Propositions;
real_propositions.add_proposition_from_byte(alice_pk_bytes);
const bob_hints_bag = ergo_wasm.extract_hints(partial_signed, ctx, unspent_boxes, tx_data_inputs, real_propositions, simulated_proposition).all_hints_for_input(0);
bob_hints_bag.add_commitment(bob_own);
const bob_tx_hints_bag = ergo_wasm.TransactionHintsBag.empty();
bob_tx_hints_bag.add_hints_for_input(0, bob_hints_bag);
const signed_tx = wallet_bob.sign_transaction_multi(ctx, tx, unspent_boxes, tx_data_inputs, bob_tx_hints_bag);
assert(signed_tx != null);
});
it('signing multi signature transaction (issue 597)', async () => {
const secrets = [
"00eda6c0e9fc808d4cf050fc4e98705372b9f0786a6b63aa4013d1a20539b104",
"cc2e48e5e53059e0d68866eff97a6037cb39945ea9f09f40fcec82d12cd8cb8b",
"c97250f41cfa8d545c2f8d75b2ee24002b5feec32340c2bb81fa4e2d4c7527d3",
"53ceef0ece83401cf5cd853fd0c1a9bbfab750d76f278b3187f1a14768d6e9c4",
]
const reduced = ergo_wasm.ReducedTransaction.sigma_parse_bytes(Uint8Array.from(Buffer.from("ce04022f4cd0df4db787875b3a071e098b72ba4923bd2460e08184b34359563febe04700005e8269c8e2b975a43dc6e74a9c5b10b273313c6d32c1dd40c171fc0a8852ca0100000001a6ac381e6fa99929fd1477b3ba9499790a775e91d4c14c5aa86e9a118dfac8530480ade204100504000400040004000402d804d601b2a5730000d602e4c6a7041ad603e4c6a70510d604ad7202d901040ecdee7204ea02d19683020193c27201c2a7938cb2db63087201730100018cb2db6308a773020001eb02ea02d19683020193e4c67201041a720293e4c672010510720398b27203730300720498b272037304007204d18b0f010001021a04210302e57ca7ebf8cfa1802d4bc79a455008307a936b4f50f0629d9bef484fdd5189210399f5724bbc4d08c6e146d61449c05a3e0546868b1d4f83411f325187d5ca4f8521024e06e6c6073e13a03fa4629882a69108cd60e0a9fbb2e0fcc898ce68a7051b6621027a069cc972fc7816539a316ba1cfc0164656d63dd1873ee407670b0e8195f3bd100206088094ebdc030008cd0314368e16c9c99c5a6e20dda917aeb826b3a908becff543b3a36b38e6b3355ff5d18b0f0000c0843d1005040004000e36100204a00b08cd0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ea02d192a39a8cc7a701730073011001020402d19683030193a38cc7b2a57300000193c2b2a57301007473027303830108cdeeac93b1a57304d18b0f0000c0af87c3210008cd0314368e16c9c99c5a6e20dda917aeb826b3a908becff543b3a36b38e6b3355ff5d18b0f00009702980304cd0302e57ca7ebf8cfa1802d4bc79a455008307a936b4f50f0629d9bef484fdd5189cd0399f5724bbc4d08c6e146d61449c05a3e0546868b1d4f83411f325187d5ca4f85cd024e06e6c6073e13a03fa4629882a69108cd60e0a9fbb2e0fcc898ce68a7051b66cd027a069cc972fc7816539a316ba1cfc0164656d63dd1873ee407670b0e8195f3bd9604cd0302e57ca7ebf8cfa1802d4bc79a455008307a936b4f50f0629d9bef484fdd5189cd0399f5724bbc4d08c6e146d61449c05a3e0546868b1d4f83411f325187d5ca4f85cd024e06e6c6073e13a03fa4629882a69108cd60e0a9fbb2e0fcc898ce68a7051b66cd027a069cc972fc7816539a316ba1cfc0164656d63dd1873ee407670b0e8195f3bdf39b03d3cb9e02d073", "hex")))
assert(reduced != null);
const sks = new ergo_wasm.SecretKeys()
secrets.forEach(item => sks.add(ergo_wasm.SecretKey.dlog_from_bytes(Uint8Array.from(Buffer.from(item, "hex")))))
assert(sks != null);
const prover = ergo_wasm.Wallet.from_secrets(sks)
assert(prover != null);
const signed = prover.sign_reduced_transaction(reduced)
// console.log(JSON.stringify(signed.to_json()))
});