func ToOutputScript(address string) ([]byte, error) {
	addressType, err := DecodeType(address)
	if err != nil {
		return nil, err
	}
	switch addressType {
	case P2Pkh:
		pubKeyHash, _, err := base58.CheckDecode(address)
		if err != nil {
			return nil, err
		}
		return txscript.NewScriptBuilder().
			AddOp(txscript.OP_DUP).
			AddOp(txscript.OP_HASH160).
			AddData(pubKeyHash).
			AddOp(txscript.OP_EQUALVERIFY).
			AddOp(txscript.OP_CHECKSIG).
			Script()
	case P2Sh:
		scriptHash, _, err := base58.CheckDecode(address)
		if err != nil {
			return nil, err
		}
		return txscript.NewScriptBuilder().
			AddOp(txscript.OP_HASH160).
			AddData(scriptHash).
			AddOp(txscript.OP_EQUAL).
			Script()
	case ConfidentialP2Pkh:
		decoded, _, err := base58.CheckDecode(address)
		if err != nil {
			return nil, err
		}
		prefixPlusBlindKeySize := 34
		pubKeyHash := decoded[prefixPlusBlindKeySize:]
		return txscript.NewScriptBuilder().
			AddOp(txscript.OP_DUP).
			AddOp(txscript.OP_HASH160).
			AddData(pubKeyHash).
			AddOp(txscript.OP_EQUALVERIFY).
			AddOp(txscript.OP_CHECKSIG).
			Script()
	case ConfidentialP2Sh:
		decoded, _, err := base58.CheckDecode(address)
		if err != nil {
			return nil, err
		}
		prefixPlusBlindKeySize := 34
		scriptHash := decoded[prefixPlusBlindKeySize:]
		return txscript.NewScriptBuilder().
			AddOp(txscript.OP_HASH160).
			AddData(scriptHash).
			AddOp(txscript.OP_EQUAL).
			Script()
	case P2Wpkh, P2Wsh:
		fromBech32, err := FromBech32(address)
		if err != nil {
			return nil, err
		}
		return txscript.NewScriptBuilder().
			AddOp(txscript.OP_0).
			AddData(fromBech32.Program).
			Script()
	case ConfidentialP2Wpkh, ConfidentialP2Wsh:
		fromBlech32, err := FromBlech32(address)
		if err != nil {
			return nil, err
		}
		return txscript.NewScriptBuilder().
			AddOp(txscript.OP_0).
			AddData(fromBlech32.Program).
			Script()
	default:
		return nil, errors.New("unsupported address type")
	}
}
ToOutputScript creates a new script to pay a transaction output to a the
specified address
package address
import (
	"bytes"
	"errors"
	"fmt"
	"strings"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcutil/base58"
	"github.com/btcsuite/btcutil/bech32"
	"github.com/vulpemventures/go-elements/blech32"
	"github.com/vulpemventures/go-elements/network"
	"golang.org/x/crypto/ripemd160"
)
type Address struct {
	address string
}
const (
	P2Pkh = iota
	P2Sh
	ConfidentialP2Pkh
	ConfidentialP2Sh
	P2Wpkh
	P2Wsh
	ConfidentialP2Wpkh
	ConfidentialP2Wsh
	P2PkhScript      = 1
	P2ShScript       = 2
	P2MultiSigScript = 3
	P2WpkhScript     = 4
	P2WshScript      = 5
)
type Base58 struct {
	Version byte
	Data    []byte
}
type Base58Confidential struct {
	Base58
	Version   byte
	PublicKey []byte
}
type Bech32 struct {
	Prefix  string
	Version byte
	Program []byte
}
type Blech32 struct {
	Prefix    string
	Version   byte
	PublicKey []byte
	Program   []byte
}
type ConfidentialAddress struct {
	Address     string
	BlindingKey []byte
}
func FromBase58(address string) (*Base58, error) {
	decoded, version, err := base58.CheckDecode(address)
	if err != nil {
		return nil, errors.New("Invalid address")
	}
	if len(decoded) < 20 {
		return nil, errors.New(address + " is too short")
	}
	if len(decoded) > 20 {
		return nil, errors.New(address + " is too long")
	}
	return &Base58{version, decoded}, nil
}
func ToBase58(b *Base58) string {
	encoded := base58.CheckEncode(b.Data, b.Version)
	return encoded
}
func FromBech32(address string) (*Bech32, error) {
	oneIndex := strings.LastIndexByte(address, '1')
	if oneIndex <= 1 {
		return nil, errors.New("Invalid Sewgit address")
	}
	hrp := address[:oneIndex+1]
	prefix := hrp[:len(hrp)-1]
	_, data, err := bech32.Decode(address)
	if err != nil {
		return nil, err
	}
	if len(data) < 1 {
		return nil, errors.New("no witness version")
	}
	version := data[0]
	if version > 16 {
		return nil, errors.New("invalid witness version")
	}
	regrouped, err := bech32.ConvertBits(data[1:], 5, 8, false)
	if err != nil {
		return nil, err
	}
	if len(regrouped) < 2 || len(regrouped) > 40 {
		return nil, errors.New("invalid Data Length")
	}
	if version == 0 && len(regrouped) != 20 && len(regrouped) != 32 {
		return nil, errors.New("invalid Data Length for witness ")
	}
	return &Bech32{prefix, version, regrouped}, nil
}
func ToBech32(bc *Bech32) (string, error) {
	converted, err := bech32.ConvertBits(bc.Program, 8, 5, true)
	if err != nil {
		return "", err
	}
	combined := make([]byte, len(converted)+1)
	combined[0] = bc.Version
	copy(combined[1:], converted)
	bech, err := bech32.Encode(bc.Prefix, combined)
	if err != nil {
		return "", err
	}
	return bech, nil
}
func FromBase58Confidential(address string) (*Base58Confidential, error) {
	decoded, version, err := base58.CheckDecode(address)
	if err != nil {
		return nil, errors.New("Invalid address")
	}
	if len(decoded) < 54 {
		return nil, errors.New(address + " is too short")
	}
	if len(decoded) > 54 {
		return nil, errors.New(address + " is too long")
	}
	return &Base58Confidential{
		Base58{
			decoded[0],
			decoded[34:],
		},
		version,
		decoded[1:34],
	}, nil
}
func ToBase58Confidential(b *Base58Confidential) string {
	data := append([]byte{b.Base58.Version}, b.PublicKey...)
	data = append(data, b.Base58.Data...)
	encoded := base58.CheckEncode(data, b.Version)
	return encoded
}
func FromBlech32(address string) (*Blech32, error) {
	oneIndex := strings.LastIndexByte(address, '1')
	if oneIndex <= 1 {
		return nil, errors.New("Invalid Sewgit address")
	}
	hrp := address[:oneIndex+1]
	prefix := hrp[:len(hrp)-1]
	_, data, err := blech32.Decode(address)
	if err != nil {
		return nil, err
	}
	if len(data) < 1 {
		return nil, fmt.Errorf("no witness version")
	}
	version := data[0]
	if version > 16 {
		return nil, fmt.Errorf("invalid witness version: %v", version)
	}
	regrouped, err := blech32.ConvertBits(data[1:], 5, 8, false)
	if err != nil {
		return nil, err
	}
	if len(regrouped) < 2 || len(regrouped) > 40+33 {
		return nil, fmt.Errorf("invalid Data Length")
	}
	if version == 0 && len(regrouped) != 20+33 && len(regrouped) != 32+33 {
		return nil, fmt.Errorf("invalid Data Length for witness "+
			"version 0: %v", len(regrouped))
	}
	return &Blech32{
		prefix,
		version,
		regrouped[:33],
		regrouped[33:],
	}, nil
}
func ToBlech32(bl *Blech32) (string, error) {
	converted, err := blech32.ConvertBits(
		append(bl.PublicKey, bl.Program...),
		8,
		5,
		true,
	)
	if err != nil {
		return "", err
	}
	combined := make([]byte, len(converted)+1)
	combined[0] = bl.Version
	copy(combined[1:], converted)
	blech32Addr, err := blech32.Encode(bl.Prefix, combined)
	if err != nil {
		return "", err
	}
	blech, err := FromBlech32(blech32Addr)
	if err != nil {
		return "", fmt.Errorf("invalid blech32 address: %v", err)
	}
	blechData := append(blech.PublicKey, blech.Program...)
	blData := append(bl.PublicKey, bl.Program...)
	if blech.Version != bl.Version || !bytes.Equal(blechData, blData) {
		return "", fmt.Errorf("invalid segwit address")
	}
	return blech32Addr, nil
}
func FromConfidential(address string) (*ConfidentialAddress, error) {
	net, err := NetworkForAddress(address)
	if err != nil {
		return nil, err
	}
	addressType, err := DecodeType(address)
	if err != nil {
		return nil, err
	}
	switch addressType {
	case ConfidentialP2Pkh, ConfidentialP2Sh:
		fromBase58, err := FromBase58Confidential(address)
		if err != nil {
			return nil, err
		}
		addr := ToBase58(&fromBase58.Base58)
		return &ConfidentialAddress{
			Address:     addr,
			BlindingKey: fromBase58.PublicKey,
		}, nil
	case ConfidentialP2Wpkh, ConfidentialP2Wsh:
		fromBlech32, err := FromBlech32(address)
		if err != nil {
			return nil, err
		}
		addr, err := ToBech32(&Bech32{
			Prefix:  net.Bech32,
			Version: fromBlech32.Version,
			Program: fromBlech32.Program,
		})
		if err != nil {
			return nil, err
		}
		return &ConfidentialAddress{
			Address:     addr,
			BlindingKey: fromBlech32.PublicKey,
		}, nil
	default:
		return nil, errors.New("unknown address type")
	}
}
func ToConfidential(ca *ConfidentialAddress) (string, error) {
	net, err := NetworkForAddress(ca.Address)
	if err != nil {
		return "", err
	}
	if strings.HasPrefix(ca.Address, net.Bech32) {
		b32, _ := FromBech32(ca.Address)
		return ToBlech32(&Blech32{
			Prefix:    net.Blech32,
			Version:   b32.Version,
			Program:   b32.Program,
			PublicKey: ca.BlindingKey,
		})
	}
	b58, _ := FromBase58(ca.Address)
	return ToBase58Confidential(&Base58Confidential{
		*b58,
		net.Confidential,
		ca.BlindingKey,
	}), nil
}
func NetworkForAddress(address string) (*network.Network, error) {
	if strings.HasPrefix(address, network.Liquid.Bech32) ||
		strings.HasPrefix(address, network.Liquid.Blech32) {
		return &network.Liquid, nil
	}
	if strings.HasPrefix(address, network.Regtest.Bech32) ||
		strings.HasPrefix(address, network.Regtest.Blech32) {
		return &network.Regtest, nil
	}
	if strings.HasPrefix(address, network.Testnet.Bech32) ||
		strings.HasPrefix(address, network.Testnet.Blech32) {
		return &network.Testnet, nil
	}
	_, prefix, err := base58.CheckDecode(address)
	if err != nil {
		return nil, err
	}
	if prefix == network.Liquid.Confidential ||
		prefix == network.Liquid.PubKeyHash ||
		prefix == network.Liquid.ScriptHash {
		return &network.Liquid, nil
	}
	if prefix == network.Regtest.Confidential ||
		prefix == network.Regtest.PubKeyHash ||
		prefix == network.Regtest.ScriptHash {
		return &network.Regtest, nil
	}
	if prefix == network.Testnet.Confidential ||
		prefix == network.Testnet.PubKeyHash ||
		prefix == network.Testnet.ScriptHash {
		return &network.Testnet, nil
	}
	return nil, errors.New("unknown prefix for address")
}