Skip to content

Commit

Permalink
delegations from state export
Browse files Browse the repository at this point in the history
  • Loading branch information
asamere committed Feb 14, 2023
1 parent 8f87078 commit bb25395
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 7 deletions.
37 changes: 37 additions & 0 deletions cli/cosmos_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import (
)

var (
delegationsFromStateExport = &cobra.Command{
Use: "import-delegations [data-directory] [chain] [height]",
Short: "import staked delegations from a cosmos daemond export",
Run: runDelegationsFromStateExport,
Args: cobra.ExactValidArgs(3),
}
// DEPRECATED
indexStartingDelegateBalancesCmd = &cobra.Command{
Use: "starting-delegations [chain] [data-directory]",
Short: "initialize delegate balances from JSON export",
Expand Down Expand Up @@ -87,6 +94,36 @@ func runThorLPIndexer(cmd *cobra.Command, args []string) {
}
}

func runDelegationsFromStateExport(cmd *cobra.Command, args []string) {
flags := cmd.InheritedFlags()
envPath, _ := flags.GetString("env")
c := utils.ReadDBConfig(envPath)
if c == nil {
cmd.PrintErrf("no config for path %s", envPath)
return
}

chain := args[1]
baseDataDir := args[0]
sheight := args[2]
height, err := strconv.ParseInt(sheight, 10, 64)
if err != nil {
cmd.PrintErrf("error parsing height %s: %+v", sheight, err)
return
}

params := indexer.CosmosIndexerParams{Chain: chain, DB: *c}
indxr, err := indexer.NewCosmosIndexer(params)
if err != nil {
cmd.PrintErrf("error creating cosmos indexer: %+v", err)
return
}
dataDir := fmt.Sprintf("%s/%s", baseDataDir, strings.ToLower(chain))
if err = indxr.IndexDelegationsFromStateExport(dataDir, chain, height); err != nil {
cmd.PrintErrf("error indexing Delegations from state export: %+v", err)
}
}

func runStartingDelegationsIndexer(cmd *cobra.Command, args []string) {
flags := cmd.InheritedFlags()
envPath, _ := flags.GetString("env")
Expand Down
2 changes: 1 addition & 1 deletion cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func init() {
indexCosmosCmd.AddCommand(indexDelegatorsCmd)
indexCosmosCmd.AddCommand(indexThorchainLPCmd)
indexCosmosCmd.AddCommand(indexOsmoLPCmd)
indexCosmosCmd.AddCommand(indexStartingDelegateBalancesCmd)
indexCosmosCmd.AddCommand(delegationsFromStateExport)
rootCmd.AddCommand(indexCosmosCmd)
rootCmd.AddCommand(exportCmd)
rootCmd.AddCommand(exportDelegatesCmd)
Expand Down
86 changes: 80 additions & 6 deletions indexer/cosmos_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"math/big"
"os"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -45,18 +46,28 @@ type DelegationPage struct {
DelegationResponses []DelegationResponse `json:"delegation_responses"`
}

type Delegation struct {
DelegatorAddress string `json:"delegator_address"`
ValidatorAddress string `json:"validator_address"`
Shares string `json:"shares"`
}

type DelegationResponse struct {
Delegation struct {
DelegatorAddress string `json:"delegator_address"`
ValidatorAddress string `json:"validator_address"`
Shares string `json:"shares"`
} `json:"delegation"`
Balance struct {
Delegation Delegation `json:"delegation"`
Balance struct {
Denom string `json:"denom"`
Amount int64 `json:"amount,string"`
} `json:"balance"`
}

type ImportedDelegation struct {
AppState struct {
Staking struct {
Delegations []Delegation `json:"delegations"`
} `json:"staking"`
} `json:"app_state"`
}

func NewCosmosIndexer(params CosmosIndexerParams) (*CosmosIndexer, error) {
d, err := db.New(params.DB)
if err != nil {
Expand All @@ -76,6 +87,69 @@ func NewCosmosIndexer(params CosmosIndexerParams) (*CosmosIndexer, error) {
return &CosmosIndexer{db: d, tm: tm, lcd: lcd, chain: chain, startHeight: params.StartHeight, endHeight: params.EndHeight}, nil
}

func (c *CosmosIndexer) IndexDelegationsFromStateExport(dataDir, chain string, height int64) error {
stateExportFile := fmt.Sprintf("%s/state-export_%d.json", dataDir, height)
start := time.Now()
raw, err := os.ReadFile(stateExportFile)
if err != nil {
return errors.Wrapf(err, "error reading file %s", stateExportFile)
}
log.Infof("read file %s in %.3f seconds", stateExportFile, time.Since(start).Seconds())
start = time.Now()
imported := ImportedDelegation{}
if err = json.Unmarshal(raw, &imported); err != nil {
return errors.Wrapf(err, "error unmarshalling file %s", stateExportFile)
}
log.Infof("unmarshalled delegations %s in %.3f seconds", stateExportFile, time.Since(start).Seconds())

events := make([]*types.CosmosStakingEvent, 0, len(imported.AppState.Staking.Delegations))

start = time.Now()
for _, d := range imported.AppState.Staking.Delegations {
value, err := parseShares(d.Shares, c.chain.Decimals)
if err != nil {
return errors.Wrapf(err, "%s delegation to %s error parsing shares %s", d.DelegatorAddress, d.ValidatorAddress, d.Shares)
}
if value <= 0 {
log.Warnf("%s delegation to %s with value %f. string shares: %s", d.DelegatorAddress, d.ValidatorAddress, value, d.Shares)
}
event := &types.CosmosStakingEvent{
Chain: c.chain.Name,
EventType: "initial",
Delegator: d.DelegatorAddress,
Validator: d.ValidatorAddress,
Value: value,
BlockNumber: uint64(height),
TxHash: "00000000000000000000000000000000",
EventIndex: 0,
}
events = append(events, event)
}
log.Infof("created %d staking events in %.3f seconds", len(events), time.Since(start).Seconds())
start = time.Now()
if err = c.db.InsertStakingEvents(events); err != nil {
return errors.Wrapf(err, "error inserting staking events")
}
log.Infof("inserted %d staking events in %.3f seconds", len(events), time.Since(start).Seconds())
return nil
}

func parseShares(s string, decimals uint8) (float64, error) {
if !strings.Contains(s, ".") {
return -1, fmt.Errorf("shares %s does not contain a decimal", s)
}
parts := strings.Split(s, ".")
if len(parts) != 2 {
return -1, fmt.Errorf("shares %s has more than one decimal", s)
}
ishares, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil {
return -1, errors.Wrapf(err, "error parsing shares %d", ishares)
}

return utils.FromBaseUnits(ishares, decimals), nil
}

// reads a collection of pageN.json files from the dataDir and inserts them into the db
func (c *CosmosIndexer) IndexStartingDelegations(dataDir string) error {
dir, err := os.ReadDir(dataDir)
Expand Down

0 comments on commit bb25395

Please sign in to comment.