Liquid Transaction Example

Liquid transaction example in Java

The example below shows you how to create and run an example in Java that builds a Liquid transaction and signs it.

Create file named in libwally-core/src/swig_java/src/com/blockstream/test/

The contents of the file are shown below. Copy them into the file and save it.

package com.blockstream.test;
import com.blockstream.libwally.Wally;
public class liquid_tx_example {  
    public liquid_tx_example() { }
     * Example of stages in creating a transaction, using dummy hex values. 
     * Adds two inputs and one output.
     * Signs the inputs.
     * @System.out    the signed transaction hex
    public void build_and_sign_transaction() {
         * Create a transaction 
         * --------------------
        final String tx_in_hex = "0000000000000000000000000000000000000000000000000000000000000000"; 
        final byte[] tx_in_byte = Wally.hex_to_bytes(tx_in_hex);
        final String tx_out_hex = "0000000000000000000000000000000000000000000000000000000000000000"; 
        final byte[] tx_out_byte = Wally.hex_to_bytes(tx_out_hex);
        final String script_hex = "0000"; 
        final byte[] script_byte = Wally.hex_to_bytes(script_hex);
        final String witness_script_hex = "000000"; 
        final byte[] witness_script_byte = Wally.hex_to_bytes(witness_script_hex);
        final String nonce_hex = "0000000000000000000000000000000000000000000000000000000000000000"; 
        final byte[] nonce_byte = Wally.hex_to_bytes(nonce_hex);
        final String entropy_hex = "0000000000000000000000000000000000000000000000000000000000000000"; 
        final byte[] entropy_byte = Wally.hex_to_bytes(entropy_hex);
        final Object witness = Wally.tx_witness_stack_init(5L);
        Wally.tx_witness_stack_add(witness, witness_script_byte);
        // This is currently required by tx_elements_input_init - this is a bug that is being addressed.
        final Object pegin_witness = Wally.tx_witness_stack_init(5L);
        Wally.tx_witness_stack_add(pegin_witness, witness_script_byte);
        final long sequence = 0xffffffffL;
        // Version, locktime, inputs, outputs:
        final Object tx = Wally.tx_init(2, 0, 2, 1);
        final Object tx_input01 = Wally.tx_elements_input_init(tx_in_byte, 0L, sequence, script_byte, witness, nonce_byte, entropy_byte, null, null, null, null, pegin_witness);
        final Object tx_input02 = Wally.tx_elements_input_init(tx_in_byte, 2L, sequence, script_byte, witness, nonce_byte, entropy_byte, null, null, null, null, pegin_witness);
        final byte[] ct_value_byte = Wally.tx_confidential_value_from_satoshi(10000L, null);
        final Object tx_output = Wally.tx_elements_output_init(script_byte, null, ct_value_byte, null, null, null);
        Wally.tx_add_input(tx, tx_input01);
        Wally.tx_add_input(tx, tx_input02);
        Wally.tx_add_output(tx, tx_output);
        final byte[] input_witness01 = Wally.tx_input_get_witness(tx_input01, 0);
        final byte[] input_witness02 = Wally.tx_input_get_witness(tx_input02, 0);
        String tx_hex = "";
        tx_hex = Wally.tx_to_hex(tx, Wally.WALLY_TX_FLAG_USE_WITNESS);
        System.out.println("UNSIGNED TX HEX: " + tx_hex);
         * Sign the transaction 
         * --------------------
        byte[] sig_hash01 = Wally.tx_get_elements_signature_hash(tx, 0L, script_byte, ct_value_byte, Wally.WALLY_SIGHASH_ALL, Wally.WALLY_TX_FLAG_USE_WITNESS, null);
        byte[] sig_hash02 = Wally.tx_get_elements_signature_hash(tx, 1L, script_byte, ct_value_byte, Wally.WALLY_SIGHASH_ALL, Wally.WALLY_TX_FLAG_USE_WITNESS, null);
        // Example bip32 key
        final byte[] seed = h("000102030405060708090a0b0c0d0e0f"); 
        final Object seedKey = Wally.bip32_key_from_seed(seed, Wally.BIP32_VER_MAIN_PRIVATE, 0);
        final Object derivedKey = Wally.bip32_key_from_parent(seedKey, 0, Wally.BIP32_FLAG_KEY_PRIVATE);
        final byte[] private_key_bytes = Wally.bip32_key_get_priv_key(derivedKey);
        final byte[] public_key_bytes = Wally.bip32_key_get_pub_key(derivedKey);
        final byte[] signature01 = Wally.ec_sig_from_bytes(private_key_bytes, sig_hash01, Wally.EC_FLAG_ECDSA);        
        final byte[] signature02 = Wally.ec_sig_from_bytes(private_key_bytes, sig_hash02, Wally.EC_FLAG_ECDSA);        
        Wally.ec_sig_verify(public_key_bytes, sig_hash01, Wally.EC_FLAG_ECDSA, signature01);
        Wally.ec_sig_verify(public_key_bytes, sig_hash02, Wally.EC_FLAG_ECDSA, signature02);
        Wally.tx_set_input_script(tx, 0L, signature01);
        Wally.tx_set_input_script(tx, 1L, signature02);
        tx_hex = Wally.tx_to_hex(tx, Wally.WALLY_TX_FLAG_USE_WITNESS);
        System.out.println("SIGNED TX HEX: " + tx_hex);
        // Cleanup
    private String h(final byte[] bytes) { return Wally.hex_from_bytes(bytes); }
    private byte[] h(final String hex) { return Wally.hex_to_bytes(hex); }
    public static void main(final String[] args) {
        final liquid_tx_example example = new liquid_tx_example();

From the libwally-core/src directory, compile the code and then run it:

cd swig_java/src
javac com/blockstream/test/
cd ..
cd ..
LD_LIBRARY_PATH=.libs java -Djava.library.path=.libs -classpath swig_java/src com.blockstream.test.liquid_tx_example

For more details on signing see libwally-core/src/swig_java/src/com/blockstream/test/

Using other Libwally functions

You can find all the Libwally functions on

To use one, look up your chosen function on

To see the arguments you need to provide to use the function in Java:

  • Refer to the similar function (e.g. wally_tx_init_alloc is wally_tx_init) in
  • Note the arguments you must provide (some are not needed) and call the function from Java.

For example using tx_elements_input_init as an example:

Readthedocs lists 21 arguments whereas lists 12:

jarg1, jarg3, jarg4, jarg5, jarg7, jarg8, jarg10, jarg12, jarg14, jarg16, jarg18, jarg20.

Meaning that you do not need to provide the following readthedocs arguments in order to call the function from Java:

2 (txhash_len), 6, 9, 11, 13, 15, 17, 19, 21