Skip to content

Commit 859ba45

Browse files
authored
Merge pull request #1119 from starius/static-autoloop
autoloop: support static loop-ins
2 parents 72a38c5 + 83534a2 commit 859ba45

52 files changed

Lines changed: 4285 additions & 374 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmd/loop/liquidity.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,12 @@ var setParamsCommand = &cli.Command{
340340
Usage: "the confirmation target for loop in on-chain " +
341341
"htlcs.",
342342
},
343+
&cli.StringFlag{
344+
Name: "loopinsource",
345+
Usage: "the loop-in source to use for autoloop rules: " +
346+
"wallet or static-address. Static-address " +
347+
"requires loopd --experimental.",
348+
},
343349
&cli.BoolFlag{
344350
Name: "easyautoloop",
345351
Usage: "set to true to enable easy autoloop, which " +
@@ -555,6 +561,25 @@ func setParams(ctx context.Context, cmd *cli.Command) error {
555561
flagSet = true
556562
}
557563

564+
if cmd.IsSet("loopinsource") {
565+
switch cmd.String("loopinsource") {
566+
case "wallet":
567+
params.LoopInSource =
568+
looprpc.LoopInSource_LOOP_IN_SOURCE_WALLET
569+
570+
case "static-address", "static_address", "static":
571+
params.LoopInSource =
572+
looprpc.LoopInSource_LOOP_IN_SOURCE_STATIC_ADDRESS
573+
574+
default:
575+
return fmt.Errorf("unknown loopinsource value %q "+
576+
"(use \"wallet\" or \"static-address\")",
577+
cmd.String("loopinsource"))
578+
}
579+
580+
flagSet = true
581+
}
582+
558583
// If we are setting easy autoloop parameters, we need to ensure that
559584
// the asset ID is set, and that we have a valid entry in our params
560585
// map.

cmd/loop/session_fixture_update_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ func writeSessionFilePath(path string, fixture sessionFile) error {
8585
defer file.Close()
8686

8787
encoder := json.NewEncoder(file)
88+
encoder.SetEscapeHTML(false)
8889
encoder.SetIndent("", " ")
8990

9091
return encoder.Encode(fixture)
@@ -152,7 +153,7 @@ func rewriteSessionFixture(fixture sessionFile,
152153
func rewriteExitEventRunError(events []sessionEvent, runError *string,
153154
changed bool) ([]sessionEvent, bool, error) {
154155

155-
data, err := json.Marshal(exitPayload{
156+
data, err := marshalSessionJSON(exitPayload{
156157
RunError: cloneOptionalString(runError),
157158
})
158159
if err != nil {
@@ -338,7 +339,7 @@ func buildReplacementTextEvents(events []sessionEvent, indices []int,
338339

339340
replacements := make([]sessionEvent, 0, len(chunks))
340341
for i, chunk := range chunks {
341-
data, err := json.Marshal(newTextPayload(chunk))
342+
data, err := marshalSessionJSON(newTextPayload(chunk))
342343
if err != nil {
343344
return nil, err
344345
}
@@ -571,7 +572,7 @@ func TestRewriteSessionFixtureSkipsNormalizedTimestampNoise(t *testing.T) {
571572
func textEvent(t *testing.T, timeMS int64, kind, text string) sessionEvent {
572573
t.Helper()
573574

574-
data, err := json.Marshal(newTextPayload(text))
575+
data, err := marshalSessionJSON(newTextPayload(text))
575576
require.NoError(t, err)
576577

577578
return sessionEvent{
@@ -585,7 +586,7 @@ func textEvent(t *testing.T, timeMS int64, kind, text string) sessionEvent {
585586
func exitEvent(t *testing.T, timeMS int64, runError *string) sessionEvent {
586587
t.Helper()
587588

588-
data, err := json.Marshal(exitPayload{
589+
data, err := marshalSessionJSON(exitPayload{
589590
RunError: cloneOptionalString(runError),
590591
})
591592
require.NoError(t, err)

cmd/loop/session_recorder.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/json"
67
"errors"
@@ -48,6 +49,20 @@ var grpcMarshalOptions = protojson.MarshalOptions{
4849
EmitUnpopulated: true,
4950
}
5051

52+
// marshalSessionJSON encodes nested session payloads without HTML escaping so
53+
// recorded fixture strings stay byte-for-byte close to the CLI text.
54+
func marshalSessionJSON(value any) ([]byte, error) {
55+
var buf bytes.Buffer
56+
57+
encoder := json.NewEncoder(&buf)
58+
encoder.SetEscapeHTML(false)
59+
if err := encoder.Encode(value); err != nil {
60+
return nil, err
61+
}
62+
63+
return bytes.TrimSuffix(buf.Bytes(), []byte("\n")), nil
64+
}
65+
5166
// sessionRecorder captures CLI IO and gRPC traffic for replay.
5267
type sessionRecorder struct {
5368
mu sync.Mutex
@@ -80,9 +95,9 @@ type sessionMetadata struct {
8095
Args []string `json:"args"`
8196
Env map[string]string `json:"env"`
8297
Version string `json:"version"`
83-
ClockStartUnix int64 `json:"clock_start_unix"`
8498
RunError *string `json:"run_error,omitempty"`
8599
Duration *time.Duration `json:"duration,omitempty"`
100+
ClockStartUnix int64 `json:"clock_start_unix"`
86101
}
87102

88103
// sessionEvent records a single timestamped payload entry.
@@ -262,7 +277,7 @@ func ensureSessionBaseDir(baseDir string) error {
262277

263278
// logEvent records a new event with the elapsed timestamp.
264279
func (r *sessionRecorder) logEvent(kind string, payload any) {
265-
data, err := json.Marshal(payload)
280+
data, err := marshalSessionJSON(payload)
266281
if err != nil {
267282
r.mu.Lock()
268283
if r.eventErr == nil {
@@ -434,6 +449,7 @@ func (r *sessionRecorder) finalize(runErr error) error {
434449
defer file.Close()
435450

436451
encoder := json.NewEncoder(file)
452+
encoder.SetEscapeHTML(false)
437453
encoder.SetIndent("", " ")
438454
if err := encoder.Encode(fileContent); err != nil {
439455
finalizeErr = errors.Join(err, eventErr, hookErr)
@@ -563,7 +579,7 @@ func (r *sessionRecorder) logGRPCMessage(method, event string, msg any,
563579
payload.Payload = data
564580
}
565581
} else {
566-
data, err := json.Marshal(msg)
582+
data, err := marshalSessionJSON(msg)
567583
if err == nil {
568584
payload.Payload = data
569585
}

cmd/loop/testdata/sessions/AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Base URL: `http://127.0.0.1:12345`
7070
| `misc/` | `loop terms` |
7171
| `quote/` | `loop quote out` (success + verbose), `loop quote in` (help + verbose), `loop quote out` (help), `loop quote in` (deposit_outpoint success), `loop quote in` (positional + last_hop) |
7272
| `static/` | `loop static withdraw` (no selection error), `loop static withdraw` (invalid utxo), `loop static withdraw` (all success), `loop static withdraw` (utxo + dest_addr success), `loop static listwithdrawals`, `loop static listswaps` |
73+
| `static-autoloop/` | `loop setparams --loopinsource static-address` (success + no-experimental error), `loop getparams` (static-address loop-in source), `loop suggestswaps` (static loop-in suggestion) |
7374
| `static-loop-in/` | `loop static new`, `loop static` (help), `loop static listunspent` (incl alias), `loop static listdeposits`, `loop static summary`, `loop static in` (multiple args/flags cases), `loop static in` (duplicate outpoints), `loop static in` (positional low amount error), `loop static in` (positional + last_hop + payment_timeout), `loop static in` (all cancel) |
7475
| `static-filters/` | `loop static listdeposits --filter ...` for each state (deposited/withdrawing/withdrawn/looping_in/looped_in/publish_expired_deposit/sweep_htlc_timeout/htlc_timeout_swept/wait_for_expiry_sweep/expired/failed) |
7576
| `swaps/` | `loop listswaps` (success + conflicting filters + loop_out_only filters + loop_in_only), `loop swapinfo` (success + invalid id + id flag errors), `loop abandonswap` (help + invalid id + success) |

cmd/loop/testdata/sessions/liquidity/01_loop-getparams.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@
5858
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
5959
"easy_asset_params": {},
6060
"fast_swap_publication": true,
61-
"easy_autoloop_excluded_peers": []
61+
"easy_autoloop_excluded_peers": [],
62+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
6263
}
6364
}
6465
},
@@ -85,6 +86,7 @@
8586
" \"fast_swap_publication\": true,\n",
8687
" \"fee_ppm\": \"20000\",\n",
8788
" \"htlc_conf_target\": 6,\n",
89+
" \"loop_in_source\": \"LOOP_IN_SOURCE_WALLET\",\n",
8890
" \"max_miner_fee_sat\": \"0\",\n",
8991
" \"max_prepay_routing_fee_ppm\": \"0\",\n",
9092
" \"max_prepay_sat\": \"0\",\n",

cmd/loop/testdata/sessions/liquidity/02_loop-setparams-no-flags.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@
6868
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
6969
"easy_asset_params": {},
7070
"fast_swap_publication": true,
71-
"easy_autoloop_excluded_peers": []
71+
"easy_autoloop_excluded_peers": [],
72+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
7273
}
7374
}
7475
},

cmd/loop/testdata/sessions/liquidity/03_loop-setparams-feepercent.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
6161
"easy_asset_params": {},
6262
"fast_swap_publication": true,
63-
"easy_autoloop_excluded_peers": []
63+
"easy_autoloop_excluded_peers": [],
64+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
6465
}
6566
}
6667
},
@@ -99,7 +100,8 @@
99100
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
100101
"easy_asset_params": {},
101102
"fast_swap_publication": true,
102-
"easy_autoloop_excluded_peers": []
103+
"easy_autoloop_excluded_peers": [],
104+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
103105
}
104106
}
105107
}

cmd/loop/testdata/sessions/liquidity/04_loop-setparams-feepercent-conflict.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@
7272
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
7373
"easy_asset_params": {},
7474
"fast_swap_publication": true,
75-
"easy_autoloop_excluded_peers": []
75+
"easy_autoloop_excluded_peers": [],
76+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
7677
}
7778
}
7879
},

cmd/loop/testdata/sessions/liquidity/05_loop-setrule-missing-threshold.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@
6969
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
7070
"easy_asset_params": {},
7171
"fast_swap_publication": true,
72-
"easy_autoloop_excluded_peers": []
72+
"easy_autoloop_excluded_peers": [],
73+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
7374
}
7475
}
7576
},

cmd/loop/testdata/sessions/liquidity/08_loop-setrule-success.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
7171
"easy_asset_params": {},
7272
"fast_swap_publication": true,
73-
"easy_autoloop_excluded_peers": []
73+
"easy_autoloop_excluded_peers": [],
74+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
7475
}
7576
}
7677
},
@@ -118,7 +119,8 @@
118119
"account_addr_type": "ADDRESS_TYPE_UNKNOWN",
119120
"easy_asset_params": {},
120121
"fast_swap_publication": true,
121-
"easy_autoloop_excluded_peers": []
122+
"easy_autoloop_excluded_peers": [],
123+
"loop_in_source": "LOOP_IN_SOURCE_WALLET"
122124
}
123125
}
124126
}

0 commit comments

Comments
 (0)