Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 28 additions & 22 deletions glightning/lightning.go
Original file line number Diff line number Diff line change
Expand Up @@ -2563,38 +2563,44 @@ type FeeRateEstimate struct {
Style FeeRateStyle
Details *FeeRateDetails
OnchainEstimate *OnchainEstimate `json:"onchain_fee_estimates"`
Warning string `json:"warning"`
Warning string `json:"warning_missing_feerates,omitempty"`
}

type OnchainEstimate struct {
OpeningChannelSatoshis uint64 `json:"opening_channel_satoshis"`
MutualCloseSatoshis uint64 `json:"mutual_close_satoshis"`
UnilateralCloseSatoshis uint64 `json:"unilateral_close_satoshis"`
HtlcTimeoutSatoshis uint64 `json:"htlc_timeout_satoshis"`
HtlcSuccessSatoshis uint64 `json:"htlc_success_satoshis"`
OpeningChannelSatoshis uint64 `json:"opening_channel_satoshis"`
MutualCloseSatoshis uint64 `json:"mutual_close_satoshis"`
UnilateralCloseSatoshis uint64 `json:"unilateral_close_satoshis"`
UnilateralCloseNonanchorSatoshis uint64 `json:"unilateral_close_nonanchor_satoshis,omitempty"`
HtlcTimeoutSatoshis uint64 `json:"htlc_timeout_satoshis"`
HtlcSuccessSatoshis uint64 `json:"htlc_success_satoshis"`
}

type FeeRateEstimateEntry struct {
Blockcount uint32 `json:"blockcount"`
FeeRate uint32 `json:"feerate"`
SmoothedFeeRate uint32 `json:"smoothed_feerate"`
}

type FeeRateDetails struct {
Urgent int `json:"urgent"`
Normal int `json:"normal"`
Slow int `json:"slow"`
MinAcceptable int `json:"min_acceptable"`
MaxAcceptable int `json:"max_acceptable"`
Opening uint `json:"opening"`
MutualClose uint `json:"mutual_close"`
UnilateralClose uint `json:"unilateral_close"`
DelayedToUs uint `json:"delayed_to_us"`
HtlcResolution uint `json:"htlc_resolution"`
Penalty uint `json:"penalty"`
MinAcceptable uint32 `json:"min_acceptable"`
MaxAcceptable uint32 `json:"max_acceptable"`
Floor uint32 `json:"floor,omitempty"`
Estimates []FeeRateEstimateEntry `json:"estimates,omitempty"`
Opening uint32 `json:"opening,omitempty"`
MutualClose uint32 `json:"mutual_close,omitempty"`
UnilateralClose uint32 `json:"unilateral_close,omitempty"`
UnilateralAnchorClose uint32 `json:"unilateral_anchor_close,omitempty"`
Penalty uint32 `json:"penalty,omitempty"`
Splice uint32 `json:"splice,omitempty"`
}

