github.com/decred/dcrlnd@v0.7.6/lnrpc/marshall_utils.go (about)

     1  package lnrpc
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	fmt "fmt"
     7  
     8  	"github.com/decred/dcrd/chaincfg/v3"
     9  	"github.com/decred/dcrd/dcrutil/v4"
    10  	"github.com/decred/dcrd/txscript/v4/stdscript"
    11  	"github.com/decred/dcrlnd/lnwallet"
    12  	"github.com/decred/dcrlnd/lnwire"
    13  )
    14  
    15  var (
    16  	// ErrAtomsMAtomsMutualExclusive is returned when both an atom and an
    17  	// matom amount are set.
    18  	ErrAtomMAtomMutualExclusive = errors.New(
    19  		"atom and matom arguments are mutually exclusive",
    20  	)
    21  )
    22  
    23  // CalculateFeeLimit returns the fee limit in millisatoshis. If a percentage
    24  // based fee limit has been requested, we'll factor in the ratio provided with
    25  // the amount of the payment.
    26  func CalculateFeeLimit(feeLimit *FeeLimit,
    27  	amount lnwire.MilliAtom) lnwire.MilliAtom {
    28  
    29  	switch feeLimit.GetLimit().(type) {
    30  
    31  	case *FeeLimit_Fixed:
    32  		return lnwire.NewMAtomsFromAtoms(
    33  			dcrutil.Amount(feeLimit.GetFixed()),
    34  		)
    35  
    36  	case *FeeLimit_FixedMAtoms:
    37  		return lnwire.MilliAtom(feeLimit.GetFixedMAtoms())
    38  
    39  	case *FeeLimit_Percent:
    40  		return amount * lnwire.MilliAtom(feeLimit.GetPercent()) / 100
    41  
    42  	default:
    43  		// Fall back to a sane default value that is based on the amount
    44  		// itself.
    45  		return lnwallet.DefaultRoutingFeeLimitForAmount(amount)
    46  	}
    47  }
    48  
    49  // UnmarshallAmt returns a strong msat type for a atom/matom pair of rpc
    50  // fields.
    51  func UnmarshallAmt(amtAtom, amtMAtom int64) (lnwire.MilliAtom, error) {
    52  	if amtAtom != 0 && amtMAtom != 0 {
    53  		return 0, ErrAtomMAtomMutualExclusive
    54  	}
    55  
    56  	if amtAtom != 0 {
    57  		return lnwire.NewMAtomsFromAtoms(dcrutil.Amount(amtAtom)), nil
    58  	}
    59  
    60  	return lnwire.MilliAtom(amtMAtom), nil
    61  }
    62  
    63  // ParseConfs validates the minimum and maximum confirmation arguments of a
    64  // ListUnspent request.
    65  func ParseConfs(min, max int32) (int32, int32, error) {
    66  	switch {
    67  	// Ensure that the user didn't attempt to specify a negative number of
    68  	// confirmations, as that isn't possible.
    69  	case min < 0:
    70  		return 0, 0, fmt.Errorf("min confirmations must be >= 0")
    71  
    72  	// We'll also ensure that the min number of confs is strictly less than
    73  	// or equal to the max number of confs for sanity.
    74  	case min > max:
    75  		return 0, 0, fmt.Errorf("max confirmations must be >= min " +
    76  			"confirmations")
    77  
    78  	default:
    79  		return min, max, nil
    80  	}
    81  }
    82  
    83  // MarshalUtxos translates a []*lnwallet.Utxo into a []*lnrpc.Utxo.
    84  func MarshalUtxos(utxos []*lnwallet.Utxo, activeNetParams *chaincfg.Params) (
    85  	[]*Utxo, error) {
    86  
    87  	// TODO(decred): this needs to come from the utxo itself.
    88  	const scriptVersion uint16 = 0
    89  
    90  	res := make([]*Utxo, 0, len(utxos))
    91  	for _, utxo := range utxos {
    92  		// Translate lnwallet address type to the proper gRPC proto
    93  		// address type.
    94  		var addrType AddressType
    95  		switch utxo.AddressType {
    96  
    97  		case lnwallet.WitnessPubKey:
    98  			addrType = AddressType_WITNESS_PUBKEY_HASH
    99  
   100  		case lnwallet.NestedWitnessPubKey:
   101  			addrType = AddressType_NESTED_PUBKEY_HASH
   102  
   103  		case lnwallet.PubKeyHash:
   104  			addrType = AddressType_PUBKEY_HASH
   105  
   106  		case lnwallet.ScriptHash:
   107  			addrType = AddressType_SCRIPT_HASH
   108  
   109  		case lnwallet.UnknownAddressType:
   110  			continue
   111  
   112  		default:
   113  			return nil, fmt.Errorf("invalid utxo address type")
   114  		}
   115  
   116  		// Now that we know we have a proper mapping to an address,
   117  		// we'll convert the regular outpoint to an lnrpc variant.
   118  		outpoint := &OutPoint{
   119  			TxidBytes:   utxo.OutPoint.Hash[:],
   120  			TxidStr:     utxo.OutPoint.Hash.String(),
   121  			OutputIndex: utxo.OutPoint.Index,
   122  		}
   123  
   124  		utxoResp := Utxo{
   125  			AddressType:   addrType,
   126  			AmountAtoms:   int64(utxo.Value),
   127  			PkScript:      hex.EncodeToString(utxo.PkScript),
   128  			Outpoint:      outpoint,
   129  			Confirmations: utxo.Confirmations,
   130  		}
   131  
   132  		// Finally, we'll attempt to extract the raw address from the
   133  		// script so we can display a human friendly address to the end
   134  		// user.
   135  		_, outAddresses := stdscript.ExtractAddrs(
   136  			scriptVersion, utxo.PkScript, activeNetParams,
   137  		)
   138  
   139  		// If we can't properly locate a single address, then this was
   140  		// an error in our mapping, and we'll return an error back to
   141  		// the user.
   142  		if len(outAddresses) != 1 {
   143  			return nil, fmt.Errorf("an output was unexpectedly " +
   144  				"multisig")
   145  		}
   146  		utxoResp.Address = outAddresses[0].String()
   147  
   148  		res = append(res, &utxoResp)
   149  	}
   150  
   151  	return res, nil
   152  }