-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added command to generate chain link JSON
See PR #583
- Loading branch information
Showing
11 changed files
with
444 additions
and
9 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
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,101 @@ | ||
package chainlink | ||
|
||
import ( | ||
"encoding/hex" | ||
"fmt" | ||
"io/ioutil" | ||
|
||
chainlinktypes "github.com/desmos-labs/desmos/app/desmos/cmd/chainlink/types" | ||
|
||
"github.com/cosmos/cosmos-sdk/crypto/hd" | ||
"github.com/cosmos/cosmos-sdk/crypto/keyring" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/desmos-labs/desmos/app" | ||
profilescliutils "github.com/desmos-labs/desmos/x/profiles/client/utils" | ||
profilestypes "github.com/desmos-labs/desmos/x/profiles/types" | ||
) | ||
|
||
// GetCreateChainLinkJSON returns the command allowing to generate the chain link JSON | ||
// file that is required by the link-chain command | ||
func GetCreateChainLinkJSON() *cobra.Command { | ||
return &cobra.Command{ | ||
Use: "create-chain-link-json", | ||
Short: "Start an interactive prompt to create a new chain link JSON object", | ||
Long: `Start an interactive prompt to create a new chain link JSON object that can be used to later link your Desmos profile to another chain. | ||
Once you have built the JSON object using this command, you can then run the following command to complete the linkage: | ||
desmos tx profiles link-chain [/path/to/json/file.json] | ||
Note that this command will ask you the mnemonic that should be used to generate the private key of the address you want to link. | ||
The mnemonic is only used temporarily and never stored anywhere.`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
// Build the chain link reference getter | ||
getter := chainlinktypes.NewChainLinkReferencePrompt() | ||
|
||
// Get the data | ||
mnemonic, err := getter.GetMnemonic() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
chain, err := getter.GetChain() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
filename, err := getter.GetFilename() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Build che chain link JSON | ||
chainLinkJSON, err := generateChainLinkJSON(mnemonic, chain) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
cdc, _ := app.MakeCodecs() | ||
bz, err := cdc.MarshalJSON(&chainLinkJSON) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if filename != "" { | ||
if err := ioutil.WriteFile(filename, bz, 0600); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
cmd.Println(fmt.Sprintf("Chain link JSON file stored at %s", filename)) | ||
|
||
return nil | ||
}, | ||
} | ||
} | ||
|
||
// generateChainLinkJSON returns build a new ChainLinkJSON intance using the provided mnemonic and chain configuration | ||
func generateChainLinkJSON(mnemonic string, chain chainlinktypes.Chain) (profilescliutils.ChainLinkJSON, error) { | ||
// Create an in-memory keybase for signing | ||
keyBase := keyring.NewInMemory() | ||
keyName := "chainlink" | ||
_, err := keyBase.NewAccount(keyName, mnemonic, "", chain.DerivationPath, hd.Secp256k1) | ||
if err != nil { | ||
return profilescliutils.ChainLinkJSON{}, err | ||
} | ||
|
||
// Generate the proof signing it with the key | ||
key, _ := keyBase.Key(keyName) | ||
addr, _ := sdk.Bech32ifyAddressBytes(chain.Prefix, key.GetAddress()) | ||
sig, pubkey, err := keyBase.Sign(keyName, []byte(addr)) | ||
if err != nil { | ||
return profilescliutils.ChainLinkJSON{}, err | ||
} | ||
|
||
return profilescliutils.NewChainLinkJSON( | ||
profilestypes.NewBech32Address(addr, chain.Prefix), | ||
profilestypes.NewProof(pubkey, hex.EncodeToString(sig), addr), | ||
profilestypes.NewChainConfig(chain.Name), | ||
), 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,83 @@ | ||
package chainlink_test | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
cmd "github.com/desmos-labs/desmos/app/desmos/cmd/chainlink" | ||
"github.com/desmos-labs/desmos/app/desmos/cmd/chainlink/types" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/crypto/hd" | ||
"github.com/cosmos/cosmos-sdk/crypto/keyring" | ||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/desmos-labs/desmos/app" | ||
profilescliutils "github.com/desmos-labs/desmos/x/profiles/client/utils" | ||
profilestypes "github.com/desmos-labs/desmos/x/profiles/types" | ||
) | ||
|
||
// MockGetter represents a mock implementation of ChainLinkReferenceGetter | ||
type MockGetter struct{} | ||
|
||
// GetMnemonic implements ChainLinkReferenceGetter | ||
func (mock MockGetter) GetMnemonic() (string, error) { | ||
return "clip toilet stairs jaguar baby over mosquito capital speed mule adjust eye print voyage verify smart open crack imitate auto gauge museum planet rebel", nil | ||
} | ||
|
||
// GetChain implements ChainLinkReferenceGetter | ||
func (mock MockGetter) GetChain() (types.Chain, error) { | ||
return types.NewChain("Cosmos", "cosmos", "cosmos", "m/44'/118'/0'/0/0"), nil | ||
} | ||
|
||
// GetFilename implements ChainLinkReferenceGetter | ||
func (mock MockGetter) GetFilename() (string, error) { | ||
return "", nil | ||
} | ||
|
||
func TestGetCreateChainLinkJSON(t *testing.T) { | ||
cfg := sdk.GetConfig() | ||
app.SetupConfig(cfg) | ||
|
||
output := os.Stdout | ||
clientCtx := client.Context{}. | ||
WithOutput(output) | ||
|
||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.GetCreateChainLinkJSON(MockGetter{}), []string{}) | ||
require.NoError(t, err) | ||
|
||
cdc, _ := app.MakeCodecs() | ||
var data profilescliutils.ChainLinkJSON | ||
err = cdc.UnmarshalJSON(out.Bytes(), &data) | ||
require.NoError(t, err) | ||
|
||
// create a account to inmemory keybase | ||
keyBase := keyring.NewInMemory() | ||
keyName := "chainlink" | ||
_, err = keyBase.NewAccount( | ||
"chainlink", | ||
"clip toilet stairs jaguar baby over mosquito capital speed mule adjust eye print voyage verify smart open crack imitate auto gauge museum planet rebel", | ||
"", | ||
"m/44'/118'/0'/0/0", | ||
hd.Secp256k1, | ||
) | ||
require.NoError(t, err) | ||
|
||
// get key from keybase | ||
key, err := keyBase.Key(keyName) | ||
require.NoError(t, err) | ||
|
||
expected := profilescliutils.NewChainLinkJSON( | ||
profilestypes.NewBech32Address("cosmos13j7p6faa9jr8ty6lvqv0prldprr6m5xenmafnt", "cosmos"), | ||
profilestypes.NewProof( | ||
key.GetPubKey(), | ||
"c3bd014b2178d63d94b9c28e628bfcf56736de28f352841b0bb27d6fff2968d62c13a10aeddd1ebfe3b13f3f8e61f79a2c63ae6ff5cb78cb0d64e6b0a70fae57", | ||
"cosmos13j7p6faa9jr8ty6lvqv0prldprr6m5xenmafnt"), | ||
profilestypes.NewChainConfig("cosmos"), | ||
) | ||
|
||
require.Equal(t, expected, data) | ||
|
||
} |
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,19 @@ | ||
package types | ||
|
||
// Chain contains the data of a single chain | ||
type Chain struct { | ||
ID string | ||
Name string | ||
Prefix string | ||
DerivationPath string | ||
} | ||
|
||
// NewChain returns a new Chain instance | ||
func NewChain(id, name, prefix, derivationPath string) Chain { | ||
return Chain{ | ||
id, | ||
name, | ||
prefix, | ||
derivationPath, | ||
} | ||
} |
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,19 @@ | ||
package types | ||
|
||
// Config contains the data of the configuration | ||
type Config struct { | ||
Chains []Chain | ||
} | ||
|
||
// DefaultConfig returns the default config instance of the configuration | ||
func DefaultConfig() Config { | ||
return Config{ | ||
Chains: []Chain{ | ||
NewChain("Desmos", "desmos", "desmos", "m/44'/852'/0'/0/0"), | ||
NewChain("Cosmos", "cosmos", "cosmos", "m/44'/118'/0'/0/0"), | ||
NewChain("Akash", "akash", "akash", "m/44'/118'/0'/0/0"), | ||
NewChain("Osmosis", "osmosis", "osmo", "m/44'/118'/0'/0/0"), | ||
NewChain("Other", "", "", ""), | ||
}, | ||
} | ||
} |
Oops, something went wrong.