Skip to content

Commit 8294280

Browse files
committed
hyperloop: add hyperloop manager
1 parent 6619477 commit 8294280

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

hyperloop/manager.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package hyperloop
2+
3+
import (
4+
"context"
5+
"sync"
6+
"time"
7+
8+
"github.com/btcsuite/btcd/btcutil"
9+
"github.com/btcsuite/btcd/chaincfg"
10+
"github.com/lightninglabs/lndclient"
11+
"github.com/lightninglabs/loop/fsm"
12+
looprpc "github.com/lightninglabs/loop/swapserverrpc"
13+
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
14+
"github.com/lightningnetwork/lnd/lntypes"
15+
)
16+
17+
var (
18+
// defaultFSMObserverTimeout is the default timeout we'll wait for the fsm
19+
// to reach a certain state.
20+
defaultFSMObserverTimeout = time.Second * 15
21+
)
22+
23+
// Config contains all the services that the reservation FSM needs to operate.
24+
type Config struct {
25+
26+
// Store is the store that is used to store the hyperloop.
27+
Store Store
28+
29+
// Wallet handles the key derivation for the reservation.
30+
Wallet lndclient.WalletKitClient
31+
32+
// ChainNotifier is used to subscribe to block notifications.
33+
ChainNotifier lndclient.ChainNotifierClient
34+
35+
// Signer is used to sign messages.
36+
Signer lndclient.SignerClient
37+
38+
// Router is used to pay the offchain payments.
39+
Router lndclient.RouterClient
40+
41+
// HyperloopClient is the client used to communicate with the
42+
// swap server.
43+
HyperloopClient looprpc.HyperloopServerClient
44+
45+
// ChainParams are the params for the bitcoin network.
46+
ChainParams *chaincfg.Params
47+
}
48+
49+
type Manager struct {
50+
cfg *Config
51+
runCtx context.Context
52+
53+
activePendingHyperloop *HyperLoop
54+
pendingHyperloops map[lntypes.Hash]*HyperLoop
55+
56+
sync.Mutex
57+
}
58+
59+
// NewManager creates a new hyperloop manager.
60+
func NewManager(cfg *Config) *Manager {
61+
return &Manager{
62+
cfg: cfg,
63+
pendingHyperloops: make(map[lntypes.Hash]*HyperLoop),
64+
}
65+
}
66+
67+
// Run starts the hyperloop manager.
68+
func (m *Manager) Run(ctx context.Context) error {
69+
runCtx, cancel := context.WithCancel(ctx)
70+
defer cancel()
71+
72+
m.runCtx = runCtx
73+
74+
for {
75+
select {
76+
case <-runCtx.Done():
77+
return nil
78+
}
79+
}
80+
}
81+
82+
// NewHyperLoopOut creates a new hyperloop out swap. If we have a pending
83+
// hyperloop, we'll use the same id and sweep address in order to batch
84+
// a possible sweep.
85+
func (m *Manager) NewHyperLoopOut(ctx context.Context, amt btcutil.Amount,
86+
customSweepAddr string) (*HyperLoop, error) {
87+
88+
var (
89+
hyperloopID ID
90+
sweepAddr btcutil.Address
91+
publishDeadline time.Time
92+
err error
93+
)
94+
95+
// As we're only doing private hyperloops for now, we'll create an id.
96+
if m.activePendingHyperloop == nil {
97+
hyperloopID, err = NewHyperLoopId()
98+
if err != nil {
99+
return nil, err
100+
}
101+
102+
publishDeadline = time.Now().Add(time.Minute * 30)
103+
104+
// Create a sweep pk script.
105+
if customSweepAddr == "" {
106+
sweepAddr, err = m.cfg.Wallet.NextAddr(
107+
ctx, "", walletrpc.AddressType_TAPROOT_PUBKEY, false,
108+
)
109+
if err != nil {
110+
return nil, err
111+
}
112+
} else {
113+
sweepAddr, err = btcutil.DecodeAddress(customSweepAddr, nil)
114+
if err != nil {
115+
return nil, err
116+
}
117+
}
118+
} else {
119+
hyperloopID = m.activePendingHyperloop.ID
120+
publishDeadline = m.activePendingHyperloop.PublishTime
121+
122+
if customSweepAddr == "" {
123+
sweepAddr = m.activePendingHyperloop.SweepAddr
124+
} else {
125+
addr, err := btcutil.DecodeAddress(customSweepAddr, nil)
126+
if err != nil {
127+
return nil, err
128+
}
129+
130+
sweepAddr = addr
131+
}
132+
}
133+
134+
req := &initHyperloopContext{
135+
hyperloopID: hyperloopID,
136+
swapAmt: amt,
137+
sweepAddr: sweepAddr,
138+
publishTime: publishDeadline,
139+
}
140+
141+
// Create a new hyperloop fsm.
142+
hl, err := NewFSM(m.runCtx, m.cfg)
143+
if err != nil {
144+
return nil, err
145+
}
146+
147+
err = hl.SendEvent(OnInit, req)
148+
if err != nil {
149+
return nil, err
150+
}
151+
152+
err = hl.DefaultObserver.WaitForState(
153+
ctx, defaultFSMObserverTimeout, WaitForPublish,
154+
fsm.WithAbortEarlyOnErrorOption(),
155+
)
156+
if err != nil {
157+
return nil, err
158+
}
159+
160+
return hl.hyperloop, nil
161+
}

0 commit comments

Comments
 (0)