Skip to content

Commit

Permalink
Merge pull request #18 from axone-protocol/feat/extract-command
Browse files Browse the repository at this point in the history
Feat/extract command
  • Loading branch information
ccamel authored Jan 4, 2025
2 parents 7434e8f + 91edcb5 commit f34cdf7
Show file tree
Hide file tree
Showing 11 changed files with 244 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ target/
.idea/
.vscode/
.DS_Store
data/
18 changes: 9 additions & 9 deletions .releaserc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins:
- preset: conventionalcommits
- - "@semantic-release/changelog"
- changelogFile: CHANGELOG.md
changelogTitle: "# ØKP4 template-go"
changelogTitle: "# Axone Wallet Extractor Changelog"
- - "@google/semantic-release-replace-plugin"
- replacements:
- files: [version]
Expand All @@ -25,18 +25,18 @@ plugins:
make build-go-all
- - "@semantic-release/github"
- assets:
- name: template-go_darwin_amd64
- name: wallet-extractor_darwin_amd64
label: Binary - Darwin amd64
path: "./target/dist/darwin/amd64/template-go"
- name: template-go_darwin_arm64
path: "./target/dist/darwin/amd64/wallet-extractor"
- name: wallet-extractor_darwin_arm64
label: Binary - Darwin arm64
path: "./target/dist/darwin/arm64/template-go"
- name: template-go_linux_amd64
path: "./target/dist/darwin/arm64/wallet-extractor"
- name: wallet-extractor_linux_amd64
label: Binary - Linux amd64
path: "./target/dist/linux/amd64/template-go"
- name: template-go_windows_amd64.exe
path: "./target/dist/linux/amd64/wallet-extractor"
- name: wallet-extractor_windows_amd64.exe
label: Binary - Windows amd64
path: "./target/dist/windows/amd64/template-go.exe"
path: "./target/dist/windows/amd64/wallet-extractor.exe"
- - "@semantic-release/git"
- assets:
- CHANGELOG.md
Expand Down
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ℹ Freely based on: https://gist.github.com/thomaspoignant/5b72d579bd5f311904d973652180c705

# Constants
BINARY_NAME = template-go
BINARY_NAME = $(shell basename `pwd`)
TARGET_FOLDER = target
DIST_FOLDER = $(TARGET_FOLDER)/dist
DOCKER_IMAGE_GOLANG_CI = golangci/golangci-lint:v1.62
Expand All @@ -17,13 +17,13 @@ COLOR_RESET = $(shell tput -Txterm sgr0)
VERSION := $(shell cat version)
COMMIT := $(shell git log -1 --format='%H')
LD_FLAGS = \
-X okp4/template-go/internal/version.Name=$(BINARY_NAME) \
-X okp4/template-go/internal/version.Version=$(VERSION) \
-X okp4/template-go/internal/version.Commit=$(COMMIT)
-X github.com/axone-protocol/wallet-extractor/internal/version.Name=$(BINARY_NAME) \
-X github.com/axone-protocol/wallet-extractor/internal/version.Version=$(VERSION) \
-X github.com/axone-protocol/wallet-extractor/internal/version.Commit=$(COMMIT)
BUILD_FLAGS := -ldflags '$(LD_FLAGS)'

# Commands
GO_BUiLD := CGO_ENABLED=0 go build $(BUILD_FLAGS)
GO_BUILD := CGO_ENABLED=0 go build $(BUILD_FLAGS)

# Environments
ENVIRONMENTS = \
Expand Down Expand Up @@ -103,5 +103,5 @@ help: ## Show this help.
# $2: architecture (GOARCH)
# $3: filename of the executable generated
define build-go
GOOS=$1 GOARCH=$2 $(GO_BUiLD) -o $3 ${CMD_ROOT}
GOOS=$1 GOARCH=$2 $(GO_BUILD) -o $3 ${CMD_ROOT}
endef
27 changes: 27 additions & 0 deletions cmd/delegators.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package cmd

