Skip to content

Commit

Permalink
add structure to bot
Browse files Browse the repository at this point in the history
  • Loading branch information
yago-123 committed Jan 11, 2025
1 parent 44b3f7c commit ca0397c
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 47 deletions.
112 changes: 76 additions & 36 deletions cmd/bot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package main
import (
"context"
"crypto/sha256"
"github.com/yago-123/chainnet/pkg/script"
"fmt"
"time"

"github.com/btcsuite/btcutil/base58"
"github.com/yago-123/chainnet/pkg/kernel"
"github.com/yago-123/chainnet/pkg/script"

"github.com/sirupsen/logrus"
"github.com/yago-123/chainnet/config"
Expand All @@ -15,7 +17,6 @@ import (
"github.com/yago-123/chainnet/pkg/crypto/hash"
"github.com/yago-123/chainnet/pkg/crypto/sign"
"github.com/yago-123/chainnet/pkg/encoding"
"github.com/yago-123/chainnet/pkg/kernel"
util_crypto "github.com/yago-123/chainnet/pkg/util/crypto"
"github.com/yago-123/chainnet/pkg/wallet/hd_wallet"
)
Expand All @@ -27,6 +28,7 @@ const (
MinimumTxBalance = 100

SleepTimeBetweenRecalculations = 20 * time.Minute
TimeBetweenMetadataBackup = 1 * time.Minute
)

var (
Expand Down Expand Up @@ -75,87 +77,104 @@ func main() {

logger.Infof("HD wallet synced with %d accounts", numAccounts)

totalBalance, err := hdWallet.GetBalance()
if err != nil {
logger.Fatalf("error getting wallet balance: %v", err)
if numAccounts == 0 {
if errAskFunds := AskForFunds(hdWallet); errAskFunds != nil {
logger.Fatalf("error asking for funds: %v", errAskFunds)
}
}

if totalBalance == 0 {
var errAcc error
var acc *hd_wallet.Account

numAcc := hdWallet.GetNumAccounts()
if numAcc == 0 {
acc, errAcc = hdWallet.GetNewAccount()
if errAcc != nil {
logger.Fatalf("error creating account: %v", errAcc)
}
if numAccounts == 1 {
if errDistrFund := DistributeFundsAmongAccounts(hdWallet); errDistrFund != nil {
logger.Fatalf("error distributing funds: %v", errDistrFund)
}
}

if numAcc > 0 {
acc, errAcc = hdWallet.GetAccount(FoundationAccountIndex)
if errAcc != nil {
logger.Fatalf("error getting account: %v", errAcc)
}
}
if numAccounts > 1 {
// keep redistributing funds
// if account exists but wallets is 1
CreateMultipleWalletsInsideAccount()
go SaveMetadataPeriodically(hdWallet)
}

wallet, errAcc := acc.GetNewExternalWallet()
if errAcc != nil {
logger.Fatalf("error getting foundation wallet: %v", errAcc)
}
// if numAccounts > 1 && numWallets > 1 {
// CreateTransactionsInsideAccount()
// }
}

func AskForFunds(hdWallet *hd_wallet.Wallet) error {
acc, errAcc := hdWallet.GetNewAccount()
if errAcc != nil {
return fmt.Errorf("error getting account: %w", errAcc)
}

logger.Fatalf("HD wallet is empty, fund %s with a P2PK and execute this again", base58.Encode(wallet.GetP2PKAddress()))
wallet, errAcc := acc.GetNewExternalWallet()
if errAcc != nil {
return fmt.Errorf("error getting wallet: %w", errAcc)
}

logger.Warnf("HD wallet is empty, fund %s with a P2PK and execute this again", base58.Encode(wallet.GetP2PKAddress()))

return nil
}

func DistributeFundsAmongAccounts(hdWallet *hd_wallet.Wallet) error {
addresses := [][]byte{}
targetAmounts := []uint{}

totalBalance, err := hdWallet.GetBalance()
if err != nil {
return fmt.Errorf("error getting wallet balance: %w", err)
}

logger.Infof("HD wallet contains %.5f coins", float64(totalBalance)/float64(kernel.ChainnetCoinAmount))

numAccounts := hdWallet.GetNumAccounts()

// create remaining accounts so that we can operate them in parallel without problems
if numAccounts < ConcurrentAccounts {
logger.Infof("creating remaining %d accounts...", ConcurrentAccounts-numAccounts)
for i := numAccounts; i < ConcurrentAccounts; i++ {
_, errAccount := hdWallet.GetNewAccount()
if errAccount != nil {
logger.Fatalf("error creating account: %v", errAccount)
return fmt.Errorf("error creating account: %w", errAccount)
}
}
}

// check the balance of the foundation account
foundationAccount, err := hdWallet.GetAccount(FoundationAccountIndex)
if err != nil {
logger.Fatalf("error getting foundation account: %v", err)
return fmt.Errorf("error getting foundation account: %w", err)
}

foundationAccountBalance, err := foundationAccount.GetBalance()
if err != nil {
logger.Fatalf("error getting foundation account balance: %v", err)
return fmt.Errorf("error getting foundation account balance: %w", err)
}

logger.Infof("foundation account contains %.5f coins", kernel.ConvertFromChannoshisToCoins(foundationAccountBalance))

// generate outputs for multiple addresses
addresses := [][]byte{}
targetAmounts := []uint{}
distributeFundsAmount := (foundationAccountBalance + 1) / ConcurrentAccounts
distributeFundsAmount := (foundationAccountBalance) / (ConcurrentAccounts + 1)
for i := range ConcurrentAccounts {
targetAmounts = append(targetAmounts, distributeFundsAmount)

account, errAccount := hdWallet.GetAccount(uint(i))
if errAccount != nil {
logger.Fatalf("error getting account: %v", errAccount)
return fmt.Errorf("error getting account: %w", errAccount)
}

wallet, errWallet := account.GetNewExternalWallet()
if errWallet != nil {
logger.Fatalf("error getting wallet: %v", errWallet)
return fmt.Errorf("error getting wallet: %w", errWallet)
}

addresses = append(addresses, wallet.GetP2PKAddress())
}

foundationAccountUTXOs, err := foundationAccount.GetAccountUTXOs()
if err != nil {
logger.Fatalf("error getting foundation account UTXOs: %v", err)
return fmt.Errorf("error getting foundation account UTXOs: %w", err)
}

// create the foundation fund transaction
Expand All @@ -166,13 +185,34 @@ func main() {
distributeFundsAmount,
foundationAccountUTXOs,
)
if err != nil {
return fmt.Errorf("error generating transaction: %w", err)
}

ctx, cancel := context.WithTimeout(context.Background(), cfg.P2P.ConnTimeout)
defer cancel()

if errSend := foundationAccount.SendTransaction(ctx, tx); errSend != nil {
logger.Fatalf("error sending transaction: %v", errSend)
return fmt.Errorf("error sending transaction: %w", errSend)
}

logger.Infof("funds distributed to %d accounts: %s", ConcurrentAccounts, tx.String())

return nil
}

func CreateMultipleWalletsInsideAccount() {

}

func CreateTransactionsInsideAccount() {

}

func SaveMetadataPeriodically(hdWallet *hd_wallet.Wallet) {
for {
time.Sleep(SleepTimeBetweenRecalculations)

hdWallet.GetMetadata()
}
}
1 change: 1 addition & 0 deletions cmd/nespv/cmd/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"context"

cerror "github.com/yago-123/chainnet/pkg/errs"
"github.com/yago-123/chainnet/pkg/kernel"

Expand Down
1 change: 1 addition & 0 deletions pkg/wallet/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package wallet

import (
"errors"

"github.com/yago-123/chainnet/pkg/kernel"
"github.com/yago-123/chainnet/pkg/script"
util_p2pkh "github.com/yago-123/chainnet/pkg/util/p2pkh"
Expand Down
46 changes: 35 additions & 11 deletions pkg/wallet/hd_wallet/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ func (hda *Account) Sync() (uint32, uint32, error) {
hda.mu.Lock()
defer hda.mu.Unlock()

var wg sync.WaitGroup
errCh := make(chan error, 2)

// helper function to sync wallets
syncWallets := func(changeType changeType) ([]*wallt.Wallet, error) {
wallets := []*wallt.Wallet{}
Expand Down Expand Up @@ -136,19 +139,40 @@ func (hda *Account) Sync() (uint32, uint32, error) {
return activeWallets, nil
}

// sync external wallets
externalWallets, err := syncWallets(ExternalChangeType)
if err != nil {
return 0, 0, fmt.Errorf("failed syncing external addresses: %w", err)
}
hda.externalWallets = externalWallets
// parallel tasks
wg.Add(1)
go func() {
defer wg.Done()
externalWallets, err := syncWallets(ExternalChangeType)
if err != nil {
errCh <- fmt.Errorf("failed syncing external addresses: %w", err)
return
}
hda.externalWallets = externalWallets
}()

// sync internal wallets
internalWallets, err := syncWallets(InternalChangeType)
if err != nil {
return 0, 0, fmt.Errorf("failed syncing internal addresses: %w", err)
wg.Add(1)
go func() {
defer wg.Done()
internalWallets, err := syncWallets(InternalChangeType)
if err != nil {
errCh <- fmt.Errorf("failed syncing internal addresses: %w", err)
return
}
hda.internalWallets = internalWallets
}()

// wait for all goroutines to complete
wg.Wait()
close(errCh)

// check for errors
var firstError error
for err := range errCh {
if firstError == nil {
firstError = err // capture the first error
}
}
hda.internalWallets = internalWallets

return uint32(len(hda.externalWallets)), uint32(len(hda.internalWallets)), nil
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/wallet/hd_wallet/hd_wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ func (hd *Wallet) Sync() (uint, error) {
return uint(hd.accountNum), nil
}

func (hd *Wallet) GetMetadata() {
hd.mu.Lock()
defer hd.mu.Unlock()

// todo(): implement this method
}

// GetNewAccount derives a new account from the HD wallet by incrementing the account index
func (hd *Wallet) GetNewAccount() (*Account, error) {
hd.mu.Lock()
Expand Down

0 comments on commit ca0397c

Please sign in to comment.