// Return feerate estimates, either satoshi-per-kw or satoshi-per-kb {style}
func (l *Lightning) FeeRates(style FeeRateStyle) (*FeeRateEstimate, error) {
var result struct {
PerKw *FeeRateDetails `json:"perkw"`
PerKb *FeeRateDetails `json:"perkb"`
OnchainEstimate *OnchainEstimate `json:"onchain_fee_estimates"`
Warning string `json:"warning"`
PerKw *FeeRateDetails `json:"perkw"`
PerKb *FeeRateDetails `json:"perkb"`
OnchainEstimate *OnchainEstimate `json:"onchain_fee_estimates"`
WarningMissingFeerates string `json:"warning_missing_feerates"`
}
err := l.client.Request(&FeeRatesRequest{style.String()}, &result)
if err != nil {
Expand All @@ -2613,7 +2619,7 @@ func (l *Lightning) FeeRates(style FeeRateStyle) (*FeeRateEstimate, error) {
Style: style,
Details: details,
OnchainEstimate: result.OnchainEstimate,
Warning: result.Warning,
Warning: result.WarningMissingFeerates,
}, nil
}

Expand Down
61 changes: 35 additions & 26 deletions glightning/lightning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2041,20 +2041,23 @@ func TestFeeRate(t *testing.T) {

// what i expect the lightning rpc to generate
expectedRequest := "{\"jsonrpc\":\"2.0\",\"method\":\"feerates\",\"params\":{\"style\":\"perkb\"},\"id\":1}"
// json the server will respond with
// json the server will respond with (CLN v24.05+ format)
reply := wrapResult(1, `{
"perkb": {
"min_acceptable": 1012,
"max_acceptable": 10000,
"floor": 1012,
"estimates": [
{"blockcount": 6, "feerate": 1012, "smoothed_feerate": 1012},
{"blockcount": 12, "feerate": 1012, "smoothed_feerate": 1012},
{"blockcount": 100, "feerate": 2024, "smoothed_feerate": 2024}
],
"opening": 1012,
"mutual_close": 1012,
"unilateral_close": 1012,
"delayed_to_us": 1012,
"htlc_resolution": 1012,
"unilateral_anchor_close": 1012,
"penalty": 1012,
"min_acceptable": 1012,
"max_acceptable": 10000,
"urgent": 1012,
"normal": 1012,
"slow": 2024
"splice": 1012
},
"onchain_fee_estimates": {
"opening_channel_satoshis": 177,
Expand All @@ -2074,17 +2077,20 @@ func TestFeeRate(t *testing.T) {
assert.Equal(t, &glightning.FeeRateEstimate{
Style: glightning.PerKb,
Details: &glightning.FeeRateDetails{
Urgent: 1012,
Normal: 1012,
Slow: 2024,
MinAcceptable: 1012,
MaxAcceptable: 10000,
Opening: 1012,
MutualClose: 1012,
UnilateralClose: 1012,
DelayedToUs: 1012,
HtlcResolution: 1012,
Penalty: 1012,
MinAcceptable: 1012,
MaxAcceptable: 10000,
Floor: 1012,
Estimates: []glightning.FeeRateEstimateEntry{
{Blockcount: 6, FeeRate: 1012, SmoothedFeeRate: 1012},
{Blockcount: 12, FeeRate: 1012, SmoothedFeeRate: 1012},
{Blockcount: 100, FeeRate: 2024, SmoothedFeeRate: 2024},
},
Opening: 1012,
MutualClose: 1012,
UnilateralClose: 1012,
UnilateralAnchorClose: 1012,
Penalty: 1012,
Splice: 1012,
},
OnchainEstimate: &glightning.OnchainEstimate{
OpeningChannelSatoshis: 177,
Expand All @@ -2093,12 +2099,11 @@ func TestFeeRate(t *testing.T) {
HtlcTimeoutSatoshis: 167,
HtlcSuccessSatoshis: 177,
},
Warning: "",
}, rates)

expectedRequest = "{\"jsonrpc\":\"2.0\",\"method\":\"feerates\",\"params\":{\"style\":\"perkw\"},\"id\":2}"

reply = "{ \"jsonrpc\":\"2.0\", \"id\":2,\"result\":{\"perkw\": { \"urgent\": 832, \"normal\": 253, \"slow\": 253, \"min_acceptable\": 253, \"max_acceptable\": 8320 }, \"onchain_fee_estimates\": { \"opening_channel_satoshis\": 177, \"mutual_close_satoshis\": 170, \"unilateral_close_satoshis\": 497 }}}"
reply = wrapResult(2, `{"perkw": {"min_acceptable": 253, "max_acceptable": 8320, "floor": 253, "estimates": [{"blockcount": 6, "feerate": 832, "smoothed_feerate": 832}, {"blockcount": 12, "feerate": 253, "smoothed_feerate": 253}], "opening": 253, "mutual_close": 253, "unilateral_close": 253}, "onchain_fee_estimates": {"opening_channel_satoshis": 177, "mutual_close_satoshis": 170, "unilateral_close_satoshis": 497}}`)

// queue request & response
go runServerSide(t, expectedRequest, reply, replyQ, requestQ)
Expand All @@ -2109,18 +2114,22 @@ func TestFeeRate(t *testing.T) {
assert.Equal(t, &glightning.FeeRateEstimate{
Style: glightning.PerKw,
Details: &glightning.FeeRateDetails{
Urgent: 832,
Normal: 253,
Slow: 253,
MinAcceptable: 253,
MaxAcceptable: 8320,
Floor: 253,
Estimates: []glightning.FeeRateEstimateEntry{
{Blockcount: 6, FeeRate: 832, SmoothedFeeRate: 832},
{Blockcount: 12, FeeRate: 253, SmoothedFeeRate: 253},
},
Opening: 253,
MutualClose: 253,
UnilateralClose: 253,
},
OnchainEstimate: &glightning.OnchainEstimate{
OpeningChannelSatoshis: 177,
MutualCloseSatoshis: 170,
UnilateralCloseSatoshis: 497,
},
Warning: "",
}, rates)
}

Expand Down Expand Up @@ -2384,7 +2393,7 @@ func TestSetChannelFee(t *testing.T) {

func TestLimitedFeeRates(t *testing.T) {
request := "{\"jsonrpc\":\"2.0\",\"method\":\"feerates\",\"params\":{\"style\":\"perkw\"},\"id\":1}"
reply := wrapResult(1, `{ "perkw": { "min_acceptable": 253, "max_acceptable": 4294967295 }, "warning": "Some fee estimates unavailable: bitcoind startup?" } `)
reply := wrapResult(1, `{ "perkw": { "min_acceptable": 253, "max_acceptable": 4294967295 }, "warning_missing_feerates": "Some fee estimates unavailable: bitcoind startup?" } `)

lightning, requestQ, replyQ := startupServer(t)
go runServerSide(t, request, reply, replyQ, requestQ)
Expand Down