import (
"github.com/axone-protocol/wallet-extractor/pkg/delegators"
"github.com/spf13/cobra"
)

const (
flagChainName = "chain-name"
)

var extractDelegatorsCmd = &cobra.Command{
Use: "delegators [source] [dest]",
Short: "Extract all delegators into CSV files",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
chainName, _ := cmd.Flags().GetString(flagChainName)

return delegators.Extract(chainName, args[0], args[1])
},
}

func init() {
extractCmd.AddCommand(extractDelegatorsCmd)

extractDelegatorsCmd.Flags().StringP(flagChainName, "n", "cosmos", "Name of the chain")
}
14 changes: 14 additions & 0 deletions cmd/extract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cmd

import (
"github.com/spf13/cobra"
)

var extractCmd = &cobra.Command{
Use: "extract",
Short: "Extract data from a chain (snapshot)",
}

func init() {
rootCmd.AddCommand(extractCmd)
}
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

// rootCmd represents the base command when called without any subcommands.
var rootCmd = &cobra.Command{
Use: "template-go",
Use: "wallet-extractor",
Short: "A template fo Golang projects",
Long: "A template fo Golang projects",
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ require (
github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ=
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
Expand Down
159 changes: 159 additions & 0 deletions pkg/delegators/extract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package delegators

import (
"bufio"
"fmt"
"os"
"path"
"strings"

"github.com/axone-protocol/wallet-extractor/pkg/keeper"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/gocarina/gocsv"

"cosmossdk.io/log"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/bech32"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

func Extract(chainName, src, dst string) error {
logger := log.NewLogger(os.Stderr)

logger.Info("Extracting wallets", "source", src, "destination", dst)

keepers, err := keeper.OpenStore(src, logger)
if err != nil {
return err
}

ctx := sdk.NewContext(keepers.Store, cmtproto.Header{}, false, keepers.Logger)

validators, err := keepers.Staking.GetAllValidators(ctx)
if err != nil {
panic(err)
}

keepers.Logger.Info("Analyzing validators", "count", len(validators))

err = extractChainMetadata(ctx, chainName, keepers, dst)
if err != nil {
return err
}

return extractDelegators(ctx, chainName, keepers, validators, dst)
}

func extractDelegators(
ctx sdk.Context, chainName string, keepers *keeper.Keepers, validators []stakingtypes.Validator, destination string,
) error {
file, err := os.OpenFile(path.Join(destination, "delegations.csv"), os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)
if err != nil {
return err
}
defer file.Close()
writer := bufio.NewWriter(file)
defer writer.Flush()

prefix, err := guessPrefixFromValoper(validators[0].OperatorAddress)
if err != nil {
return err
}

config := sdk.GetConfig()

keepers.Bank.IterateAllBalances(ctx, func(addr sdk.AccAddress, _ sdk.Coin) (stop bool) {
for _, val := range validators {
if config.GetBech32AccountAddrPrefix() != prefix {
config.SetBech32PrefixForValidator(
fmt.Sprintf("%svaloper", prefix),
fmt.Sprintf("%svaloperpub", prefix),
)
}

valAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress)
if err != nil {
panic(err)
}
delegation, err := keepers.Staking.GetDelegation(ctx, addr, valAddr)
if err != nil {
continue
}

record := Delegations{
ChainName: chainName,
DelegatorNativeAddr: delegation.DelegatorAddress,
DelegatorCosmosAddr: convertAndEncodeMust("cosmos", delegation.DelegatorAddress),
DelegatorAxoneAddr: convertAndEncodeMust("axone", delegation.DelegatorAddress),
ValidatorAddr: delegation.ValidatorAddress,
Shares: delegation.Shares.String(),
}

v, err := gocsv.MarshalStringWithoutHeaders(&[]Delegations{record})
if err != nil {
panic(err)
}

_, err = writer.WriteString(v)
if err != nil {
panic(err)
}
}

return false
})

return nil
}

func extractChainMetadata(
_ sdk.Context, chainName string, keepers *keeper.Keepers, destination string,
) error {
file, err := os.OpenFile(path.Join(destination, "metadatas.csv"), os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)
if err != nil {
return err
}
defer file.Close()
writer := bufio.NewWriter(file)
defer writer.Flush()

record := Chains{
Name: chainName,
StoreVersion: fmt.Sprintf("%d", keepers.Store.LastCommitID().Version),
StoreHash: fmt.Sprintf("%X", keepers.Store.LastCommitID().Hash),
}

v, err := gocsv.MarshalStringWithoutHeaders(&[]Chains{record})
if err != nil {
panic(err)
}

_, err = writer.WriteString(v)
if err != nil {
panic(err)
}

return nil
}

func convertAndEncodeMust(hrp string, bech string) string {
_, bytes, err := bech32.DecodeAndConvert(bech)
if err != nil {
panic(err)
}

encoded, err := bech32.ConvertAndEncode(hrp, bytes)
if err != nil {
panic(err)
}

return encoded
}

func guessPrefixFromValoper(valoper string) (string, error) {
if idx := strings.Index(valoper, "valoper"); idx != -1 {
return valoper[:idx], nil
}
return "", fmt.Errorf("valoper not found in operator address: %s", valoper)
}
17 changes: 17 additions & 0 deletions pkg/delegators/record.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package delegators

type Chains struct {
Name string `csv:"name"`
StoreVersion string `csv:"store_version"`
StoreHash string `csv:"store_hash"`
}

type Delegations struct {
ChainName string `csv:"chain_name"`
DelegatorNativeAddr string `csv:"delegator_native_addr"`
DelegatorCosmosAddr string `csv:"delegator_cosmos_addr"`
DelegatorAxoneAddr string `csv:"delegator_axone_addr"`

ValidatorAddr string `csv:"validator_addr"`
Shares string `csv:"shares"`
}
18 changes: 7 additions & 11 deletions pkg/keeper.go → pkg/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pkg
package keeper

import (
"fmt"
Expand Down Expand Up @@ -42,15 +42,7 @@ type Keepers struct {
}

// OpenStore opens an existing store at the given path and returns the keepers for the store.
func OpenStore(dbPath, addressPrefix string) (*Keepers, error) {
config := sdk.GetConfig()
config.SetBech32PrefixForValidator(
fmt.Sprintf("%svaloper", addressPrefix),
fmt.Sprintf("%svaloperpub", addressPrefix),
)
config.Seal()

logger := log.NewNopLogger()
func OpenStore(dbPath string, logger log.Logger) (*Keepers, error) {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey,
banktypes.StoreKey,
Expand Down Expand Up @@ -105,6 +97,7 @@ func newCodec() (*codec.ProtoCodec, error) {
return nil, err
}
std.RegisterInterfaces(interfaceRegistry)
interfaceRegistry.RegisterInterface("/cosmos.auth.v1beta1.BaseAccount", (*sdk.AccountI)(nil))

return codec.NewProtoCodec(interfaceRegistry), nil
}
Expand Down Expand Up @@ -154,6 +147,8 @@ func newStakingKeeper(
func newCommitMultiStore(
dbPath string, keys map[string]*storetypes.KVStoreKey, logger log.Logger,
) (storetypes.CommitMultiStore, error) {
logger.Debug("Opening store", "path", dbPath)

db, err := dbm.NewDB("application", dbm.GoLevelDBBackend, dbPath)
if err != nil {
return nil, err
Expand All @@ -169,7 +164,8 @@ func newCommitMultiStore(
}

commitID := ms.LastCommitID()
logger.Info("Loaded store at version: %d, hash: %X\n", commitID.Version, commitID.Hash)

logger.Debug("Store loaded", "version", commitID.Version, "hash", fmt.Sprintf("%x", commitID.Hash))

return ms, nil
}

0 comments on commit f34cdf7

Please sign in to comment.