Skip to content

Commit

Permalink
feat: add fee abstraction app (#130)
Browse files Browse the repository at this point in the history
* add fee abstraction app

* add readme and cghangelog

* improve readme and changelog

* fix integration tests

* update docs

* add registry and check if sdk is greater o equal than v0.51

* bump ignite version

* Initialized with Ignite CLI

* avoid create module with feeabs name

* add more test cases and fix old cases

* simplify integration logic

* check if the app is served for integration

* bump cli

* remove v7

* Update fee-abstraction/README.md

* remove version map

---------

Co-authored-by: Developer Experience team at Ignite <hello@ignite.com>
  • Loading branch information
Pantani and Developer Experience team at Ignite authored Nov 5, 2024
1 parent 48cb66c commit c0aeb63
Show file tree
Hide file tree
Showing 17 changed files with 2,440 additions and 0 deletions.
32 changes: 32 additions & 0 deletions _registry/ignite.apps.fee-abstraction.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"appName": "fee-abstraction",
"appDescription": "Integrate the fee abstraction module from osmosis-labs to make it easy for new chains to accept the currencies of existing chains",
"ignite": ">28.5.2",
"dependencies": {},
"cosmosSDK": ">0.50.8",
"authors": [
{
"name": "Danilo Pantani",
"github": "Pantani"
}
],
"repositoryUrl": "https://github.com/ignite/apps",
"documentationUrl": "https://github.com/ignite/apps/blob/main/fee-abstraction/README.md",
"license": {
"name": "MIT",
"url": "https://github.com/ignite/apps/blob/main/LICENSE"
},
"keywords": [
"scaffolder",
"fee-abstraction",
"osmosis",
"osmosis-labs",
"cli",
"cosmos-sdk",
"ignite app"
],
"supportedPlatforms": [
"mac",
"linux"
]
}
3 changes: 3 additions & 0 deletions app.ignite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ apps:
explorer:
description: Easy to use terminal chain explorer for testing your Ignite blockchains
path: ./explorer
fee-abstraction:
description: Integrate the fee abstraction module from osmosis-labs to make it easy for new chains to accept the currencies of existing chains
path: ./fee-abstraction
hermes:
description: A wrapper around the hermes IBC relayer
path: ./hermes
Expand Down
7 changes: 7 additions & 0 deletions fee-abstraction/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Fee Abstraction App Changelog

## Unreleased

## [`v0.1.0`](https://github.com/ignite/apps/releases/tag/fee-abstraction/v0.1.0)

* First release of the Fee Abstraction app compatible with Ignite >= v28.5.2
33 changes: 33 additions & 0 deletions fee-abstraction/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Fee Abstraction

