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

     1  package lnrpc
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	"sort"
     7  
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/wire"
    10  	"github.com/decred/dcrlnd/lnwallet"
    11  )
    12  
    13  const (
    14  	// RegisterRPCMiddlewareURI is the full RPC method URI for the
    15  	// middleware registration call. This is declared here rather than where
    16  	// it's mainly used to avoid circular package dependencies.
    17  	RegisterRPCMiddlewareURI = "/lnrpc.Lightning/RegisterRPCMiddleware"
    18  )
    19  
    20  // RPCTransaction returns a rpc transaction.
    21  func RPCTransaction(tx *lnwallet.TransactionDetail) *Transaction {
    22  	var destAddresses []string
    23  	for _, destAddress := range tx.DestAddresses {
    24  		destAddresses = append(destAddresses, destAddress.String())
    25  	}
    26  
    27  	// We also get unconfirmed transactions, so BlockHash can be nil.
    28  	blockHash := ""
    29  	if tx.BlockHash != nil {
    30  		blockHash = tx.BlockHash.String()
    31  	}
    32  
    33  	return &Transaction{
    34  		TxHash:           tx.Hash.String(),
    35  		Amount:           int64(tx.Value),
    36  		NumConfirmations: tx.NumConfirmations,
    37  		BlockHash:        blockHash,
    38  		BlockHeight:      tx.BlockHeight,
    39  		TimeStamp:        tx.Timestamp,
    40  		TotalFees:        tx.TotalFees,
    41  		DestAddresses:    destAddresses,
    42  		RawTxHex:         hex.EncodeToString(tx.RawTx),
    43  		Label:            tx.Label,
    44  	}
    45  }
    46  
    47  // RPCTransactionDetails returns a set of rpc transaction details.
    48  func RPCTransactionDetails(txns []*lnwallet.TransactionDetail) *TransactionDetails {
    49  	txDetails := &TransactionDetails{
    50  		Transactions: make([]*Transaction, len(txns)),
    51  	}
    52  
    53  	for i, tx := range txns {
    54  		txDetails.Transactions[i] = RPCTransaction(tx)
    55  	}
    56  
    57  	// Sort transactions by number of confirmations rather than height so
    58  	// that unconfirmed transactions (height =0; confirmations =-1) will
    59  	// follow the most recently set of confirmed transactions. If we sort
    60  	// by height, unconfirmed transactions will follow our oldest
    61  	// transactions, because they have lower block heights.
    62  	sort.Slice(txDetails.Transactions, func(i, j int) bool {
    63  		return txDetails.Transactions[i].NumConfirmations <
    64  			txDetails.Transactions[j].NumConfirmations
    65  	})
    66  
    67  	return txDetails
    68  }
    69  
    70  // ExtractMinConfs extracts the minimum number of confirmations that each
    71  // output used to fund a transaction should satisfy.
    72  func ExtractMinConfs(minConfs int32, spendUnconfirmed bool) (int32, error) {
    73  	switch {
    74  	// Ensure that the MinConfs parameter is non-negative.
    75  	case minConfs < 0:
    76  		return 0, errors.New("minimum number of confirmations must " +
    77  			"be a non-negative number")
    78  
    79  	// The transaction should not be funded with unconfirmed outputs
    80  	// unless explicitly specified by SpendUnconfirmed. We do this to
    81  	// provide sane defaults to the OpenChannel RPC, as otherwise, if the
    82  	// MinConfs field isn't explicitly set by the caller, we'll use
    83  	// unconfirmed outputs without the caller being aware.
    84  	case minConfs == 0 && !spendUnconfirmed:
    85  		return 1, nil
    86  
    87  	// In the event that the caller set MinConfs > 0 and SpendUnconfirmed to
    88  	// true, we'll return an error to indicate the conflict.
    89  	case minConfs > 0 && spendUnconfirmed:
    90  		return 0, errors.New("SpendUnconfirmed set to true with " +
    91  			"MinConfs > 0")
    92  
    93  	// The funding transaction of the new channel to be created can be
    94  	// funded with unconfirmed outputs.
    95  	case spendUnconfirmed:
    96  		return 0, nil
    97  
    98  	// If none of the above cases matched, we'll return the value set
    99  	// explicitly by the caller.
   100  	default:
   101  		return minConfs, nil
   102  	}
   103  }
   104  
   105  // OutpointToChanPoint transforms a standard wire outpoint (that represents a
   106  // channel id) into a ChannelPoint.
   107  func OutpointToChanPoint(out *wire.OutPoint) *ChannelPoint {
   108  	return &ChannelPoint{
   109  		FundingTxid: &ChannelPoint_FundingTxidBytes{
   110  			FundingTxidBytes: out.Hash[:],
   111  		},
   112  		OutputIndex: out.Index,
   113  	}
   114  }
   115  
   116  // GetChanPointFundingTxid returns the given channel point's funding txid in
   117  // raw bytes.
   118  func GetChanPointFundingTxid(chanPoint *ChannelPoint) (*chainhash.Hash, error) {
   119  	var txid []byte
   120  
   121  	// A channel point's funding txid can be get/set as a byte slice or a
   122  	// string. In the case it is a string, decode it.
   123  	switch chanPoint.GetFundingTxid().(type) {
   124  	case *ChannelPoint_FundingTxidBytes:
   125  		txid = chanPoint.GetFundingTxidBytes()
   126  	case *ChannelPoint_FundingTxidStr:
   127  		s := chanPoint.GetFundingTxidStr()
   128  		h, err := chainhash.NewHashFromStr(s)
   129  		if err != nil {
   130  			return nil, err
   131  		}
   132  
   133  		txid = h[:]
   134  	}
   135  
   136  	return chainhash.NewHash(txid)
   137  }