@@ -9,8 +9,11 @@ import (
99 "github.com/btcsuite/btcd/btcutil"
1010 "github.com/lightninglabs/lndclient"
1111 "github.com/lightninglabs/loop/swap"
12+ "github.com/lightningnetwork/lnd/lnwallet/chainfee"
1213 "github.com/lightningnetwork/lnd/lnwire"
1314 "github.com/lightningnetwork/lnd/routing/route"
15+
16+ clientrpc "github.com/lightninglabs/loop/looprpc"
1417)
1518
1619var (
@@ -271,3 +274,150 @@ func cloneParameters(params Parameters) Parameters {
271274
272275 return paramCopy
273276}
277+
278+ // rpcToFee converts the values provided over rpc to a fee limit interface,
279+ // failing if an inconsistent set of fields are set.
280+ func rpcToFee (req * clientrpc.LiquidityParameters ) (FeeLimit , error ) {
281+ // Check which fee limit type we have values set for. If any fields
282+ // relevant to our individual categories are set, we count that type
283+ // as set.
284+ isFeePPM := req .FeePpm != 0
285+ isCategories := req .MaxSwapFeePpm != 0 || req .MaxRoutingFeePpm != 0 ||
286+ req .MaxPrepayRoutingFeePpm != 0 || req .MaxMinerFeeSat != 0 ||
287+ req .MaxPrepaySat != 0 || req .SweepFeeRateSatPerVbyte != 0
288+
289+ switch {
290+ case isFeePPM && isCategories :
291+ return nil , errors .New ("set either fee ppm, or individual " +
292+ "fee categories" )
293+ case isFeePPM :
294+ return NewFeePortion (req .FeePpm ), nil
295+
296+ case isCategories :
297+ satPerKVbyte := chainfee .SatPerKVByte (
298+ req .SweepFeeRateSatPerVbyte * 1000 ,
299+ )
300+
301+ return NewFeeCategoryLimit (
302+ req .MaxSwapFeePpm ,
303+ req .MaxRoutingFeePpm ,
304+ req .MaxPrepayRoutingFeePpm ,
305+ btcutil .Amount (req .MaxMinerFeeSat ),
306+ btcutil .Amount (req .MaxPrepaySat ),
307+ satPerKVbyte .FeePerKWeight (),
308+ ), nil
309+
310+ default :
311+ return nil , errors .New ("no fee categories set" )
312+ }
313+ }
314+
315+ // rpcToRule switches on rpc rule type to convert to our rule interface.
316+ func rpcToRule (rule * clientrpc.LiquidityRule ) (* SwapRule , error ) {
317+ swapType := swap .TypeOut
318+ if rule .SwapType == clientrpc .SwapType_LOOP_IN {
319+ swapType = swap .TypeIn
320+ }
321+
322+ switch rule .Type {
323+ case clientrpc .LiquidityRuleType_UNKNOWN :
324+ return nil , fmt .Errorf ("rule type field must be set" )
325+
326+ case clientrpc .LiquidityRuleType_THRESHOLD :
327+ return & SwapRule {
328+ ThresholdRule : NewThresholdRule (
329+ int (rule .IncomingThreshold ),
330+ int (rule .OutgoingThreshold ),
331+ ),
332+ Type : swapType ,
333+ }, nil
334+
335+ default :
336+ return nil , fmt .Errorf ("unknown rule: %T" , rule )
337+ }
338+ }
339+
340+ // rpcToParameters takes a `LiquidityParameters` and creates a `Parameters`
341+ // from it.
342+ func rpcToParameters (req * clientrpc.LiquidityParameters ) (* Parameters ,
343+ error ) {
344+
345+ feeLimit , err := rpcToFee (req )
346+ if err != nil {
347+ return nil , err
348+ }
349+
350+ params := & Parameters {
351+ FeeLimit : feeLimit ,
352+ SweepConfTarget : req .SweepConfTarget ,
353+ FailureBackOff : time .Duration (req .FailureBackoffSec ) *
354+ time .Second ,
355+ Autoloop : req .Autoloop ,
356+ AutoFeeBudget : btcutil .Amount (req .AutoloopBudgetSat ),
357+ MaxAutoInFlight : int (req .AutoMaxInFlight ),
358+ ChannelRules : make (
359+ map [lnwire.ShortChannelID ]* SwapRule ,
360+ ),
361+ PeerRules : make (
362+ map [route.Vertex ]* SwapRule ,
363+ ),
364+ ClientRestrictions : Restrictions {
365+ Minimum : btcutil .Amount (req .MinSwapAmount ),
366+ Maximum : btcutil .Amount (req .MaxSwapAmount ),
367+ },
368+ HtlcConfTarget : req .HtlcConfTarget ,
369+ }
370+
371+ // Zero unix time is different to zero golang time.
372+ if req .AutoloopBudgetStartSec != 0 {
373+ params .AutoFeeStartDate = time .Unix (
374+ int64 (req .AutoloopBudgetStartSec ), 0 ,
375+ )
376+ }
377+
378+ for _ , rule := range req .Rules {
379+ peerRule := rule .Pubkey != nil
380+ chanRule := rule .ChannelId != 0
381+
382+ liquidityRule , err := rpcToRule (rule )
383+ if err != nil {
384+ return nil , err
385+ }
386+
387+ switch {
388+ case peerRule && chanRule :
389+ return nil , fmt .Errorf ("cannot set channel: %v and " +
390+ "peer: %v fields in rule" , rule .ChannelId ,
391+ rule .Pubkey )
392+
393+ case peerRule :
394+ pubkey , err := route .NewVertexFromBytes (rule .Pubkey )
395+ if err != nil {
396+ return nil , err
397+ }
398+
399+ if _ , ok := params .PeerRules [pubkey ]; ok {
400+ return nil , fmt .Errorf ("multiple rules set " +
401+ "for peer: %v" , pubkey )
402+ }
403+
404+ params .PeerRules [pubkey ] = liquidityRule
405+
406+ case chanRule :
407+ shortID := lnwire .NewShortChanIDFromInt (rule .ChannelId )
408+
409+ if _ , ok := params .ChannelRules [shortID ]; ok {
410+ return nil , fmt .Errorf ("multiple rules set " +
411+ "for channel: %v" , shortID )
412+ }
413+
414+ params .ChannelRules [shortID ] = liquidityRule
415+
416+ default :
417+ return nil , errors .New ("please set channel id or " +
418+ "pubkey for rule" )
419+ }
420+ }
421+
422+ return params , nil
423+ }
0 commit comments