diff --git a/main.go b/main.go index 89965fe..aa31098 100644 --- a/main.go +++ b/main.go @@ -52,7 +52,7 @@ func main() { fmt.Println("Positions", positions) var accounts []types.Account - for i := 0; i < positions; i++ { + for i := 0; i < int(positions); i++ { position := uint32(i) privKey, pubKey, acctAddress := lib.GetPrivKey(config, mnemonic, position) accounts = append(accounts, types.Account{ @@ -288,6 +288,7 @@ func extractExpectedSequence(errMsg string) (uint64, error) { return expectedSeq, nil } +// adjustBalances transfers funds between accounts to balance their balances within the threshold // adjustBalances transfers funds between accounts to balance their balances within the threshold func adjustBalances(accounts []types.Account, balances map[string]sdkmath.Int, config types.Config) error { if len(accounts) == 0 { @@ -299,6 +300,7 @@ func adjustBalances(accounts []types.Account, balances map[string]sdkmath.Int, c for _, balance := range balances { totalBalance = totalBalance.Add(balance) } + fmt.Printf("Total Balance across all accounts: %s %s\n", totalBalance.String(), config.Denom) if totalBalance.IsZero() { return errors.New("total balance is zero, nothing to adjust") @@ -306,9 +308,11 @@ func adjustBalances(accounts []types.Account, balances map[string]sdkmath.Int, c numAccounts := sdkmath.NewInt(int64(len(accounts))) averageBalance := totalBalance.Quo(numAccounts) + fmt.Printf("Number of Accounts: %d, Average Balance per account: %s %s\n", numAccounts.Int64(), averageBalance.String(), config.Denom) // Define minimum transfer amount to avoid dust transfers minTransfer := sdkmath.NewInt(1000) // Adjust based on your token's decimal places + fmt.Printf("Minimum Transfer Amount to avoid dust: %s %s\n", minTransfer.String(), config.Denom) // Create a slice to track balances that need to send or receive funds type balanceAdjustment struct { @@ -317,17 +321,25 @@ func adjustBalances(accounts []types.Account, balances map[string]sdkmath.Int, c } var adjustments []balanceAdjustment + threshold := averageBalance.MulRaw(10).QuoRaw(100) // threshold = averageBalance * 10 / 100 + fmt.Printf("Balance Threshold for adjustments (10%% of average balance): %s %s\n", threshold.String(), config.Denom) + for _, acct := range accounts { currentBalance := balances[acct.Address] difference := averageBalance.Sub(currentBalance) + fmt.Printf("Account %s - Current Balance: %s %s, Difference from average: %s %s\n", + acct.Address, currentBalance.String(), config.Denom, difference.String(), config.Denom) + // Only consider adjustments exceeding the threshold and minimum transfer amount - threshold := averageBalance.MulRaw(10).QuoRaw(100) // threshold = averageBalance * 10 / 100 if difference.Abs().GT(threshold) && difference.Abs().GT(minTransfer) { adjustments = append(adjustments, balanceAdjustment{ Account: acct, Amount: difference, }) + fmt.Printf("-> Account %s requires adjustment of %s %s\n", acct.Address, difference.String(), config.Denom) + } else { + fmt.Printf("-> Account %s is within balance threshold, no adjustment needed\n", acct.Address) } } @@ -337,52 +349,77 @@ func adjustBalances(accounts []types.Account, balances map[string]sdkmath.Int, c if adj.Amount.IsNegative() { // Check if the account has enough balance to send accountBalance := balances[adj.Account.Address] + fmt.Printf("Sender Account %s - Balance: %s %s, Surplus: %s %s\n", + adj.Account.Address, accountBalance.String(), config.Denom, adj.Amount.Abs().String(), config.Denom) + if accountBalance.GT(sdkmath.ZeroInt()) { senders = append(senders, adj) } else { - fmt.Printf("Account %s has zero balance, cannot send funds.\n", adj.Account.Address) + fmt.Printf("-> Account %s has zero balance, cannot send funds.\n", adj.Account.Address) } } else if adj.Amount.IsPositive() { + fmt.Printf("Receiver Account %s - Needs: %s %s\n", + adj.Account.Address, adj.Amount.String(), config.Denom) receivers = append(receivers, adj) } } - // Initialize gRPC client - grpcClient, err := client.NewGRPCClient(config.Nodes.GRPC) - if err != nil { - return fmt.Errorf("failed to create gRPC client: %v", err) - } - // Perform transfers from senders to receivers for _, sender := range senders { + // The total amount the sender needs to transfer (their surplus) amountToSend := sender.Amount.Abs() + fmt.Printf("\nStarting transfers from Sender Account %s - Total Surplus to send: %s %s\n", + sender.Account.Address, amountToSend.String(), config.Denom) + + // Iterate over the receivers who need funds for i := range receivers { receiver := &receivers[i] + + // Check if the receiver still needs funds if receiver.Amount.GT(sdkmath.ZeroInt()) { + // Determine the amount to transfer: + // It's the minimum of what the sender can send and what the receiver needs transferAmount := sdkmath.MinInt(amountToSend, receiver.Amount) - // Ensure you're using the correct sender account with matching PrivKey - err := TransferFunds(grpcClient, sender.Account, receiver.Account.Address, transferAmount, config) + fmt.Printf("Transferring %s %s from %s to %s\n", + transferAmount.String(), config.Denom, sender.Account.Address, receiver.Account.Address) + + // Transfer funds from the sender to the receiver + err := TransferFunds(sender.Account, receiver.Account.Address, transferAmount, config) if err != nil { return fmt.Errorf("failed to transfer funds from %s to %s: %v", sender.Account.Address, receiver.Account.Address, err) } - // Update the amounts + fmt.Printf("-> Successfully transferred %s %s from %s to %s\n", + transferAmount.String(), config.Denom, sender.Account.Address, receiver.Account.Address) + + // Update the sender's remaining amount to send amountToSend = amountToSend.Sub(transferAmount) + fmt.Printf("Sender %s remaining surplus to send: %s %s\n", + sender.Account.Address, amountToSend.String(), config.Denom) + + // Update the receiver's remaining amount to receive receiver.Amount = receiver.Amount.Sub(transferAmount) + fmt.Printf("Receiver %s remaining amount needed: %s %s\n", + receiver.Account.Address, receiver.Amount.String(), config.Denom) + // If the sender has sent all their surplus, move to the next sender if amountToSend.IsZero() { + fmt.Printf("Sender %s has sent all surplus funds.\n", sender.Account.Address) break } + } else { + fmt.Printf("Receiver %s no longer needs funds.\n", receiver.Account.Address) } } } + fmt.Println("\nBalance adjustment complete.") return nil } -func TransferFunds(grpcClient *client.GRPCClient, sender types.Account, receiverAddress string, amount sdkmath.Int, config types.Config) error { +func TransferFunds(sender types.Account, receiverAddress string, amount sdkmath.Int, config types.Config) error { // Get the sender's account info sequence, accNum, err := lib.GetAccountInfo(sender.Address, config) if err != nil { @@ -409,7 +446,7 @@ func TransferFunds(grpcClient *client.GRPCClient, sender types.Account, receiver PrivKey: sender.PrivKey, PubKey: sender.PubKey, AcctAddress: sender.Address, - MsgType: config.MsgType, + MsgType: "bank_send", MsgParams: types.MsgParams{ FromAddress: sender.Address, ToAddress: receiverAddress, @@ -418,18 +455,17 @@ func TransferFunds(grpcClient *client.GRPCClient, sender types.Account, receiver }, } - // Create a context with timeout - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() + fmt.Println("TransferFunds - txParams", txParams) + fmt.Println("TransferFunds - msgParams", txParams.MsgParams) - // Send the transaction - grpcResp, _, err := broadcast.SendTransactionViaGRPC(ctx, txParams, sequence, grpcClient) + // Send the transaction via RPC + resp, _, err := broadcast.SendTransactionViaRPC(txParams, sequence) if err != nil { return fmt.Errorf("failed to send transaction: %v", err) } - if grpcResp.Code != 0 { - return fmt.Errorf("transaction failed with code %d: %s", grpcResp.Code, grpcResp.RawLog) + if resp.Code != 0 { + return fmt.Errorf("transaction failed with code %d: %s", resp.Code, resp.Log) } fmt.Printf("Transferred %s%s from %s to %s\n", amount.String(), config.Denom, sender.Address, receiverAddress)