github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/prefunds/prefunds.go (about)

     1  package prefunds
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  
     7  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
     8  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
     9  	"github.com/gocarina/gocsv"
    10  )
    11  
    12  func GetPrefundPath(chain string) string {
    13  	return filepath.Join(config.MustGetPathToChainConfig(chain), "allocs.csv")
    14  }
    15  
    16  // Allocation is a single allocation in the genesis file
    17  type Allocation struct {
    18  	Address base.Address `json:"address" csv:"address"`
    19  	Balance base.Wei     `json:"balance" csv:"balance"`
    20  }
    21  
    22  // emptyAllocs is a list of empty allocations. We use this to return at least one allocation
    23  var emptyAllocs = []Allocation{}
    24  
    25  type allocCallback func(*Allocation, *any) (bool, error)
    26  
    27  // TODO: In the c++ code, the prefunds were cached in memory. We should do the same here.
    28  
    29  // LoadPrefunds loads the prefunds from the genesis file and processes each with provided callback if present
    30  func LoadPrefunds(chain string, thePath string, userCallback allocCallback) ([]Allocation, error) {
    31  	allocations := make([]Allocation, 0, 4000)
    32  	callbackFunc := func(record Allocation) error {
    33  		if base.IsValidAddress(record.Address.Hex()) {
    34  			alloc := Allocation{
    35  				Address: record.Address,
    36  				Balance: record.Balance,
    37  			}
    38  			// fmt.Println(alloc)
    39  			allocations = append(allocations, alloc)
    40  			if userCallback != nil {
    41  				if cont, err := userCallback(&alloc, nil); !cont || err != nil {
    42  					return err
    43  				}
    44  			}
    45  		}
    46  		return nil
    47  	}
    48  
    49  	if theFile, err := os.OpenFile(thePath, os.O_RDWR|os.O_CREATE, os.ModePerm); err != nil {
    50  		return emptyAllocs, err
    51  
    52  	} else {
    53  		defer theFile.Close()
    54  		if err := gocsv.UnmarshalToCallback(theFile, callbackFunc); err != nil {
    55  			return emptyAllocs, err
    56  		}
    57  	}
    58  
    59  	if len(allocations) == 0 {
    60  		allocations = emptyAllocs
    61  	}
    62  
    63  	return allocations, nil
    64  }
    65  
    66  func GetLargestPrefund(chain, thePath string) (Allocation, error) {
    67  	largest := Allocation{}
    68  	getLargest := func(alloc *Allocation, data *any) (bool, error) {
    69  		if alloc.Balance.Cmp(&largest.Balance) > 0 {
    70  			largest = *alloc
    71  		}
    72  		return true, nil
    73  	}
    74  
    75  	_, err := LoadPrefunds(chain, thePath, getLargest)
    76  	if err != nil {
    77  		return Allocation{}, err
    78  	}
    79  
    80  	return largest, nil
    81  }