The Fee Abstraction app is an extension for the [Ignite CLI](https://github.com/ignite/cli), designed to help developers seamlessly integrate the [Fee Abstraction](https://github.com/osmosis-labs/fee-abstraction) module from Osmosis Labs into their blockchain projects.

This app extends the `ignite scaffold chain` command by adding a `--fee-abstraction` flag, which automatically incorporates the Fee Abstraction module into your chain.

## Features

- Effortless Integration: Easily integrate the Fee Abstraction module into your blockchain with a single command.

## Prerequisites

- Ignite CLI version v28.5.2 or greater.
- Or migrate your chain using the [Ignite migration guides](https://docs.ignite.com/migration).
- Knowledge of blockchain development and the Fee Abstraction module.

## Installation

To install the Fee Abstraction app, it need to be globally, run the following command:

```shell
ignite app install -g github.com/ignite/apps/fee-abstraction
```

## Usage

- Now you can scaffold your chain using the fee abstraction module:

```shell
ignite s chain mars --fee-abstraction
```

This command will scaffold a new chain named `mars` with the Fee Abstraction module already integrated.
144 changes: 144 additions & 0 deletions fee-abstraction/cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package cmd

import (
"os"
"path/filepath"
"sort"
"strings"

"github.com/ignite/cli/v28/ignite/pkg/cliui/colors"
"github.com/ignite/cli/v28/ignite/pkg/xgenny"
"github.com/ignite/cli/v28/ignite/services/chain"
"github.com/ignite/cli/v28/ignite/services/plugin"
)

const (
flagVersion = "fee-abstraction-version"
flagFeeAbsModule = "fee-abstraction"
flagNoModule = "no-module"
flagPath = "path"

statusScaffolding = "Scaffolding..."

defaultFeeAbsVersion = "v8.0.2"
feeAbsModuleName = "feeabs"

ScaffoldChainHook = "scaffold-chain"
ScaffoldModuleHook = "scaffold-module"
)

var (
modifyPrefix = colors.Modified("modify ")
createPrefix = colors.Success("create ")
removePrefix = func(s string) string {
return strings.TrimPrefix(strings.TrimPrefix(s, modifyPrefix), createPrefix)
}
)

// GetCommands returns the list of fee-abstraction app commands.
func GetCommands() []*plugin.Command {
return []*plugin.Command{
{
Use: "fee-abstraction",
Short: "Integrate the fee abstraction module from osmosis-labs",
Long: "Integrate the fee abstraction module from osmosis-labs to make it easy for new chains to accept the currencies of existing chains",
},
}
}

// GetHooks returns the list of fee-abstraction app hooks.
func GetHooks() []*plugin.Hook {
return []*plugin.Hook{
{
Name: ScaffoldChainHook,
PlaceHookOn: "ignite scaffold chain",
Flags: []*plugin.Flag{
{
Name: flagFeeAbsModule,
Usage: "Create a project that includes the fee abstraction module",
DefaultValue: "false",
Type: plugin.FlagTypeBool,
},

{
Name: flagVersion,
Usage: "fee abstraction semantic version",
Shorthand: "v",
DefaultValue: defaultFeeAbsVersion,
Type: plugin.FlagTypeString,
},
},
},
{
Name: ScaffoldModuleHook,
PlaceHookOn: "ignite scaffold module",
},
}
}

func getPath(flags plugin.Flags) string {
path, _ := flags.GetString(flagPath)
return path
}

func getVersion(flags plugin.Flags) string {
version, _ := flags.GetString(flagVersion)
version = strings.Replace(version, "v", "", 1)
return version
}

// newChain create new *chain.Chain with home and path flags.
func newChain(chainFolder string, flags plugin.Flags, chainOption ...chain.Option) (*chain.Chain, error) {
appPath := getPath(flags)
absPath, err := filepath.Abs(appPath)
if err != nil {
return nil, err
}
absPath = filepath.Join(absPath, chainFolder)
return chain.New(absPath, chainOption...)
}

// sourceModificationToString output the modifications into a readable text.
func sourceModificationToString(sm xgenny.SourceModification) (string, error) {
// get file names and add prefix
var files []string
for _, modified := range sm.ModifiedFiles() {
// get the relative app path from the current directory
relativePath, err := relativePath(modified)
if err != nil {
return "", err
}
files = append(files, modifyPrefix+relativePath)
}
for _, created := range sm.CreatedFiles() {
// get the relative app path from the current directory
relativePath, err := relativePath(created)
if err != nil {
return "", err
}
files = append(files, createPrefix+relativePath)
}

// sort filenames without prefix
sort.Slice(files, func(i, j int) bool {
s1 := removePrefix(files[i])
s2 := removePrefix(files[j])

return strings.Compare(s1, s2) == -1
})

return "\n" + strings.Join(files, "\n"), nil
}

// relativePath return the relative app path from the current directory.
func relativePath(appPath string) (string, error) {
pwd, err := os.Getwd()
if err != nil {
return "", err
}
path, err := filepath.Rel(pwd, appPath)
if err != nil {
return "", err
}
return path, nil
}
79 changes: 79 additions & 0 deletions fee-abstraction/cmd/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package cmd

import (
"context"

"github.com/blang/semver/v4"
"github.com/ignite/cli/v28/ignite/pkg/cliui"
"github.com/ignite/cli/v28/ignite/pkg/errors"
"github.com/ignite/cli/v28/ignite/pkg/gomodulepath"
"github.com/ignite/cli/v28/ignite/pkg/placeholder"
"github.com/ignite/cli/v28/ignite/services/chain"
"github.com/ignite/cli/v28/ignite/services/plugin"

"github.com/ignite/apps/fee-abstraction/services/scaffolder"
)

// ExecuteScaffoldPreHook executes the scaffold pre hook.
func ExecuteScaffoldPreHook(h *plugin.ExecutedHook) error {
var (
flags = plugin.Flags(h.Hook.Flags)
noModule, _ = flags.GetBool(flagNoModule)
name = h.ExecutedCommand.Args[0]
)
if !noModule && name == feeAbsModuleName {
return errors.Errorf("cannot scaffold module with name %s", feeAbsModuleName)
}
return nil
}

// ExecuteScaffoldChainPostHook executes the scaffold chain post hook.
func ExecuteScaffoldChainPostHook(ctx context.Context, h *plugin.ExecutedHook) error {
var (
flags = plugin.Flags(h.Hook.Flags)
feeAbsModule, _ = flags.GetBool(flagFeeAbsModule)
name = h.ExecutedCommand.Args[0]
)
if !feeAbsModule {
return nil
}

session := cliui.New(cliui.StartSpinnerWithText(statusScaffolding))
defer session.End()

pathInfo, err := gomodulepath.Parse(name)
if err != nil {
return err
}

version := getVersion(flags)
semVersion, err := semver.Parse(version)
if err != nil {
return err
}

c, err := newChain(pathInfo.Root, flags, chain.WithOutputer(session), chain.CollectEvents(session.EventBus()))
if err != nil {
return err
}

sc, err := scaffolder.New(c, session)
if err != nil {
return err
}

sm, err := sc.AddFeeAbstraction(ctx, placeholder.New(), scaffolder.WithVersion(semVersion))
if err != nil {
return err
}

modificationsStr, err := sourceModificationToString(sm)
if err != nil {
return err
}

session.Println(modificationsStr)
session.Printf("\n🎉 Fee Abstraction added (`%[1]v`).\n\n", c.AppPath())

return nil
}
Loading

0 comments on commit c0aeb63

Please sign in to comment.