-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initialized with Ignite CLI * add wasm commands * scaffold chain wasm * remove wasm* from gitignore * use chain into the scaffold struct * add config command * fix client genesis * format code * add tests without test cases * add some test cases * add test cases for the goanalysis package * add comments * remove unused file * remove duplicated .gitignore * add wasm integration verification * add integration tests * Update official/wasm/pkg/goanalysis/goanalysis.go Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com> * Update official/wasm/services/scaffolder/wasm.go Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com> * Update official/wasm/cmd/config.go Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com> * Update official/wasm/main.go Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com> * Update official/wasm/go.mod Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com> * Update official/wasm/pkg/config/config_test.go Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com> * usa github.com/ignite/apps/wasm namespace instead only wasm * apply some comments suggestions * run go mod tidy * add configurable wasm version * add readme --------- Co-authored-by: Developer Experience team at Ignite <hello@ignite.com> Co-authored-by: Pantani <Pantani> Co-authored-by: Jerónimo Albi <jeronimo.albi@gmail.com>
- Loading branch information
1 parent
607099f
commit 3c71122
Showing
23 changed files
with
3,891 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Wasm | ||
|
||
`wasm` is an app developed for [Ignite CLI](https://github.com/ignite/cli). | ||
|
||
The app adds `ignite wasm` commands to add a [CosmWasm](https://cosmwasm.com/) integration into a chain. | ||
|
||
## How to use | ||
|
||
- Install the Wasm app: | ||
```shell | ||
ignite app install -g github.com/ignite/apps/wasm | ||
``` | ||
|
||
- You must scaffold a new chain with version `v28.2.1` or greater. Or migrate your chain using the [Ignite migration guides](https://docs.ignite.com/migration). | ||
|
||
- Now you can add a Wasm support to your chain by running this command into the chain directory: | ||
```shell | ||
ignite wasm add | ||
``` | ||
|
||
- The command will automatically add the Wasm integration into your code and the Wasm config into your chain config. But if your chain is not initiated yet, the chain config does not exist, so you need to add the Wasm config later running: | ||
```shell | ||
ignite wasm add | ||
``` | ||
|
||
_All commands should be run in the chain directory._ | ||
|
||
## Developer instruction | ||
|
||
- clone this repo locally | ||
- Run `ignite app add -g /absolute/path/to/app/wasm` to add the app to global config | ||
- `ignite wasm` command is now available with the local version of the app. | ||
|
||
Then repeat the following loop: | ||
|
||
- Hack on the app code | ||
- Rerun `ignite wasm` to recompile the app and test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/blang/semver/v4" | ||
"github.com/ignite/cli/v28/ignite/pkg/cliui" | ||
"github.com/ignite/cli/v28/ignite/pkg/placeholder" | ||
"github.com/ignite/cli/v28/ignite/services/chain" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/ignite/apps/wasm/services/scaffolder" | ||
) | ||
|
||
// NewWasmAdd add wasm integration to a chain. | ||
func NewWasmAdd() *cobra.Command { | ||
c := &cobra.Command{ | ||
Use: "add", | ||
Short: "Add wasm support", | ||
Args: cobra.NoArgs, | ||
RunE: wasmAddExecuteHandler, | ||
} | ||
|
||
flagSetPath(c) | ||
flagSetHome(c) | ||
flagSetWasmConfigs(c) | ||
flagSetWasmVersion(c) | ||
|
||
return c | ||
} | ||
|
||
func wasmAddExecuteHandler(cmd *cobra.Command, args []string) error { | ||
session := cliui.New(cliui.StartSpinnerWithText(statusScaffolding)) | ||
defer session.End() | ||
|
||
var ( | ||
simulationGasLimit = getSimulationGasLimit(cmd) | ||
smartQueryGasLimit = getSmartQueryGasLimit(cmd) | ||
memoryCacheSize = getMemoryCacheSize(cmd) | ||
wasmVersion = getWasmVersion(cmd) | ||
) | ||
|
||
wasmSemVer, err := semver.Parse(wasmVersion) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
c, err := newChainWithHomeFlags(cmd, 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.AddWasm( | ||
cmd.Context(), | ||
placeholder.New(), | ||
scaffolder.WithWasmVersion(wasmSemVer), | ||
scaffolder.WithSimulationGasLimit(simulationGasLimit), | ||
scaffolder.WithSmartQueryGasLimit(smartQueryGasLimit), | ||
scaffolder.WithMemoryCacheSize(memoryCacheSize), | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
modificationsStr, err := sourceModificationToString(sm) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
session.Println(modificationsStr) | ||
session.Printf("\n🎉 CosmWasm added (`%[1]v`).\n\n", c.AppPath()) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
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/spf13/cobra" | ||
) | ||
|
||
// NewWasm creates a new wasm command that holds | ||
// some other sub commands related to CosmWasm. | ||
func NewWasm() *cobra.Command { | ||
c := &cobra.Command{ | ||
Use: "wasm [command]", | ||
Aliases: []string{"w"}, | ||
Short: "Ignite wasm integration", | ||
SilenceUsage: true, | ||
SilenceErrors: true, | ||
} | ||
|
||
// add sub commands. | ||
c.AddCommand( | ||
NewWasmAdd(), | ||
NewWasmConfig(), | ||
) | ||
return c | ||
} | ||
|
||
const ( | ||
flagPath = "path" | ||
flagHome = "home" | ||
flagVersion = "version" | ||
|
||
statusScaffolding = "Scaffolding..." | ||
statusAddingConfig = "Adding config..." | ||
|
||
defaultWasmVersion = "v0.50.0" | ||
) | ||
|
||
var ( | ||
modifyPrefix = colors.Modified("modify ") | ||
createPrefix = colors.Success("create ") | ||
removePrefix = func(s string) string { | ||
return strings.TrimPrefix(strings.TrimPrefix(s, modifyPrefix), createPrefix) | ||
} | ||
) | ||
|
||
func flagSetPath(cmd *cobra.Command) { | ||
cmd.Flags().StringP(flagPath, "p", ".", "path of the app") | ||
} | ||
|
||
func flagSetHome(cmd *cobra.Command) { | ||
cmd.Flags().String(flagHome, "", "directory where the blockchain node is initialized") | ||
} | ||
|
||
func flagSetWasmVersion(cmd *cobra.Command) { | ||
cmd.Flags().String(flagVersion, defaultWasmVersion, "wasmd semantic version") | ||
} | ||
|
||
func flagSetWasmConfigs(cmd *cobra.Command) { | ||
cmd.Flags().Uint64(flagSimulationGasLimit, 0, "the max gas to be used in a tx simulation call. When not set the consensus max block gas is used instead") | ||
cmd.Flags().Uint64(flagSmartQueryGasLimit, 3_000_000, "the max gas to be used in a smart query contract call") | ||
cmd.Flags().Uint64(flagMemoryCacheSize, 100, "memory cache size in MiB not bytes") | ||
} | ||
|
||
func getPath(cmd *cobra.Command) string { | ||
path, _ := cmd.Flags().GetString(flagPath) | ||
return path | ||
} | ||
|
||
func getHome(cmd *cobra.Command) string { | ||
home, _ := cmd.Flags().GetString(flagHome) | ||
return home | ||
} | ||
|
||
func getWasmVersion(cmd *cobra.Command) string { | ||
version, _ := cmd.Flags().GetString(flagVersion) | ||
version = strings.Replace(version, "v", "", 1) | ||
return version | ||
} | ||
|
||
func getSimulationGasLimit(cmd *cobra.Command) uint64 { | ||
simulationGasLimit, _ := cmd.Flags().GetUint64(flagSimulationGasLimit) | ||
return simulationGasLimit | ||
} | ||
|
||
func getSmartQueryGasLimit(cmd *cobra.Command) uint64 { | ||
smartQueryGasLimit, _ := cmd.Flags().GetUint64(flagSmartQueryGasLimit) | ||
return smartQueryGasLimit | ||
} | ||
|
||
func getMemoryCacheSize(cmd *cobra.Command) uint64 { | ||
memoryCacheSize, _ := cmd.Flags().GetUint64(flagMemoryCacheSize) | ||
return memoryCacheSize | ||
} | ||
|
||
// newChainWithHomeFlags create new *chain.Chain with home and path flags. | ||
func newChainWithHomeFlags(cmd *cobra.Command, chainOption ...chain.Option) (*chain.Chain, error) { | ||
// Check if custom home is provided | ||
if home := getHome(cmd); home != "" { | ||
chainOption = append(chainOption, chain.HomePath(home)) | ||
} | ||
|
||
appPath := getPath(cmd) | ||
absPath, err := filepath.Abs(appPath) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package cmd | ||
|
||
import ( | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Test_relativePath(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
appPath string | ||
want string | ||
}{ | ||
{ | ||
name: "Relative path within current directory", | ||
appPath: "subdir/file.txt", | ||
want: "subdir/file.txt", | ||
}, | ||
{ | ||
name: "Relative path outside current directory", | ||
appPath: "/path/file.txt", | ||
want: "../../../../../../../../../../../path/file.txt", | ||
}, | ||
{ | ||
name: "App path is current directory", | ||
appPath: ".", | ||
want: ".", | ||
}, | ||
{ | ||
name: "App path is parent directory", | ||
appPath: "..", | ||
want: "..", | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
absPath, err := filepath.Abs(tt.appPath) | ||
require.NoError(t, err) | ||
got, err := relativePath(absPath) | ||
require.NoError(t, err) | ||
require.Equal(t, tt.want, got) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package cmd | ||
|
||
import ( | ||
"os" | ||
|
||
"github.com/ignite/cli/v28/ignite/pkg/cliui" | ||
"github.com/ignite/cli/v28/ignite/pkg/errors" | ||
"github.com/ignite/cli/v28/ignite/services/chain" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/ignite/apps/wasm/pkg/config" | ||
) | ||
|
||
const ( | ||
// flagSimulationGasLimit is the max gas to be used in a tx simulation call. | ||
// When not set the consensus max block gas is used instead | ||
flagSimulationGasLimit = "simulation-gas-limit" | ||
// flagSmartQueryGasLimit is the max gas to be used in a smart query contract call | ||
flagSmartQueryGasLimit = "query-gas-limit" | ||
// flagMemoryCacheSize in MiB not bytes | ||
flagMemoryCacheSize = "memory-cache-size" | ||
) | ||
|
||
// NewWasmConfig add wasm config to a chain. | ||
func NewWasmConfig() *cobra.Command { | ||
c := &cobra.Command{ | ||
Use: "config", | ||
Short: "Add wasm config support", | ||
Args: cobra.NoArgs, | ||
RunE: wasmConfigExecuteHandler, | ||
} | ||
|
||
flagSetPath(c) | ||
flagSetHome(c) | ||
flagSetWasmConfigs(c) | ||
|
||
return c | ||
} | ||
|
||
func wasmConfigExecuteHandler(cmd *cobra.Command, args []string) error { | ||
session := cliui.New(cliui.StartSpinnerWithText(statusAddingConfig)) | ||
defer session.End() | ||
|
||
var ( | ||
simulationGasLimit = getSimulationGasLimit(cmd) | ||
smartQueryGasLimit = getSmartQueryGasLimit(cmd) | ||
memoryCacheSize = getMemoryCacheSize(cmd) | ||
) | ||
|
||
c, err := newChainWithHomeFlags(cmd, chain.WithOutputer(session), chain.CollectEvents(session.EventBus())) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
configTOML, err := c.ConfigTOMLPath() | ||
if _, err := os.Stat(configTOML); os.IsNotExist(err) { | ||
return errors.Errorf("chain %s not initialized yet (%s)", c.Name(), c.AppPath()) | ||
} | ||
|
||
if err := config.AddWasm( | ||
configTOML, | ||
config.WithSimulationGasLimit(simulationGasLimit), | ||
config.WithSmartQueryGasLimit(smartQueryGasLimit), | ||
config.WithMemoryCacheSize(memoryCacheSize), | ||
); err != nil { | ||
return err | ||
} | ||
session.Printf("\n🎉 CosmWasm config added at `%[1]v`.\n\n", configTOML) | ||
|
||
return nil | ||
} |
Oops, something went wrong.