Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
1 change: 1 addition & 0 deletions .changelog/unreleased/chore/21-prep-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Update go.mod to v2 ([#21](https://github.com/noble-assets/jester/pull/21)).
4 changes: 2 additions & 2 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ builds:
env:
- CGO_ENABLED=0
ldflags:
- -X jester.noble.xyz/cmd.Version={{ .Version }}
- -X jester.noble.xyz/cmd.Commit={{ .Commit }}
- -X jester.noble.xyz/v2/cmd.Version={{ .Version }}
- -X jester.noble.xyz/v2/cmd.Commit={{ .Commit }}
goos:
- linux
- darwin
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
COMMIT := $(shell git log -1 --format='%H')
VERSION := $(shell echo $(shell git describe --tags --always --dirty --match "v*"))

ldflags = -X jester.noble.xyz/cmd.Version=$(VERSION) \
-X jester.noble.xyz/cmd.Commit=$(COMMIT)
ldflags = -X jester.noble.xyz/v2/cmd.Version=$(VERSION) \
-X jester.noble.xyz/v2/cmd.Commit=$(COMMIT)

ldflags += $(LDFLAGS)
ldflags := $(strip $(ldflags))
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
![GitHub Release](https://img.shields.io/github/v/release/noble-assets/jester?filter=v*)
![GitHub Release](https://img.shields.io/github/v/release/noble-assets/jester?filter=api%2Fv*)
![Build Workflow](https://github.com/noble-assets/jester/actions/workflows/release.yaml/badge.svg?event=push)
[![Go Reference](https://pkg.go.dev/badge/jester.noble.zyx.svg)](https://pkg.go.dev/jester.noble.xyz)
[![Go Reference](https://pkg.go.dev/badge/jester.noble.zyx.svg)](https://pkg.go.dev/jester.noble.xyz/v2)

Jester is a sidecar application designed to be run by the Noble validator set. It facilitates the implementation of the Noble Dollar, powered by M0.

Expand Down
13 changes: 9 additions & 4 deletions appstate/appstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,26 @@ import (
"os"
"strings"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/phsym/console-slog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"jester.noble.xyz/ethereum"
"jester.noble.xyz/metrics"
"jester.noble.xyz/v2/ethereum"
"jester.noble.xyz/v2/metrics"
)

// appState is the modifiable state of the application.
type AppState struct {
Home string
Log *slog.Logger
Viper *viper.Viper
Mux *http.ServeMux
Metrics *metrics.PrometheusMetrics
Config *Config
Key keyring.Keyring
cdc *codec.ProtoCodec

*ethereum.Eth
}
Expand Down Expand Up @@ -91,9 +96,9 @@ func (a *AppState) ConfigureViper(cmd *cobra.Command) {
}
})

home := viper.GetString(FlagHome)
a.Home = viper.GetString(FlagHome)

viper.AddConfigPath(home)
viper.AddConfigPath(a.Home)
viper.SetConfigType("toml")
viper.SetConfigName("config")

Expand Down
30 changes: 30 additions & 0 deletions appstate/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2025 NASD Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package appstate

import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
)

// NewCodec initializes the codec for the application.
func (a *AppState) NewCodec() {
registry := codectypes.NewInterfaceRegistry()
cryptocodec.RegisterInterfaces(registry)
a.cdc = codec.NewProtoCodec(registry)
}
54 changes: 54 additions & 0 deletions appstate/keyring.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2025 NASD Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package appstate

import (
"os"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
)

const JesterSigningKey = "jesterSigningKey"

func (a *AppState) NewKeyring() (err error) {
configureSDK()

a.Key, err = keyring.New("jester", keyring.BackendTest, a.Home, os.Stdin, a.cdc)
if err != nil {
return err
}

return nil
}

// configureSDK sets up the Cosmos SDK with the jester bech32 prefix
func configureSDK() {
config := sdk.GetConfig()
config.SetBech32PrefixForAccount("jester", "jesterpub")
config.Seal()
}

// KeyExists returns true if a Jester signing key exists in the keystore, it returns false otherwise.
func (a *AppState) KeyExists() bool {
r, err := a.Key.Key(JesterSigningKey)
if err != nil {
return false
}

return r.Name == JesterSigningKey
}
2 changes: 1 addition & 1 deletion cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package config

import (
"github.com/spf13/cobra"
"jester.noble.xyz/appstate"
"jester.noble.xyz/v2/appstate"
)

// configCmd represents the config command
Expand Down
4 changes: 2 additions & 2 deletions cmd/config/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"os"
"path/filepath"

"jester.noble.xyz/appstate"
"jester.noble.xyz/v2/appstate"

"github.com/BurntSushi/toml"
"github.com/spf13/cobra"
Expand All @@ -36,7 +36,7 @@ func initCmd(a *appstate.AppState) *cobra.Command {
populate values.`,

RunE: func(_ *cobra.Command, _ []string) error {
configPath := filepath.Join(a.Viper.GetString(appstate.FlagHome), ".jester", "config.toml")
configPath := filepath.Join(a.Home, ".jester", "config.toml")

// programmatically overwriting config file does not treat viper keys ase expected
// instead, notify user and have them delete config manually
Expand Down
2 changes: 1 addition & 1 deletion cmd/jesterd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"syscall"

"github.com/spf13/cobra"
"jester.noble.xyz/cmd"
"jester.noble.xyz/v2/cmd"
)

func main() {
Expand Down
89 changes: 89 additions & 0 deletions cmd/keys/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2025 NASD Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package keys

import (
"fmt"

"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
"jester.noble.xyz/v2/appstate"
)

const (
coinType = uint32(118)
account = uint32(0)
index = uint32(0)
mnemonicEntropySize = 256
)

var algo keyring.SignatureAlgo = hd.Secp256k1

// createCmd represents the create command to create a Jester Siging Key
func createCmd(a *appstate.AppState) *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "Create a new Jester signing key",
Long: "Create a new Jester signing key. Jester can only have one key loaded at a time.",

RunE: func(cmd *cobra.Command, _ []string) error {
k := a.Key

if a.KeyExists() {
cmd.Println("Jester's signing key already exists. Delete it before creating a new one.")
return nil
}

mnemonicStr, err := createMnemonic()
if err != nil {
return fmt.Errorf("failed to create mnemonic: %w", err)
}

keyRecord, err := k.NewAccount(appstate.JesterSigningKey, mnemonicStr, "", hd.CreateHDPath(coinType, account, index).String(), algo)
if err != nil {
return fmt.Errorf("failed to create account: %w", err)
}

addr, err := keyRecord.GetAddress()
if err != nil {
return fmt.Errorf("failed to get address: %w", err)
}

cmd.Printf("Generated new key: %s\n", addr.String())
cmd.Printf("\n\n**MNEMONIC**\n\n%s\n", mnemonicStr)

return nil
},
}

return cmd
}

// CreateMnemonic generates a new mnemonic.
func createMnemonic() (string, error) {
entropySeed, err := bip39.NewEntropy(mnemonicEntropySize)
if err != nil {
return "", err
}
mnemonic, err := bip39.NewMnemonic(entropySeed)
if err != nil {
return "", err
}
return mnemonic, nil
}
61 changes: 61 additions & 0 deletions cmd/keys/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: Apache-2.0
//
// Copyright 2025 NASD Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package keys

import (
"bufio"
"fmt"

"github.com/cosmos/cosmos-sdk/client/input"
"github.com/spf13/cobra"
"jester.noble.xyz/v2/appstate"
)

// deleteCmd represents the create command to create a Jester Siging Key
func deleteCmd(a *appstate.AppState) *cobra.Command {
cmd := &cobra.Command{
Use: "delete",
Short: "Delete Jester's signing key",

RunE: func(cmd *cobra.Command, _ []string) error {
k := a.Key

if !a.KeyExists() {
cmd.Println("No key to delete.")
return nil
}

buf := bufio.NewReader(cmd.InOrStdin())

yes, err := input.GetConfirmation("Delete Jester's signing key?", buf, cmd.ErrOrStderr())
if err != nil {
return fmt.Errorf("failed to read confirmation: %w", err)
}
if !yes {
return nil
}

k.Delete(appstate.JesterSigningKey)

cmd.Println("Jester's signing key deleted 👋")

return nil
},
}

return cmd
}
Loading