Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add airdrop plugin #18

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions airdrop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Ignite Airdrop App

Official [Ignite CLI](https://ignite.com/cli) apps repository.

Each directory in the root of this repo must be a Go module containing
an Ignite App package, each one with its own `go.mod` file.

### How to test

Run the raw airdrop command to generate the raw data
```shell
go run cmd/debug/debug.go airdrop raw testdata/genesis.json 2> raw-snapshot.json
```

Run the process command to generate the claim records
```shell
go run cmd/debug/debug.go airdrop process testdata/config.yml raw-snapshot.json 2> snapshot.json
```

Generate the new genesis json with the claimable state based on the output genesis
```shell
go run cmd/debug/debug.go airdrop genesis testdata/config.yml raw-snapshot.json testdata/genesis.json
```


Or you can only use the generate command to run all four above with one command
```shell
go run cmd/debug/debug.go airdrop generate testdata/config.yml testdata/genesis.json testdata/genesis.json
```

214 changes: 214 additions & 0 deletions airdrop/cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package cmd

import (
"encoding/json"
"fmt"

"github.com/spf13/cobra"

"github.com/ignite/apps/airdrop/pkg/config"
"github.com/ignite/apps/airdrop/pkg/genesis"
"github.com/ignite/apps/airdrop/pkg/snapshot"
)

func NewAirdrop() *cobra.Command {
c := &cobra.Command{
Use: "airdrop",
Short: "Utility tool to create snapshots for an airdrop",
}

c.AddCommand(
NewAirdropGenerate(),
NewAirdropRaw(),
NewAirdropProcess(),
NewAirdropGenesis(),
)

return c
}

func NewAirdropRaw() *cobra.Command {
return &cobra.Command{
Use: "raw [input-genesis]",
Short: "Generate raw airdrop data based on the input genesis",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// parse the genesis input to get the current stake state
genState, err := genesis.GetGenStateFromPath(args[0])
if err != nil {
return err
}

// get only the essential info from input genesis
// to generate the snapshot the raw snapshot object
s, err := snapshot.Generate(genState.AppState)
if err != nil {
return err
}

// export snapshot json
snapshotJSON, err := json.MarshalIndent(s, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal snapshot: %w", err)
}

cmd.Println(string(snapshotJSON))
return nil
},
}
}

func NewAirdropProcess() *cobra.Command {
return &cobra.Command{
Use: "process [airdrop-config] [raw-snapshot]",
Short: "Process the airdrop raw data based on the config file",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
var (
airdropConfig = args[0]
rawSnapshot = args[1]
)

c, err := config.ParseConfig(airdropConfig)
if err != nil {
return err
}

s, err := snapshot.ParseSnapshot(rawSnapshot)
if err != nil {
return err
}

records := make(snapshot.Records, 0)
for _, snap := range c.Snapshots {
record := s.ApplyConfig(snapshot.ConfigType(snap.Type), snap.Denom, snap.Formula, snap.Excluded)
records = append(records, record)
}
filter := records.Sum()

// export filter json
filterJSON, err := json.MarshalIndent(filter, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal snapshot: %w", err)
}

cmd.Println(string(filterJSON))
return nil
},
}
}

func NewAirdropGenesis() *cobra.Command {
return &cobra.Command{
Use: "genesis [airdrop-config] [raw-snapshot] [output-genesis]",
Short: "Generate and add quadratic airdrop claim record to the output genesis based on the raw data and airdrop config",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
var (
airdropConfig = args[0]
rawSnapshot = args[1]
outputGenesis = args[2]
)

c, err := config.ParseConfig(airdropConfig)
if err != nil {
return err
}

// parse the genesis output to get the current stake state
genState, err := genesis.GetGenStateFromPath(outputGenesis)
if err != nil {
return err
}

s, err := snapshot.ParseSnapshot(rawSnapshot)
if err != nil {
return err
}

// apply the config file to the raw data to generate the claim records
records := make(snapshot.Records, 0)
for _, snap := range c.Snapshots {
record := s.ApplyConfig(snapshot.ConfigType(snap.Type), snap.Denom, snap.Formula, snap.Excluded)
records = append(records, record)
}
record := records.Sum()

// add claim records to the output genesis
if err := genState.AddFromClaimRecord(c.AirdropToken, record.ClaimRecords()); err != nil {
return err
}

// export snapshot json
genesisJSON, err := json.MarshalIndent(genState, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal snapshot: %w", err)
}

cmd.Println(string(genesisJSON))
return nil
},
}
}

func NewAirdropGenerate() *cobra.Command {
return &cobra.Command{
Use: "generate [airdrop-config] [input-genesis] [output-genesis]",
Short: "Generate and add quadratic airdrop claim records to the output genesis based on the input genesis stake values and airdrop config",
Args: cobra.ExactArgs(3),
RunE: func(cmd *cobra.Command, args []string) error {
var (
airdropConfig = args[0]
inputGenesis = args[1]
outputGenesis = args[2]
)

// parse the airdrop config yaml
c, err := config.ParseConfig(airdropConfig)
if err != nil {
return err
}

// parse the genesis input to get the current stake state
inGenState, err := genesis.GetGenStateFromPath(inputGenesis)
if err != nil {
return err
}

// parse the genesis output state to be modified
outGenState, err := genesis.GetGenStateFromPath(outputGenesis)
if err != nil {
return err
}

// get only the essential info from input genesis
// to generate the snapshot the raw snapshot object
s, err := snapshot.Generate(inGenState.AppState)
if err != nil {
return err
}

// apply the config file to the raw data to generate the claim records
records := make(snapshot.Records, 0)
for _, snap := range c.Snapshots {
record := s.ApplyConfig(snapshot.ConfigType(snap.Type), snap.Denom, snap.Formula, snap.Excluded)
records = append(records, record)
}
filter := records.Sum()

// add claim records to the output genesis
if err := outGenState.AddFromClaimRecord(c.AirdropToken, filter.ClaimRecords()); err != nil {
return err
}

// export snapshot json
genesisJSON, err := json.MarshalIndent(outGenState, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal snapshot: %w", err)
}

cmd.Println(string(genesisJSON))
return nil
},
}
}
23 changes: 23 additions & 0 deletions airdrop/cmd/debug/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import (
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/ignite/apps/airdrop/cmd"
)

var rootCmd = &cobra.Command{
Use: "airdrop",
Short: "debug command for CLI airdrop plugin",
}

func main() {
rootCmd.AddCommand(cmd.NewAirdrop())
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
Loading