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 }