func (m *Manager) WatchMatchedAccounts(ctx context.Context,
	matchedAccounts []*btcec.PublicKey) error {
	for _, matchedAccount := range matchedAccounts {
		acct, err := m.cfg.Store.Account(matchedAccount)
		if err != nil {
			return fmt.Errorf("error reading account %x: %v",
				matchedAccount.SerializeCompressed(), err)
		}
		m.watcher.CancelAccountSpend(matchedAccount)
		m.watcher.CancelAccountConf(matchedAccount)
		err = m.resumeAccount(ctx, acct, false, false, 0)
		if err != nil {
			return fmt.Errorf("error resuming account %x: %v",
				matchedAccount.SerializeCompressed(), err)
		}
	}
	return nil
}
WatchMatchedAccounts resumes accounts that were just matched in a batch and
are expecting the batch transaction to confirm as their next account output.
This will cancel all previous spend and conf watchers of all accounts
involved in the batch.
package account
import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"math"
	"strings"
	"sync"
	"time"
	"github.com/btcsuite/btcd/blockchain"
	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
	"github.com/btcsuite/btcutil/txsort"
	"github.com/btcsuite/btcwallet/wallet"
	"github.com/btcsuite/btcwallet/wallet/txrules"
	"github.com/btcsuite/btcwallet/wtxmgr"
	"github.com/lightninglabs/lndclient"
	"github.com/lightninglabs/pool/account/watcher"
	"github.com/lightninglabs/pool/poolscript"
	"github.com/lightningnetwork/lnd/chainntnfs"
	"github.com/lightningnetwork/lnd/input"
	"github.com/lightningnetwork/lnd/lnwallet"
	"github.com/lightningnetwork/lnd/lnwallet/chainfee"
	"github.com/lightningnetwork/lnd/lnwallet/chanfunding"
)
const (
	minConfs = 3
	maxConfs = 6
	MinAccountValue btcutil.Amount = 100000
	minAccountExpiry = 144        
	maxAccountExpiry = 144 * 365  
)
var (
	errTxNotFound = errors.New("transaction not found")
)
type witnessType uint8
const (
	expiryWitness witnessType = iota
	multiSigWitness
)
type spendPackage struct {
	tx *wire.MsgTx
	accountInputIdx int
	witnessScript []byte
	ourSig []byte
}
type ManagerConfig struct {
	Store Store
	Auctioneer Auctioneer
	Wallet lndclient.WalletKitClient
	Signer lndclient.SignerClient
	ChainNotifier lndclient.ChainNotifierClient
	TxSource TxSource
	TxFeeEstimator TxFeeEstimator
	TxLabelPrefix string
}
type Manager struct {
	started sync.Once
	stopped sync.Once
	cfg     ManagerConfig
	watcher *watcher.Watcher
	pendingBatchMtx sync.Mutex
	reservationMtx sync.Mutex
	wg   sync.WaitGroup
	quit chan struct{}
}
func NewManager(cfg *ManagerConfig) *Manager {
	m := &Manager{
		cfg:  *cfg,
		quit: make(chan struct{}),
	}
	m.watcher = watcher.New(&watcher.Config{
		ChainNotifier:       cfg.ChainNotifier,
		HandleAccountConf:   m.handleAccountConf,
		HandleAccountSpend:  m.handleAccountSpend,
		HandleAccountExpiry: m.handleAccountExpiry,
	})
	return m
}
func (m *Manager) Start() error {
	var err error
	m.started.Do(func() {
		err = m.start()
	})
	return err
}
func (m *Manager) start() error {
	ctx := context.Background()
	if err := m.watcher.Start(); err != nil {
		return err
	}
	accounts, err := m.cfg.Store.Accounts()
	if err != nil {
		return fmt.Errorf("unable to retrieve accounts: %v", err)
	}
	feeRate, err := m.cfg.Wallet.EstimateFee(
		ctx, int32(DefaultFundingConfTarget),
	)
	if err != nil {
		return fmt.Errorf("unable to estimate default fees %w", err)
	}
	for _, account := range accounts {
		acctKey := account.TraderKey.PubKey.SerializeCompressed()
		if err := m.verifyAccountSigner(ctx, account); err != nil {
			return fmt.Errorf("unable to resume account %x: %v",
				acctKey, err)
		}
		if err := m.resumeAccount(
			ctx, account, true, false, feeRate,
		); err != nil {
			return fmt.Errorf("unable to resume account %x: %v",
				acctKey, err)
		}
	}
	return nil
}
func (m *Manager) Stop() {
	m.stopped.Do(func() {
		m.watcher.Stop()
		close(m.quit)
		m.wg.Wait()
	})
}
func (m *Manager) QuoteAccount(ctx context.Context, value btcutil.Amount,
	confTarget uint32) (chainfee.SatPerKWeight, btcutil.Amount, error) {
	terms, err := m.cfg.Auctioneer.Terms(ctx)
	if err != nil {
		return 0, 0, fmt.Errorf("could not query auctioneer terms: %v",
			err)
	}
	err = validateAccountValue(value, terms.MaxAccountValue)
	if err != nil {
		return 0, 0, err
	}
	feeRate, err := m.cfg.Wallet.EstimateFee(ctx, int32(confTarget))
	if err != nil {
		return 0, 0, fmt.Errorf("error estimating fee rate: %v", err)
	}
	totalMinerFee, err := m.cfg.TxFeeEstimator.EstimateFeeToP2WSH(
		ctx, value, int32(confTarget),
	)
	if err != nil {
		return 0, 0, fmt.Errorf("error estimating total on-chain fee: "+
			"%v", err)
	}
	return feeRate, totalMinerFee, nil
}
func (m *Manager) InitAccount(ctx context.Context, value btcutil.Amount,
	feeRate chainfee.SatPerKWeight, expiry,
	bestHeight uint32) (*Account, error) {
	m.reservationMtx.Lock()
	defer m.reservationMtx.Unlock()
	terms, err := m.cfg.Auctioneer.Terms(ctx)
	if err != nil {
		return nil, fmt.Errorf("could not query auctioneer terms: %v",
			err)
	}
	err = validateAccountParams(
		value, terms.MaxAccountValue, expiry, bestHeight,
	)
	if err != nil {
		return nil, err
	}
	keyDesc, err := m.cfg.Wallet.DeriveNextKey(
		ctx, int32(poolscript.AccountKeyFamily),
	)
	if err != nil {
		return nil, err
	}
	reservation, err := m.cfg.Auctioneer.ReserveAccount(
		ctx, value, expiry, keyDesc.PubKey,
	)
	if err != nil {
		return nil, err
	}
	secret, err := m.cfg.Signer.DeriveSharedKey(
		ctx, reservation.AuctioneerKey, &keyDesc.KeyLocator,
	)
	if err != nil {
		return nil, err
	}
	account := &Account{
		Value:         value,
		Expiry:        expiry,
		TraderKey:     keyDesc,
		AuctioneerKey: reservation.AuctioneerKey,
		BatchKey:      reservation.InitialBatchKey,
		Secret:        secret,
		State:         StateInitiated,
		HeightHint:    bestHeight,
	}
	if err := m.cfg.Store.AddAccount(account); err != nil {
		return nil, err
	}
	log.Infof("Creating new account %x of %v that expires at height %v",
		keyDesc.PubKey.SerializeCompressed(), value, expiry)
	err = m.resumeAccount(ctx, account, false, false, feeRate)
	if err != nil {
		return nil, err
	}
	return account, nil
}