#ifndef LIBWALLY_CORE_WALLY_HPP
#define LIBWALLY_CORE_WALLY_HPP
#pragma once

#include <type_traits>
#include <string>
#include <wally_address.h>
#include <wally_bip32.h>
#include <wally_bip38.h>
#include <wally_bip39.h>
#include <wally_core.h>
#include <wally_crypto.h>
#include <wally_psbt.h>
#include <wally_script.h>
#include <wally_symmetric.h>
#include <wally_transaction.h>

/* These wrappers allow passing containers such as std::vector, std::array,
 * std::string and custom classes as input/output buffers to wally functions.
 */
namespace wally {

namespace detail {
template <class P> inline auto get_p(const P& p, std::false_type, std::true_type) {
    return &p[0];
}
template <class P> inline auto get_p(const P& p, std::true_type, std::false_type) {
    return p;
}
template <class P> inline auto get_p(const P& p, std::false_type, std::false_type) {
    return p.get();
}
template <class P> inline auto get_p(const P& p) {
    return get_p(p, std::is_pointer<P>{}, std::is_array<P>{});
}
template <> inline auto get_p(const std::string& p) {
    return p.c_str();
}
template <> inline auto get_p(const std::nullptr_t& p) {
    return p;
}
} /* namespace detail */

/* BEGIN AUTOGENERATED */
inline int bip32_key_free(const struct ext_key* hdkey) {
    int ret = ::bip32_key_free(hdkey);
    return ret;
}

template <class BASE58>
inline int bip32_key_from_base58(const BASE58& base58, struct ext_key* output) {
    int ret = ::bip32_key_from_base58(detail::get_p(base58), output);
    return ret;
}

template <class BASE58>
inline int bip32_key_from_base58_alloc(const BASE58& base58, struct ext_key** output) {
    int ret = ::bip32_key_from_base58_alloc(detail::get_p(base58), output);
    return ret;
}

template <class HDKEY>
inline int bip32_key_from_parent(const HDKEY& hdkey, uint32_t child_num, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_parent(detail::get_p(hdkey), child_num, flags, output);
    return ret;
}

template <class HDKEY>
inline int bip32_key_from_parent_alloc(const HDKEY& hdkey, uint32_t child_num, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_parent_alloc(detail::get_p(hdkey), child_num, flags, output);
    return ret;
}

template <class HDKEY, class CHILD_PATH>
inline int bip32_key_from_parent_path(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_parent_path(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return ret;
}

template <class HDKEY, class CHILD_PATH>
inline int bip32_key_from_parent_path_alloc(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_parent_path_alloc(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return ret;
}

template <class BYTES>
inline int bip32_key_from_seed(const BYTES& bytes, uint32_t version, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_from_seed(bytes.data(), bytes.size(), version, flags, output);
    return ret;
}

template <class BYTES>
inline int bip32_key_from_seed_alloc(const BYTES& bytes, uint32_t version, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_from_seed_alloc(bytes.data(), bytes.size(), version, flags, output);
    return ret;
}

template <class HDKEY, class BYTES_OUT>
inline int bip32_key_get_fingerprint(const HDKEY& hdkey, BYTES_OUT& bytes_out) {
    int ret = ::bip32_key_get_fingerprint(detail::get_p(hdkey), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class CHAIN_CODE, class PUB_KEY, class PRIV_KEY, class HASH160, class PARENT160>
inline int bip32_key_init(uint32_t version, uint32_t depth, uint32_t child_num, const CHAIN_CODE& chain_code, const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const HASH160& hash160, const PARENT160& parent160, struct ext_key* output) {
    int ret = ::bip32_key_init(version, depth, child_num, chain_code.data(), chain_code.size(), pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), hash160.data(), hash160.size(), parent160.data(), parent160.size(), output);
    return ret;
}

template <class CHAIN_CODE, class PUB_KEY, class PRIV_KEY, class HASH160, class PARENT160>
inline int bip32_key_init_alloc(uint32_t version, uint32_t depth, uint32_t child_num, const CHAIN_CODE& chain_code, const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const HASH160& hash160, const PARENT160& parent160, struct ext_key** output) {
    int ret = ::bip32_key_init_alloc(version, depth, child_num, chain_code.data(), chain_code.size(), pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), hash160.data(), hash160.size(), parent160.data(), parent160.size(), output);
    return ret;
}

template <class HDKEY, class BYTES_OUT>
inline int bip32_key_serialize(const HDKEY& hdkey, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip32_key_serialize(detail::get_p(hdkey), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

inline int bip32_key_strip_private_key(struct ext_key* hdkey) {
    int ret = ::bip32_key_strip_private_key(hdkey);
    return ret;
}

template <class HDKEY>
inline int bip32_key_to_base58(const HDKEY& hdkey, uint32_t flags, char** output) {
    int ret = ::bip32_key_to_base58(detail::get_p(hdkey), flags, output);
    return ret;
}

template <class BYTES>
inline int bip32_key_unserialize(const BYTES& bytes, struct ext_key* output) {
    int ret = ::bip32_key_unserialize(bytes.data(), bytes.size(), output);
    return ret;
}

template <class BYTES>
inline int bip32_key_unserialize_alloc(const BYTES& bytes, struct ext_key** output) {
    int ret = ::bip32_key_unserialize_alloc(bytes.data(), bytes.size(), output);
    return ret;
}

template <class BYTES, class PASS>
inline int bip38_from_private_key(const BYTES& bytes, const PASS& pass, uint32_t flags, char** output) {
    int ret = ::bip38_from_private_key(bytes.data(), bytes.size(), pass.data(), pass.size(), flags, output);
    return ret;
}

template <class BIP38>
inline int bip38_get_flags(const BIP38& bip38, size_t* written) {
    int ret = ::bip38_get_flags(detail::get_p(bip38), written);
    return ret;
}

template <class BYTES, class PASS, class BYTES_OUT>
inline int bip38_raw_from_private_key(const BYTES& bytes, const PASS& pass, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip38_raw_from_private_key(bytes.data(), bytes.size(), pass.data(), pass.size(), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES>
inline int bip38_raw_get_flags(const BYTES& bytes, size_t* written = 0) {
    size_t n;
    int ret = ::bip38_raw_get_flags(bytes.data(), bytes.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class PASS, class BYTES_OUT>
inline int bip38_raw_to_private_key(const BYTES& bytes, const PASS& pass, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip38_raw_to_private_key(bytes.data(), bytes.size(), pass.data(), pass.size(), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BIP38, class PASS, class BYTES_OUT>
inline int bip38_to_private_key(const BIP38& bip38, const PASS& pass, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::bip38_to_private_key(detail::get_p(bip38), pass.data(), pass.size(), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

inline int bip39_get_languages(char** output) {
    int ret = ::bip39_get_languages(output);
    return ret;
}

template <class W>
inline int bip39_get_word(const W& w, size_t index, char** output) {
    int ret = ::bip39_get_word(detail::get_p(w), index, output);
    return ret;
}

template <class LANG>
inline int bip39_get_wordlist(const LANG& lang, struct words** output) {
    int ret = ::bip39_get_wordlist(detail::get_p(lang), output);
    return ret;
}

template <class W, class BYTES>
inline int bip39_mnemonic_from_bytes(const W& w, const BYTES& bytes, char** output) {
    int ret = ::bip39_mnemonic_from_bytes(detail::get_p(w), bytes.data(), bytes.size(), output);
    return ret;
}

template <class W, class MNEMONIC, class BYTES_OUT>
inline int bip39_mnemonic_to_bytes(const W& w, const MNEMONIC& mnemonic, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::bip39_mnemonic_to_bytes(detail::get_p(w), detail::get_p(mnemonic), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class MNEMONIC, class PASSPHRASE, class BYTES_OUT>
inline int bip39_mnemonic_to_seed(const MNEMONIC& mnemonic, const PASSPHRASE& passphrase, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::bip39_mnemonic_to_seed(detail::get_p(mnemonic), detail::get_p(passphrase), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class W>
inline int bip39_mnemonic_validate(const W& w, const char* mnemonic) {
    int ret = ::bip39_mnemonic_validate(detail::get_p(w), mnemonic);
    return ret;
}

template <class BYTES, class ADDR_FAMILY>
inline int addr_segwit_from_bytes(const BYTES& bytes, const ADDR_FAMILY& addr_family, uint32_t flags, char** output) {
    int ret = ::wally_addr_segwit_from_bytes(bytes.data(), bytes.size(), detail::get_p(addr_family), flags, output);
    return ret;
}

template <class ADDR, class ADDR_FAMILY, class BYTES_OUT>
inline int addr_segwit_to_bytes(const ADDR& addr, const ADDR_FAMILY& addr_family, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_addr_segwit_to_bytes(detail::get_p(addr), detail::get_p(addr_family), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class ADDR, class BYTES_OUT>
inline int address_to_scriptpubkey(const ADDR& addr, uint32_t network, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_address_to_scriptpubkey(detail::get_p(addr), network, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class KEY, class BYTES, class BYTES_OUT>
inline int aes(const KEY& key, const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_aes(key.data(), key.size(), bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class KEY, class IV, class BYTES, class BYTES_OUT>
inline int aes_cbc(const KEY& key, const IV& iv, const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_aes_cbc(key.data(), key.size(), iv.data(), iv.size(), bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES>
inline int base58_from_bytes(const BYTES& bytes, uint32_t flags, char** output) {
    int ret = ::wally_base58_from_bytes(bytes.data(), bytes.size(), flags, output);
    return ret;
}

template <class STR_IN>
inline int base58_get_length(const STR_IN& str_in, size_t* written) {
    int ret = ::wally_base58_get_length(detail::get_p(str_in), written);
    return ret;
}

template <class STR_IN, class BYTES_OUT>
inline int base58_to_bytes(const STR_IN& str_in, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_base58_to_bytes(detail::get_p(str_in), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class HDKEY, class ADDR_FAMILY>
inline int bip32_key_to_addr_segwit(const HDKEY& hdkey, const ADDR_FAMILY& addr_family, uint32_t flags, char** output) {
    int ret = ::wally_bip32_key_to_addr_segwit(detail::get_p(hdkey), detail::get_p(addr_family), flags, output);
    return ret;
}

template <class HDKEY>
inline int bip32_key_to_address(const HDKEY& hdkey, uint32_t flags, uint32_t version, char** output) {
    int ret = ::wally_bip32_key_to_address(detail::get_p(hdkey), flags, version, output);
    return ret;
}

template <class BYTES>
inline int bzero(const BYTES& bytes, size_t bytes_len) {
    int ret = ::wally_bzero(detail::get_p(bytes), bytes_len);
    return ret;
}

inline int cleanup(uint32_t flags) {
    int ret = ::wally_cleanup(flags);
    return ret;
}

template <class PRIV_KEY>
inline int ec_private_key_verify(const PRIV_KEY& priv_key) {
    int ret = ::wally_ec_private_key_verify(priv_key.data(), priv_key.size());
    return ret;
}

template <class PUB_KEY, class BYTES_OUT>
inline int ec_public_key_decompress(const PUB_KEY& pub_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_decompress(pub_key.data(), pub_key.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class PRIV_KEY, class BYTES_OUT>
inline int ec_public_key_from_private_key(const PRIV_KEY& priv_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_from_private_key(priv_key.data(), priv_key.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class PUB_KEY, class BYTES_OUT>
inline int ec_public_key_negate(const PUB_KEY& pub_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_public_key_negate(pub_key.data(), pub_key.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class PUB_KEY>
inline int ec_public_key_verify(const PUB_KEY& pub_key) {
    int ret = ::wally_ec_public_key_verify(pub_key.data(), pub_key.size());
    return ret;
}

template <class PRIV_KEY, class BYTES, class BYTES_OUT>
inline int ec_sig_from_bytes(const PRIV_KEY& priv_key, const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_from_bytes(priv_key.data(), priv_key.size(), bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int ec_sig_from_der(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_from_der(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class SIG, class BYTES_OUT>
inline int ec_sig_normalize(const SIG& sig, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_normalize(sig.data(), sig.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class SIG, class BYTES_OUT>
inline int ec_sig_to_der(const SIG& sig, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_ec_sig_to_der(sig.data(), sig.size(), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class SIG, class BYTES_OUT>
inline int ec_sig_to_public_key(const BYTES& bytes, const SIG& sig, BYTES_OUT& bytes_out) {
    int ret = ::wally_ec_sig_to_public_key(bytes.data(), bytes.size(), sig.data(), sig.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class PUB_KEY, class BYTES, class SIG>
inline int ec_sig_verify(const PUB_KEY& pub_key, const BYTES& bytes, uint32_t flags, const SIG& sig) {
    int ret = ::wally_ec_sig_verify(pub_key.data(), pub_key.size(), bytes.data(), bytes.size(), flags, sig.data(), sig.size());
    return ret;
}

template <class PUB_KEY, class PRIV_KEY, class BYTES_OUT>
inline int ecdh(const PUB_KEY& pub_key, const PRIV_KEY& priv_key, BYTES_OUT& bytes_out) {
    int ret = ::wally_ecdh(pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int format_bitcoin_message(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_format_bitcoin_message(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

inline int free_string(char* str) {
    int ret = ::wally_free_string(str);
    return ret;
}

inline int get_operations(struct wally_operations* output) {
    int ret = ::wally_get_operations(output);
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int hash160(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_hash160(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES>
inline int hex_from_bytes(const BYTES& bytes, char** output) {
    int ret = ::wally_hex_from_bytes(bytes.data(), bytes.size(), output);
    return ret;
}

template <class HEX, class BYTES_OUT>
inline int hex_to_bytes(const HEX& hex, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_hex_to_bytes(detail::get_p(hex), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class KEY, class BYTES, class BYTES_OUT>
inline int hmac_sha256(const KEY& key, const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_hmac_sha256(key.data(), key.size(), bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class KEY, class BYTES, class BYTES_OUT>
inline int hmac_sha512(const KEY& key, const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_hmac_sha512(key.data(), key.size(), bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

inline int init(uint32_t flags) {
    int ret = ::wally_init(flags);
    return ret;
}

inline int is_elements_build(size_t* written) {
    int ret = ::wally_is_elements_build(written);
    return ret;
}

template <class MAP_IN, class KEY, class VALUE>
inline int map_add(const MAP_IN& map_in, const KEY& key, const VALUE& value) {
    int ret = ::wally_map_add(detail::get_p(map_in), key.data(), key.size(), value.data(), value.size());
    return ret;
}

template <class MAP_IN, class PUB_KEY, class FINGERPRINT, class CHILD_PATH>
inline int map_add_keypath_item(const MAP_IN& map_in, const PUB_KEY& pub_key, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_map_add_keypath_item(detail::get_p(map_in), pub_key.data(), pub_key.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return ret;
}

template <class MAP_IN, class KEY>
inline int map_find(const MAP_IN& map_in, const KEY& key, size_t* written = 0) {
    size_t n;
    int ret = ::wally_map_find(detail::get_p(map_in), key.data(), key.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(key.size()) ? WALLY_OK : WALLY_EINVAL;
}

inline int map_free(struct wally_map* map_in) {
    int ret = ::wally_map_free(map_in);
    return ret;
}

inline int map_init_alloc(size_t allocation_len, struct wally_map** output) {
    int ret = ::wally_map_init_alloc(allocation_len, output);
    return ret;
}

template <class MAP_IN>
inline int map_sort(const MAP_IN& map_in, uint32_t flags) {
    int ret = ::wally_map_sort(detail::get_p(map_in), flags);
    return ret;
}

template <class PASS, class SALT, class BYTES_OUT>
inline int pbkdf2_hmac_sha256(const PASS& pass, const SALT& salt, uint32_t flags, uint32_t cost, BYTES_OUT& bytes_out) {
    int ret = ::wally_pbkdf2_hmac_sha256(pass.data(), pass.size(), salt.data(), salt.size(), flags, cost, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class PASS, class SALT, class BYTES_OUT>
inline int pbkdf2_hmac_sha512(const PASS& pass, const SALT& salt, uint32_t flags, uint32_t cost, BYTES_OUT& bytes_out) {
    int ret = ::wally_pbkdf2_hmac_sha512(pass.data(), pass.size(), salt.data(), salt.size(), flags, cost, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class PSBT>
inline int psbt_add_input_at(const PSBT& psbt, uint32_t index, uint32_t flags, const struct wally_tx_input* input) {
    int ret = ::wally_psbt_add_input_at(detail::get_p(psbt), index, flags, input);
    return ret;
}

template <class PSBT>
inline int psbt_add_output_at(const PSBT& psbt, uint32_t index, uint32_t flags, const struct wally_tx_output* output) {
    int ret = ::wally_psbt_add_output_at(detail::get_p(psbt), index, flags, output);
    return ret;
}

template <class PSBT>
inline int psbt_clone_alloc(const PSBT& psbt, uint32_t flags, struct wally_psbt** output) {
    int ret = ::wally_psbt_clone_alloc(detail::get_p(psbt), flags, output);
    return ret;
}

template <class PSBT>
inline int psbt_combine(const PSBT& psbt, const struct wally_psbt* src) {
    int ret = ::wally_psbt_combine(detail::get_p(psbt), src);
    return ret;
}

template <class PSBT>
inline int psbt_extract(const PSBT& psbt, struct wally_tx** output) {
    int ret = ::wally_psbt_extract(detail::get_p(psbt), output);
    return ret;
}

inline int psbt_finalize(struct wally_psbt* psbt) {
    int ret = ::wally_psbt_finalize(psbt);
    return ret;
}

inline int psbt_free(struct wally_psbt* psbt) {
    int ret = ::wally_psbt_free(psbt);
    return ret;
}

template <class BASE64>
inline int psbt_from_base64(const BASE64& base64, struct wally_psbt** output) {
    int ret = ::wally_psbt_from_base64(detail::get_p(base64), output);
    return ret;
}

template <class BYTES>
inline int psbt_from_bytes(const BYTES& bytes, struct wally_psbt** output) {
    int ret = ::wally_psbt_from_bytes(bytes.data(), bytes.size(), output);
    return ret;
}

template <class PSBT>
inline int psbt_get_length(const PSBT& psbt, uint32_t flags, size_t* written) {
    int ret = ::wally_psbt_get_length(detail::get_p(psbt), flags, written);
    return ret;
}

inline int psbt_init_alloc(uint32_t version, size_t inputs_allocation_len, size_t outputs_allocation_len, size_t global_unknowns_allocation_len, struct wally_psbt** output) {
    int ret = ::wally_psbt_init_alloc(version, inputs_allocation_len, outputs_allocation_len, global_unknowns_allocation_len, output);
    return ret;
}

template <class INPUT, class PUB_KEY, class FINGERPRINT, class CHILD_PATH>
inline int psbt_input_add_keypath_item(const INPUT& input, const PUB_KEY& pub_key, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_input_add_keypath_item(detail::get_p(input), pub_key.data(), pub_key.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return ret;
}

template <class INPUT, class PUB_KEY, class SIG>
inline int psbt_input_add_signature(const INPUT& input, const PUB_KEY& pub_key, const SIG& sig) {
    int ret = ::wally_psbt_input_add_signature(detail::get_p(input), pub_key.data(), pub_key.size(), sig.data(), sig.size());
    return ret;
}

template <class INPUT, class PUB_KEY>
inline int psbt_input_find_keypath(const INPUT& input, const PUB_KEY& pub_key, size_t* written = 0) {
    size_t n;
    int ret = ::wally_psbt_input_find_keypath(detail::get_p(input), pub_key.data(), pub_key.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(pub_key.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class INPUT, class PUB_KEY>
inline int psbt_input_find_signature(const INPUT& input, const PUB_KEY& pub_key, size_t* written = 0) {
    size_t n;
    int ret = ::wally_psbt_input_find_signature(detail::get_p(input), pub_key.data(), pub_key.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(pub_key.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class INPUT, class KEY>
inline int psbt_input_find_unknown(const INPUT& input, const KEY& key, size_t* written = 0) {
    size_t n;
    int ret = ::wally_psbt_input_find_unknown(detail::get_p(input), key.data(), key.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(key.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class INPUT>
inline int psbt_input_is_finalized(const INPUT& input, size_t* written) {
    int ret = ::wally_psbt_input_is_finalized(detail::get_p(input), written);
    return ret;
}

template <class INPUT, class FINAL_SCRIPTSIG>
inline int psbt_input_set_final_scriptsig(const INPUT& input, const FINAL_SCRIPTSIG& final_scriptsig) {
    int ret = ::wally_psbt_input_set_final_scriptsig(detail::get_p(input), final_scriptsig.data(), final_scriptsig.size());
    return ret;
}

template <class INPUT>
inline int psbt_input_set_final_witness(const INPUT& input, const struct wally_tx_witness_stack* final_witness) {
    int ret = ::wally_psbt_input_set_final_witness(detail::get_p(input), final_witness);
    return ret;
}

template <class INPUT>
inline int psbt_input_set_keypaths(const INPUT& input, const struct wally_map* map_in) {
    int ret = ::wally_psbt_input_set_keypaths(detail::get_p(input), map_in);
    return ret;
}

template <class INPUT, class SCRIPT>
inline int psbt_input_set_redeem_script(const INPUT& input, const SCRIPT& script) {
    int ret = ::wally_psbt_input_set_redeem_script(detail::get_p(input), script.data(), script.size());
    return ret;
}

template <class INPUT>
inline int psbt_input_set_sighash(const INPUT& input, uint32_t sighash) {
    int ret = ::wally_psbt_input_set_sighash(detail::get_p(input), sighash);
    return ret;
}

template <class INPUT>
inline int psbt_input_set_signatures(const INPUT& input, const struct wally_map* map_in) {
    int ret = ::wally_psbt_input_set_signatures(detail::get_p(input), map_in);
    return ret;
}

template <class INPUT>
inline int psbt_input_set_unknowns(const INPUT& input, const struct wally_map* map_in) {
    int ret = ::wally_psbt_input_set_unknowns(detail::get_p(input), map_in);
    return ret;
}

template <class INPUT>
inline int psbt_input_set_utxo(const INPUT& input, const struct wally_tx* utxo) {
    int ret = ::wally_psbt_input_set_utxo(detail::get_p(input), utxo);
    return ret;
}

template <class INPUT, class SCRIPT>
inline int psbt_input_set_witness_script(const INPUT& input, const SCRIPT& script) {
    int ret = ::wally_psbt_input_set_witness_script(detail::get_p(input), script.data(), script.size());
    return ret;
}

template <class INPUT>
inline int psbt_input_set_witness_utxo(const INPUT& input, const struct wally_tx_output* witness_utxo) {
    int ret = ::wally_psbt_input_set_witness_utxo(detail::get_p(input), witness_utxo);
    return ret;
}

template <class PSBT>
inline int psbt_is_elements(const PSBT& psbt, size_t* written) {
    int ret = ::wally_psbt_is_elements(detail::get_p(psbt), written);
    return ret;
}

template <class PSBT>
inline int psbt_is_finalized(const PSBT& psbt, size_t* written) {
    int ret = ::wally_psbt_is_finalized(detail::get_p(psbt), written);
    return ret;
}

template <class OUTPUT, class PUB_KEY, class FINGERPRINT, class CHILD_PATH>
inline int psbt_output_add_keypath_item(const OUTPUT& output, const PUB_KEY& pub_key, const FINGERPRINT& fingerprint, const CHILD_PATH& child_path) {
    int ret = ::wally_psbt_output_add_keypath_item(detail::get_p(output), pub_key.data(), pub_key.size(), fingerprint.data(), fingerprint.size(), child_path.data(), child_path.size());
    return ret;
}

template <class OUTPUT, class PUB_KEY>
inline int psbt_output_find_keypath(const OUTPUT& output, const PUB_KEY& pub_key, size_t* written = 0) {
    size_t n;
    int ret = ::wally_psbt_output_find_keypath(detail::get_p(output), pub_key.data(), pub_key.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(pub_key.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class OUTPUT, class KEY>
inline int psbt_output_find_unknown(const OUTPUT& output, const KEY& key, size_t* written = 0) {
    size_t n;
    int ret = ::wally_psbt_output_find_unknown(detail::get_p(output), key.data(), key.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(key.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class OUTPUT>
inline int psbt_output_set_keypaths(const OUTPUT& output, const struct wally_map* map_in) {
    int ret = ::wally_psbt_output_set_keypaths(detail::get_p(output), map_in);
    return ret;
}

template <class OUTPUT, class SCRIPT>
inline int psbt_output_set_redeem_script(const OUTPUT& output, const SCRIPT& script) {
    int ret = ::wally_psbt_output_set_redeem_script(detail::get_p(output), script.data(), script.size());
    return ret;
}

template <class OUTPUT>
inline int psbt_output_set_unknowns(const OUTPUT& output, const struct wally_map* map_in) {
    int ret = ::wally_psbt_output_set_unknowns(detail::get_p(output), map_in);
    return ret;
}

template <class OUTPUT, class SCRIPT>
inline int psbt_output_set_witness_script(const OUTPUT& output, const SCRIPT& script) {
    int ret = ::wally_psbt_output_set_witness_script(detail::get_p(output), script.data(), script.size());
    return ret;
}

template <class PSBT>
inline int psbt_remove_input(const PSBT& psbt, uint32_t index) {
    int ret = ::wally_psbt_remove_input(detail::get_p(psbt), index);
    return ret;
}

template <class PSBT>
inline int psbt_remove_output(const PSBT& psbt, uint32_t index) {
    int ret = ::wally_psbt_remove_output(detail::get_p(psbt), index);
    return ret;
}

template <class PSBT>
inline int psbt_set_global_tx(const PSBT& psbt, const struct wally_tx* tx) {
    int ret = ::wally_psbt_set_global_tx(detail::get_p(psbt), tx);
    return ret;
}

template <class PSBT, class KEY>
inline int psbt_sign(const PSBT& psbt, const KEY& key, uint32_t flags) {
    int ret = ::wally_psbt_sign(detail::get_p(psbt), key.data(), key.size(), flags);
    return ret;
}

template <class PSBT>
inline int psbt_to_base64(const PSBT& psbt, uint32_t flags, char** output) {
    int ret = ::wally_psbt_to_base64(detail::get_p(psbt), flags, output);
    return ret;
}

template <class PSBT, class BYTES_OUT>
inline int psbt_to_bytes(const PSBT& psbt, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_psbt_to_bytes(detail::get_p(psbt), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int script_push_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_script_push_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_csv_2of2_then_1_from_bytes(const BYTES& bytes, uint32_t csv_blocks, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_csv_2of2_then_1_from_bytes(bytes.data(), bytes.size(), csv_blocks, flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_csv_2of2_then_1_from_bytes_opt(const BYTES& bytes, uint32_t csv_blocks, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_csv_2of2_then_1_from_bytes_opt(bytes.data(), bytes.size(), csv_blocks, flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_csv_2of3_then_2_from_bytes(const BYTES& bytes, uint32_t csv_blocks, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_csv_2of3_then_2_from_bytes(bytes.data(), bytes.size(), csv_blocks, flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES>
inline int scriptpubkey_get_type(const BYTES& bytes, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_get_type(bytes.data(), bytes.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_multisig_from_bytes(const BYTES& bytes, uint32_t threshold, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_multisig_from_bytes(bytes.data(), bytes.size(), threshold, flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_op_return_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_op_return_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_p2pkh_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_p2pkh_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int scriptpubkey_p2sh_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptpubkey_p2sh_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class SCRIPTPUBKEY>
inline int scriptpubkey_to_address(const SCRIPTPUBKEY& scriptpubkey, uint32_t network, char** output) {
    int ret = ::wally_scriptpubkey_to_address(scriptpubkey.data(), scriptpubkey.size(), network, output);
    return ret;
}

template <class SCRIPT, class BYTES, class SIGHASH, class BYTES_OUT>
inline int scriptsig_multisig_from_bytes(const SCRIPT& script, const BYTES& bytes, const SIGHASH& sighash, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptsig_multisig_from_bytes(script.data(), script.size(), bytes.data(), bytes.size(), sighash.data(), sighash.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class PUB_KEY, class SIG, class BYTES_OUT>
inline int scriptsig_p2pkh_from_der(const PUB_KEY& pub_key, const SIG& sig, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptsig_p2pkh_from_der(pub_key.data(), pub_key.size(), sig.data(), sig.size(), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class PUB_KEY, class SIG, class BYTES_OUT>
inline int scriptsig_p2pkh_from_sig(const PUB_KEY& pub_key, const SIG& sig, uint32_t sighash, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_scriptsig_p2pkh_from_sig(pub_key.data(), pub_key.size(), sig.data(), sig.size(), sighash, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class PASS, class SALT, class BYTES_OUT>
inline int scrypt(const PASS& pass, const SALT& salt, uint32_t cost, uint32_t block_size, uint32_t parallelism, BYTES_OUT& bytes_out) {
    int ret = ::wally_scrypt(pass.data(), pass.size(), salt.data(), salt.size(), cost, block_size, parallelism, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES>
inline int secp_randomize(const BYTES& bytes) {
    int ret = ::wally_secp_randomize(bytes.data(), bytes.size());
    return ret;
}

inline int set_operations(const struct wally_operations* ops) {
    int ret = ::wally_set_operations(ops);
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int sha256(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha256(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int sha256_midstate(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha256_midstate(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int sha256d(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha256d(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int sha512(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_sha512(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class LABEL, class BYTES_OUT>
inline int symmetric_key_from_parent(const BYTES& bytes, uint32_t version, const LABEL& label, BYTES_OUT& bytes_out) {
    int ret = ::wally_symmetric_key_from_parent(bytes.data(), bytes.size(), version, label.data(), label.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int symmetric_key_from_seed(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_symmetric_key_from_seed(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class TX>
inline int tx_add_input(const TX& tx, const struct wally_tx_input* input) {
    int ret = ::wally_tx_add_input(detail::get_p(tx), input);
    return ret;
}

template <class TX>
inline int tx_add_input_at(const TX& tx, uint32_t index, const struct wally_tx_input* input) {
    int ret = ::wally_tx_add_input_at(detail::get_p(tx), index, input);
    return ret;
}

template <class TX>
inline int tx_add_output(const TX& tx, const struct wally_tx_output* output) {
    int ret = ::wally_tx_add_output(detail::get_p(tx), output);
    return ret;
}

template <class TX>
inline int tx_add_output_at(const TX& tx, uint32_t index, const struct wally_tx_output* output) {
    int ret = ::wally_tx_add_output_at(detail::get_p(tx), index, output);
    return ret;
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS>
inline int tx_add_raw_input(const TX& tx, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, uint32_t flags) {
    int ret = ::wally_tx_add_raw_input(detail::get_p(tx), txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), flags);
    return ret;
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS>
inline int tx_add_raw_input_at(const TX& tx, uint32_t index, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, uint32_t flags) {
    int ret = ::wally_tx_add_raw_input_at(detail::get_p(tx), index, txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), flags);
    return ret;
}

template <class TX, class SCRIPT>
inline int tx_add_raw_output(const TX& tx, uint64_t satoshi, const SCRIPT& script, uint32_t flags) {
    int ret = ::wally_tx_add_raw_output(detail::get_p(tx), satoshi, script.data(), script.size(), flags);
    return ret;
}

template <class TX, class SCRIPT>
inline int tx_add_raw_output_at(const TX& tx, uint32_t index, uint64_t satoshi, const SCRIPT& script, uint32_t flags) {
    int ret = ::wally_tx_add_raw_output_at(detail::get_p(tx), index, satoshi, script.data(), script.size(), flags);
    return ret;
}

template <class TX>
inline int tx_clone_alloc(const TX& tx, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_tx_clone_alloc(detail::get_p(tx), flags, output);
    return ret;
}

inline int tx_free(struct wally_tx* tx) {
    int ret = ::wally_tx_free(tx);
    return ret;
}

template <class BYTES>
inline int tx_from_bytes(const BYTES& bytes, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_tx_from_bytes(bytes.data(), bytes.size(), flags, output);
    return ret;
}

template <class HEX>
inline int tx_from_hex(const HEX& hex, uint32_t flags, struct wally_tx** output) {
    int ret = ::wally_tx_from_hex(detail::get_p(hex), flags, output);
    return ret;
}

template <class TX, class SCRIPT, class BYTES_OUT>
inline int tx_get_btc_signature_hash(const TX& tx, size_t index, const SCRIPT& script, uint64_t satoshi, uint32_t sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_btc_signature_hash(detail::get_p(tx), index, script.data(), script.size(), satoshi, sighash, flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class TX>
inline int tx_get_length(const TX& tx, uint32_t flags, size_t* written) {
    int ret = ::wally_tx_get_length(detail::get_p(tx), flags, written);
    return ret;
}

template <class TX, class SCRIPT, class EXTRA, class BYTES_OUT>
inline int tx_get_signature_hash(const TX& tx, size_t index, const SCRIPT& script, const EXTRA& extra, uint32_t extra_offset, uint64_t satoshi, uint32_t sighash, uint32_t tx_sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_signature_hash(detail::get_p(tx), index, script.data(), script.size(), extra.data(), extra.size(), extra_offset, satoshi, sighash, tx_sighash, flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class TX>
inline int tx_get_total_output_satoshi(const TX& tx, uint64_t* value_out) {
    int ret = ::wally_tx_get_total_output_satoshi(detail::get_p(tx), value_out);
    return ret;
}

template <class TX, class BYTES_OUT>
inline int tx_get_txid(const TX& tx, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_txid(detail::get_p(tx), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class TX>
inline int tx_get_vsize(const TX& tx, size_t* written) {
    int ret = ::wally_tx_get_vsize(detail::get_p(tx), written);
    return ret;
}

template <class TX>
inline int tx_get_weight(const TX& tx, size_t* written) {
    int ret = ::wally_tx_get_weight(detail::get_p(tx), written);
    return ret;
}

template <class TX>
inline int tx_get_witness_count(const TX& tx, size_t* written) {
    int ret = ::wally_tx_get_witness_count(detail::get_p(tx), written);
    return ret;
}

inline int tx_init_alloc(uint32_t version, uint32_t locktime, size_t inputs_allocation_len, size_t outputs_allocation_len, struct wally_tx** output) {
    int ret = ::wally_tx_init_alloc(version, locktime, inputs_allocation_len, outputs_allocation_len, output);
    return ret;
}

inline int tx_input_free(struct wally_tx_input* input) {
    int ret = ::wally_tx_input_free(input);
    return ret;
}

template <class TXHASH, class SCRIPT, class WITNESS>
inline int tx_input_init_alloc(const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, struct wally_tx_input** output) {
    int ret = ::wally_tx_input_init_alloc(txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), output);
    return ret;
}

template <class TX>
inline int tx_is_coinbase(const TX& tx, size_t* written) {
    int ret = ::wally_tx_is_coinbase(detail::get_p(tx), written);
    return ret;
}

template <class TX_OUTPUT_IN>
inline int tx_output_clone(const TX_OUTPUT_IN& tx_output_in, struct wally_tx_output* output) {
    int ret = ::wally_tx_output_clone(detail::get_p(tx_output_in), output);
    return ret;
}

template <class TX_OUTPUT_IN>
inline int tx_output_clone_alloc(const TX_OUTPUT_IN& tx_output_in, struct wally_tx_output** output) {
    int ret = ::wally_tx_output_clone_alloc(detail::get_p(tx_output_in), output);
    return ret;
}

inline int tx_output_free(struct wally_tx_output* output) {
    int ret = ::wally_tx_output_free(output);
    return ret;
}

template <class SCRIPT>
inline int tx_output_init(uint64_t satoshi, const SCRIPT& script, struct wally_tx_output* output) {
    int ret = ::wally_tx_output_init(satoshi, script.data(), script.size(), output);
    return ret;
}

template <class SCRIPT>
inline int tx_output_init_alloc(uint64_t satoshi, const SCRIPT& script, struct wally_tx_output** output) {
    int ret = ::wally_tx_output_init_alloc(satoshi, script.data(), script.size(), output);
    return ret;
}

template <class TX>
inline int tx_remove_input(const TX& tx, size_t index) {
    int ret = ::wally_tx_remove_input(detail::get_p(tx), index);
    return ret;
}

template <class TX>
inline int tx_remove_output(const TX& tx, size_t index) {
    int ret = ::wally_tx_remove_output(detail::get_p(tx), index);
    return ret;
}

template <class TX, class SCRIPT>
inline int tx_set_input_script(const TX& tx, size_t index, const SCRIPT& script) {
    int ret = ::wally_tx_set_input_script(detail::get_p(tx), index, script.data(), script.size());
    return ret;
}

template <class TX>
inline int tx_set_input_witness(const TX& tx, size_t index, const struct wally_tx_witness_stack* stack) {
    int ret = ::wally_tx_set_input_witness(detail::get_p(tx), index, stack);
    return ret;
}

template <class TX, class BYTES_OUT>
inline int tx_to_bytes(const TX& tx, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_tx_to_bytes(detail::get_p(tx), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class TX>
inline int tx_to_hex(const TX& tx, uint32_t flags, char** output) {
    int ret = ::wally_tx_to_hex(detail::get_p(tx), flags, output);
    return ret;
}

inline int tx_vsize_from_weight(size_t weight, size_t* written) {
    int ret = ::wally_tx_vsize_from_weight(weight, written);
    return ret;
}

template <class STACK, class WITNESS>
inline int tx_witness_stack_add(const STACK& stack, const WITNESS& witness) {
    int ret = ::wally_tx_witness_stack_add(detail::get_p(stack), witness.data(), witness.size());
    return ret;
}

template <class STACK>
inline int tx_witness_stack_add_dummy(const STACK& stack, uint32_t flags) {
    int ret = ::wally_tx_witness_stack_add_dummy(detail::get_p(stack), flags);
    return ret;
}

template <class STACK>
inline int tx_witness_stack_clone_alloc(const STACK& stack, struct wally_tx_witness_stack** output) {
    int ret = ::wally_tx_witness_stack_clone_alloc(detail::get_p(stack), output);
    return ret;
}

inline int tx_witness_stack_free(struct wally_tx_witness_stack* stack) {
    int ret = ::wally_tx_witness_stack_free(stack);
    return ret;
}

inline int tx_witness_stack_init_alloc(size_t allocation_len, struct wally_tx_witness_stack** output) {
    int ret = ::wally_tx_witness_stack_init_alloc(allocation_len, output);
    return ret;
}

template <class STACK, class WITNESS>
inline int tx_witness_stack_set(const STACK& stack, size_t index, const WITNESS& witness) {
    int ret = ::wally_tx_witness_stack_set(detail::get_p(stack), index, witness.data(), witness.size());
    return ret;
}

template <class STACK>
inline int tx_witness_stack_set_dummy(const STACK& stack, size_t index, uint32_t flags) {
    int ret = ::wally_tx_witness_stack_set_dummy(detail::get_p(stack), index, flags);
    return ret;
}

template <class BYTES>
inline int varbuff_get_length(const BYTES& bytes, size_t* written = 0) {
    size_t n;
    int ret = ::wally_varbuff_get_length(bytes.data(), bytes.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class BYTES, class BYTES_OUT>
inline int varbuff_to_bytes(const BYTES& bytes, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_varbuff_to_bytes(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

inline int varint_get_length(uint64_t value, size_t* written) {
    int ret = ::wally_varint_get_length(value, written);
    return ret;
}

template <class BYTES_OUT>
inline int varint_to_bytes(uint64_t value, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_varint_to_bytes(value, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class PRIV_KEY>
inline int wif_from_bytes(const PRIV_KEY& priv_key, uint32_t prefix, uint32_t flags, char** output) {
    int ret = ::wally_wif_from_bytes(priv_key.data(), priv_key.size(), prefix, flags, output);
    return ret;
}

template <class WIF>
inline int wif_is_uncompressed(const WIF& wif, size_t* written) {
    int ret = ::wally_wif_is_uncompressed(detail::get_p(wif), written);
    return ret;
}

template <class WIF>
inline int wif_to_address(const WIF& wif, uint32_t prefix, uint32_t version, char** output) {
    int ret = ::wally_wif_to_address(detail::get_p(wif), prefix, version, output);
    return ret;
}

template <class WIF, class BYTES_OUT>
inline int wif_to_bytes(const WIF& wif, uint32_t prefix, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_wif_to_bytes(detail::get_p(wif), prefix, flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class WIF, class BYTES_OUT>
inline int wif_to_public_key(const WIF& wif, uint32_t prefix, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_wif_to_public_key(detail::get_p(wif), prefix, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class SCRIPT, class BYTES, class SIGHASH>
inline int witness_multisig_from_bytes(const SCRIPT& script, const BYTES& bytes, const SIGHASH& sighash, uint32_t flags, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_multisig_from_bytes(script.data(), script.size(), bytes.data(), bytes.size(), sighash.data(), sighash.size(), flags, witness);
    return ret;
}

template <class PUB_KEY, class SIG>
inline int witness_p2wpkh_from_der(const PUB_KEY& pub_key, const SIG& sig, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_p2wpkh_from_der(pub_key.data(), pub_key.size(), sig.data(), sig.size(), witness);
    return ret;
}

template <class PUB_KEY, class SIG>
inline int witness_p2wpkh_from_sig(const PUB_KEY& pub_key, const SIG& sig, uint32_t sighash, struct wally_tx_witness_stack** witness) {
    int ret = ::wally_witness_p2wpkh_from_sig(pub_key.data(), pub_key.size(), sig.data(), sig.size(), sighash, witness);
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int witness_program_from_bytes(const BYTES& bytes, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_witness_program_from_bytes(bytes.data(), bytes.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

#ifdef BUILD_ELEMENTS
template <class HDKEY, class CHILD_PATH>
inline int bip32_key_with_tweak_from_parent_path(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key* output) {
    int ret = ::bip32_key_with_tweak_from_parent_path(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return ret;
}

template <class HDKEY, class CHILD_PATH>
inline int bip32_key_with_tweak_from_parent_path_alloc(const HDKEY& hdkey, const CHILD_PATH& child_path, uint32_t flags, struct ext_key** output) {
    int ret = ::bip32_key_with_tweak_from_parent_path_alloc(detail::get_p(hdkey), child_path.data(), child_path.size(), flags, output);
    return ret;
}

template <class BYTES, class BYTES_OUT>
inline int asset_blinding_key_from_seed(const BYTES& bytes, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_from_seed(bytes.data(), bytes.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class BYTES, class SCRIPT, class BYTES_OUT>
inline int asset_blinding_key_to_ec_private_key(const BYTES& bytes, const SCRIPT& script, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_blinding_key_to_ec_private_key(bytes.data(), bytes.size(), script.data(), script.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class VALUES, class ABF, class VBF, class BYTES_OUT>
inline int asset_final_vbf(const VALUES& values, size_t num_inputs, const ABF& abf, const VBF& vbf, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_final_vbf(values.data(), values.size(), num_inputs, abf.data(), abf.size(), vbf.data(), vbf.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class ASSET, class ABF, class BYTES_OUT>
inline int asset_generator_from_bytes(const ASSET& asset, const ABF& abf, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_generator_from_bytes(asset.data(), asset.size(), abf.data(), abf.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class ONLINE_KEYS, class OFFLINE_KEYS, class SUB_PUBKEY, class ONLINE_PRIV_KEY, class SUMMED_KEY, class BYTES_OUT>
inline int asset_pak_whitelistproof(const ONLINE_KEYS& online_keys, const OFFLINE_KEYS& offline_keys, size_t key_index, const SUB_PUBKEY& sub_pubkey, const ONLINE_PRIV_KEY& online_priv_key, const SUMMED_KEY& summed_key, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_asset_pak_whitelistproof(online_keys.data(), online_keys.size(), offline_keys.data(), offline_keys.size(), key_index, sub_pubkey.data(), sub_pubkey.size(), online_priv_key.data(), online_priv_key.size(), summed_key.data(), summed_key.size(), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

inline int asset_pak_whitelistproof_size(size_t num_keys, size_t* written) {
    int ret = ::wally_asset_pak_whitelistproof_size(num_keys, written);
    return ret;
}

template <class PUB_KEY, class PRIV_KEY, class ASSET, class ABF, class VBF, class COMMITMENT, class EXTRA, class GENERATOR, class BYTES_OUT>
inline int asset_rangeproof(uint64_t value, const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const ASSET& asset, const ABF& abf, const VBF& vbf, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, uint64_t min_value, int exp, int min_bits, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_asset_rangeproof(value, pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), asset.data(), asset.size(), abf.data(), abf.size(), vbf.data(), vbf.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), min_value, exp, min_bits, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class OUTPUT_ASSET, class OUTPUT_ABF, class OUTPUT_GENERATOR, class BYTES, class ASSET, class ABF, class GENERATOR, class BYTES_OUT>
inline int asset_surjectionproof(const OUTPUT_ASSET& output_asset, const OUTPUT_ABF& output_abf, const OUTPUT_GENERATOR& output_generator, const BYTES& bytes, const ASSET& asset, const ABF& abf, const GENERATOR& generator, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_asset_surjectionproof(output_asset.data(), output_asset.size(), output_abf.data(), output_abf.size(), output_generator.data(), output_generator.size(), bytes.data(), bytes.size(), asset.data(), asset.size(), abf.data(), abf.size(), generator.data(), generator.size(), bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

inline int asset_surjectionproof_size(size_t num_inputs, size_t* written) {
    int ret = ::wally_asset_surjectionproof_size(num_inputs, written);
    return ret;
}

template <class PUB_KEY, class PRIV_KEY, class PROOF, class COMMITMENT, class EXTRA, class GENERATOR, class ASSET_OUT, class ABF_OUT, class VBF_OUT>
inline int asset_unblind(const PUB_KEY& pub_key, const PRIV_KEY& priv_key, const PROOF& proof, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, ASSET_OUT& asset_out, ABF_OUT& abf_out, VBF_OUT& vbf_out, uint64_t* value_out) {
    int ret = ::wally_asset_unblind(pub_key.data(), pub_key.size(), priv_key.data(), priv_key.size(), proof.data(), proof.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), asset_out.data(), asset_out.size(), abf_out.data(), abf_out.size(), vbf_out.data(), vbf_out.size(), value_out);
    return ret;
}

template <class NONCE_HASH, class PROOF, class COMMITMENT, class EXTRA, class GENERATOR, class ASSET_OUT, class ABF_OUT, class VBF_OUT>
inline int asset_unblind_with_nonce(const NONCE_HASH& nonce_hash, const PROOF& proof, const COMMITMENT& commitment, const EXTRA& extra, const GENERATOR& generator, ASSET_OUT& asset_out, ABF_OUT& abf_out, VBF_OUT& vbf_out, uint64_t* value_out) {
    int ret = ::wally_asset_unblind_with_nonce(nonce_hash.data(), nonce_hash.size(), proof.data(), proof.size(), commitment.data(), commitment.size(), extra.data(), extra.size(), generator.data(), generator.size(), asset_out.data(), asset_out.size(), abf_out.data(), abf_out.size(), vbf_out.data(), vbf_out.size(), value_out);
    return ret;
}

template <class VBF, class GENERATOR, class BYTES_OUT>
inline int asset_value_commitment(uint64_t value, const VBF& vbf, const GENERATOR& generator, BYTES_OUT& bytes_out) {
    int ret = ::wally_asset_value_commitment(value, vbf.data(), vbf.size(), generator.data(), generator.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class ADDRESS, class PUB_KEY>
inline int confidential_addr_from_addr(const ADDRESS& address, uint32_t prefix, const PUB_KEY& pub_key, char** output) {
    int ret = ::wally_confidential_addr_from_addr(detail::get_p(address), prefix, pub_key.data(), pub_key.size(), output);
    return ret;
}

template <class ADDRESS, class ADDR_FAMILY, class CONFIDENTIAL_ADDR_FAMILY, class PUB_KEY>
inline int confidential_addr_from_addr_segwit(const ADDRESS& address, const ADDR_FAMILY& addr_family, const CONFIDENTIAL_ADDR_FAMILY& confidential_addr_family, const PUB_KEY& pub_key, char** output) {
    int ret = ::wally_confidential_addr_from_addr_segwit(detail::get_p(address), detail::get_p(addr_family), detail::get_p(confidential_addr_family), pub_key.data(), pub_key.size(), output);
    return ret;
}

template <class ADDRESS, class CONFIDENTIAL_ADDR_FAMILY, class BYTES_OUT>
inline int confidential_addr_segwit_to_ec_public_key(const ADDRESS& address, const CONFIDENTIAL_ADDR_FAMILY& confidential_addr_family, BYTES_OUT& bytes_out) {
    int ret = ::wally_confidential_addr_segwit_to_ec_public_key(detail::get_p(address), detail::get_p(confidential_addr_family), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class ADDRESS>
inline int confidential_addr_to_addr(const ADDRESS& address, uint32_t prefix, char** output) {
    int ret = ::wally_confidential_addr_to_addr(detail::get_p(address), prefix, output);
    return ret;
}

template <class ADDRESS, class CONFIDENTIAL_ADDR_FAMILY, class ADDR_FAMILY>
inline int confidential_addr_to_addr_segwit(const ADDRESS& address, const CONFIDENTIAL_ADDR_FAMILY& confidential_addr_family, const ADDR_FAMILY& addr_family, char** output) {
    int ret = ::wally_confidential_addr_to_addr_segwit(detail::get_p(address), detail::get_p(confidential_addr_family), detail::get_p(addr_family), output);
    return ret;
}

template <class ADDRESS, class BYTES_OUT>
inline int confidential_addr_to_ec_public_key(const ADDRESS& address, uint32_t prefix, BYTES_OUT& bytes_out) {
    int ret = ::wally_confidential_addr_to_ec_public_key(detail::get_p(address), prefix, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class REDEEM_SCRIPT, class SCRIPT, class BYTES_OUT>
inline int elements_pegin_contract_script_from_bytes(const REDEEM_SCRIPT& redeem_script, const SCRIPT& script, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_elements_pegin_contract_script_from_bytes(redeem_script.data(), redeem_script.size(), script.data(), script.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

template <class GENESIS_BLOCKHASH, class MAINCHAIN_SCRIPT, class SUB_PUBKEY, class WHITELISTPROOF, class BYTES_OUT>
inline int elements_pegout_script_from_bytes(const GENESIS_BLOCKHASH& genesis_blockhash, const MAINCHAIN_SCRIPT& mainchain_script, const SUB_PUBKEY& sub_pubkey, const WHITELISTPROOF& whitelistproof, uint32_t flags, BYTES_OUT& bytes_out, size_t* written = 0) {
    size_t n;
    int ret = ::wally_elements_pegout_script_from_bytes(genesis_blockhash.data(), genesis_blockhash.size(), mainchain_script.data(), mainchain_script.size(), sub_pubkey.data(), sub_pubkey.size(), whitelistproof.data(), whitelistproof.size(), flags, bytes_out.data(), bytes_out.size(), written ? written : &n);
    return written || ret != WALLY_OK ? ret : n == static_cast<size_t>(bytes_out.size()) ? WALLY_OK : WALLY_EINVAL;
}

inline int elements_pegout_script_size(size_t genesis_blockhash_len, size_t mainchain_script_len, size_t sub_pubkey_len, size_t whitelistproof_len, size_t* written) {
    int ret = ::wally_elements_pegout_script_size(genesis_blockhash_len, mainchain_script_len, sub_pubkey_len, whitelistproof_len, written);
    return ret;
}

inline int psbt_elements_init_alloc(uint32_t version, size_t inputs_allocation_len, size_t outputs_allocation_len, size_t global_unknowns_allocation_len, struct wally_psbt** output) {
    int ret = ::wally_psbt_elements_init_alloc(version, inputs_allocation_len, outputs_allocation_len, global_unknowns_allocation_len, output);
    return ret;
}

inline int psbt_input_clear_value(struct wally_psbt_input* input) {
    int ret = ::wally_psbt_input_clear_value(input);
    return ret;
}

template <class INPUT, class ABF>
inline int psbt_input_set_abf(const INPUT& input, const ABF& abf) {
    int ret = ::wally_psbt_input_set_abf(detail::get_p(input), abf.data(), abf.size());
    return ret;
}

template <class INPUT, class ASSET>
inline int psbt_input_set_asset(const INPUT& input, const ASSET& asset) {
    int ret = ::wally_psbt_input_set_asset(detail::get_p(input), asset.data(), asset.size());
    return ret;
}

template <class INPUT, class SCRIPT>
inline int psbt_input_set_claim_script(const INPUT& input, const SCRIPT& script) {
    int ret = ::wally_psbt_input_set_claim_script(detail::get_p(input), script.data(), script.size());
    return ret;
}

template <class INPUT, class GENESIS_BLOCKHASH>
inline int psbt_input_set_genesis_blockhash(const INPUT& input, const GENESIS_BLOCKHASH& genesis_blockhash) {
    int ret = ::wally_psbt_input_set_genesis_blockhash(detail::get_p(input), genesis_blockhash.data(), genesis_blockhash.size());
    return ret;
}

template <class INPUT>
inline int psbt_input_set_pegin_tx(const INPUT& input, const struct wally_tx* pegin_tx) {
    int ret = ::wally_psbt_input_set_pegin_tx(detail::get_p(input), pegin_tx);
    return ret;
}

template <class INPUT, class PROOF>
inline int psbt_input_set_txoutproof(const INPUT& input, const PROOF& proof) {
    int ret = ::wally_psbt_input_set_txoutproof(detail::get_p(input), proof.data(), proof.size());
    return ret;
}

template <class INPUT>
inline int psbt_input_set_value(const INPUT& input, uint64_t value) {
    int ret = ::wally_psbt_input_set_value(detail::get_p(input), value);
    return ret;
}

template <class INPUT, class VBF>
inline int psbt_input_set_vbf(const INPUT& input, const VBF& vbf) {
    int ret = ::wally_psbt_input_set_vbf(detail::get_p(input), vbf.data(), vbf.size());
    return ret;
}

template <class OUTPUT, class ABF>
inline int psbt_output_set_abf(const OUTPUT& output, const ABF& abf) {
    int ret = ::wally_psbt_output_set_abf(detail::get_p(output), abf.data(), abf.size());
    return ret;
}

template <class OUTPUT, class COMMITMENT>
inline int psbt_output_set_asset_commitment(const OUTPUT& output, const COMMITMENT& commitment) {
    int ret = ::wally_psbt_output_set_asset_commitment(detail::get_p(output), commitment.data(), commitment.size());
    return ret;
}

template <class OUTPUT, class PUB_KEY>
inline int psbt_output_set_blinding_pubkey(const OUTPUT& output, const PUB_KEY& pub_key) {
    int ret = ::wally_psbt_output_set_blinding_pubkey(detail::get_p(output), pub_key.data(), pub_key.size());
    return ret;
}

template <class OUTPUT, class NONCE>
inline int psbt_output_set_nonce(const OUTPUT& output, const NONCE& nonce) {
    int ret = ::wally_psbt_output_set_nonce(detail::get_p(output), nonce.data(), nonce.size());
    return ret;
}

template <class OUTPUT, class PROOF>
inline int psbt_output_set_rangeproof(const OUTPUT& output, const PROOF& proof) {
    int ret = ::wally_psbt_output_set_rangeproof(detail::get_p(output), proof.data(), proof.size());
    return ret;
}

template <class OUTPUT, class PROOF>
inline int psbt_output_set_surjectionproof(const OUTPUT& output, const PROOF& proof) {
    int ret = ::wally_psbt_output_set_surjectionproof(detail::get_p(output), proof.data(), proof.size());
    return ret;
}

template <class OUTPUT, class COMMITMENT>
inline int psbt_output_set_value_commitment(const OUTPUT& output, const COMMITMENT& commitment) {
    int ret = ::wally_psbt_output_set_value_commitment(detail::get_p(output), commitment.data(), commitment.size());
    return ret;
}

template <class OUTPUT, class VBF>
inline int psbt_output_set_vbf(const OUTPUT& output, const VBF& vbf) {
    int ret = ::wally_psbt_output_set_vbf(detail::get_p(output), vbf.data(), vbf.size());
    return ret;
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF, class PEGIN_WITNESS>
inline int tx_add_elements_raw_input(const TX& tx, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof, const PEGIN_WITNESS& pegin_witness, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_input(detail::get_p(tx), txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size(), detail::get_p(pegin_witness), flags);
    return ret;
}

template <class TX, class TXHASH, class SCRIPT, class WITNESS, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF, class PEGIN_WITNESS>
inline int tx_add_elements_raw_input_at(const TX& tx, uint32_t index, const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof, const PEGIN_WITNESS& pegin_witness, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_input_at(detail::get_p(tx), index, txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size(), detail::get_p(pegin_witness), flags);
    return ret;
}

template <class TX, class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_add_elements_raw_output(const TX& tx, const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_output(detail::get_p(tx), script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), flags);
    return ret;
}

template <class TX, class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_add_elements_raw_output_at(const TX& tx, uint32_t index, const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, uint32_t flags) {
    int ret = ::wally_tx_add_elements_raw_output_at(detail::get_p(tx), index, script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), flags);
    return ret;
}

template <class BYTES_OUT>
inline int tx_confidential_value_from_satoshi(uint64_t satoshi, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_confidential_value_from_satoshi(satoshi, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class VALUE>
inline int tx_confidential_value_to_satoshi(const VALUE& value, uint64_t* value_out) {
    int ret = ::wally_tx_confidential_value_to_satoshi(value.data(), value.size(), value_out);
    return ret;
}

template <class TXHASH, class SCRIPT, class WITNESS, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF, class PEGIN_WITNESS>
inline int tx_elements_input_init_alloc(const TXHASH& txhash, uint32_t utxo_index, uint32_t sequence, const SCRIPT& script, const WITNESS& witness, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof, const PEGIN_WITNESS& pegin_witness, struct wally_tx_input** output) {
    int ret = ::wally_tx_elements_input_init_alloc(txhash.data(), txhash.size(), utxo_index, sequence, script.data(), script.size(), detail::get_p(witness), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size(), detail::get_p(pegin_witness), output);
    return ret;
}

template <class INPUT>
inline int tx_elements_input_is_pegin(const INPUT& input, size_t* written) {
    int ret = ::wally_tx_elements_input_is_pegin(detail::get_p(input), written);
    return ret;
}

inline int tx_elements_input_issuance_free(struct wally_tx_input* input) {
    int ret = ::wally_tx_elements_input_issuance_free(input);
    return ret;
}

template <class INPUT, class NONCE, class ENTROPY, class ISSUANCE_AMOUNT, class INFLATION_KEYS, class ISSUANCE_AMOUNT_RANGEPROOF, class INFLATION_KEYS_RANGEPROOF>
inline int tx_elements_input_issuance_set(const INPUT& input, const NONCE& nonce, const ENTROPY& entropy, const ISSUANCE_AMOUNT& issuance_amount, const INFLATION_KEYS& inflation_keys, const ISSUANCE_AMOUNT_RANGEPROOF& issuance_amount_rangeproof, const INFLATION_KEYS_RANGEPROOF& inflation_keys_rangeproof) {
    int ret = ::wally_tx_elements_input_issuance_set(detail::get_p(input), nonce.data(), nonce.size(), entropy.data(), entropy.size(), issuance_amount.data(), issuance_amount.size(), inflation_keys.data(), inflation_keys.size(), issuance_amount_rangeproof.data(), issuance_amount_rangeproof.size(), inflation_keys_rangeproof.data(), inflation_keys_rangeproof.size());
    return ret;
}

template <class ENTROPY, class BYTES_OUT>
inline int tx_elements_issuance_calculate_asset(const ENTROPY& entropy, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_elements_issuance_calculate_asset(entropy.data(), entropy.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

template <class ENTROPY, class BYTES_OUT>
inline int tx_elements_issuance_calculate_reissuance_token(const ENTROPY& entropy, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_elements_issuance_calculate_reissuance_token(entropy.data(), entropy.size(), flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class TXHASH, class CONTRACT_HASH, class BYTES_OUT>
inline int tx_elements_issuance_generate_entropy(const TXHASH& txhash, uint32_t index, const CONTRACT_HASH& contract_hash, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_elements_issuance_generate_entropy(txhash.data(), txhash.size(), index, contract_hash.data(), contract_hash.size(), bytes_out.data(), bytes_out.size());
    return ret;
}

inline int tx_elements_output_commitment_free(struct wally_tx_output* output) {
    int ret = ::wally_tx_elements_output_commitment_free(output);
    return ret;
}

template <class OUTPUT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_elements_output_commitment_set(const OUTPUT& output, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof) {
    int ret = ::wally_tx_elements_output_commitment_set(detail::get_p(output), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size());
    return ret;
}

template <class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_elements_output_init(const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, struct wally_tx_output* output) {
    int ret = ::wally_tx_elements_output_init(script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), output);
    return ret;
}

template <class SCRIPT, class ASSET, class VALUE, class NONCE, class SURJECTIONPROOF, class RANGEPROOF>
inline int tx_elements_output_init_alloc(const SCRIPT& script, const ASSET& asset, const VALUE& value, const NONCE& nonce, const SURJECTIONPROOF& surjectionproof, const RANGEPROOF& rangeproof, struct wally_tx_output** output) {
    int ret = ::wally_tx_elements_output_init_alloc(script.data(), script.size(), asset.data(), asset.size(), value.data(), value.size(), nonce.data(), nonce.size(), surjectionproof.data(), surjectionproof.size(), rangeproof.data(), rangeproof.size(), output);
    return ret;
}

template <class TX, class SCRIPT, class VALUE, class BYTES_OUT>
inline int tx_get_elements_signature_hash(const TX& tx, size_t index, const SCRIPT& script, const VALUE& value, uint32_t sighash, uint32_t flags, BYTES_OUT& bytes_out) {
    int ret = ::wally_tx_get_elements_signature_hash(detail::get_p(tx), index, script.data(), script.size(), value.data(), value.size(), sighash, flags, bytes_out.data(), bytes_out.size());
    return ret;
}

template <class TX>
inline int tx_is_elements(const TX& tx, size_t* written) {
    int ret = ::wally_tx_is_elements(detail::get_p(tx), written);
    return ret;
}
#endif // BUILD_ELEMENTS
/* END AUTOGENERATED */

inline struct secp256k1_context_struct *get_secp_context() {
    return ::wally_get_secp_context();
}

inline int clear(void *p, size_t n) {
    return ::wally_bzero(p, n);
}

template<typename O> inline int clear(O& out) {
    return ::wally_bzero(out.data(), out.size());
}

inline bool is_elements_build()
{
    size_t ret;
    ::wally_is_elements_build(&ret);
    return ret != 0;
}

} /* namespace wally */

#endif /* LIBWALLY_CORE_WALLY_HPP */
