-
Notifications
You must be signed in to change notification settings - Fork 547
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 node command with bank query and send #2539
feat: add node command with bank query and send #2539
Conversation
Bounty address: cosmos1zra3wz596n0qc898myceka3q23x9rk8fuw65c7
func flagSetPagination(query string) *flag.FlagSet { | ||
fs := flag.NewFlagSet("", flag.ContinueOnError) | ||
|
||
fs.Uint64(flagPage, 1, fmt.Sprintf("pagination page of %s to query for. This sets offset to a multiple of limit", query)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Flags and the code below is pretty much a copy paste from cosmos-sdk
flagGenerateOnly = "generate-only" | ||
|
||
gasFlagAuto = "auto" | ||
flagGasPrices = "gas-prices" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opted to only include gas and gas-prices. The gas-adjustment flag doesn't seem to be necessary since we already have logic in cosmosclient to increase gas when using "auto"
|
||
func flagSetGasFlags() *flag.FlagSet { | ||
fs := flag.NewFlagSet("", flag.ContinueOnError) | ||
fs.String(flagGasPrices, "", "Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom)") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of these strings are just copy pasted from cosmos-sdk
@@ -51,7 +51,7 @@ const ( | |||
|
|||
// Registry for accounts. | |||
type Registry struct { | |||
homePath string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed this to avoid confusion. This is really the keyring dir, and was already used as such.
@@ -0,0 +1,66 @@ | |||
package cosmosclient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this out of the cosmosclient file so that any non-generic functionality is separated into files
func (c Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { | ||
return c.RPC.Status(ctx) | ||
} | ||
func performQuery[T any](c Client, q func() (T, error)) (T, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just to have a wrapper function that locks the bech32 prefix for queries. See how it is used in the bank client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool!
func (c Client) BroadcastTxWithProvision(accountName string, msgs ...sdktypes.Msg) ( | ||
gas uint64, broadcast func() (Response, error), err error) { | ||
unsignedTx client.TxBuilder, broadcast func() (Response, error), err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed for this to return the unsigned transaction instead so that this could be used for generate-only commands. You simply don't call the broadcast function.
You can still get the gas from the unsigned tx.
|
||
const testAccountMnemonic = "develop mansion drum glow husband trophy labor jelly fault run pause inside jazz foil page injury foam oppose fruit chunk segment morning series nation" | ||
|
||
func TestAccount(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized there were no integration tests for account, so I added some (they are really fast)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works like a charm! 🎊 👏
ignite/cmd/node_query.go
Outdated
} | ||
|
||
func getPagination(cmd *cobra.Command) (*query.PageRequest, error) { | ||
pageKey, _ := cmd.Flags().GetString(flagPageKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about wrapping al these under a single var
block, so it can be better fmt'ed?
ignite/pkg/cosmosclient/bank.go
Outdated
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
) | ||
|
||
func (c Client) BankBalances(address string, pagination *query.PageRequest) (sdk.Coins, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (c Client) BankBalances(address string, pagination *query.PageRequest) (sdk.Coins, error) { | |
func (c Client) BankBalances(ctx context.Context, address string, pagination *query.PageRequest) (sdk.Coins, error) { |
and same for others
ignite/pkg/cosmosclient/bank.go
Outdated
} | ||
|
||
_, err := c.BroadcastTx(fromAccountName, msg) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if err != nil { | |
return err |
func NewNodeQueryBankBalances() *cobra.Command { | ||
c := &cobra.Command{ | ||
Use: "balances [address]", | ||
Short: "Query for account balances by address", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Short: "Query for account balances by address", | |
Short: "Query for account balances by account name or address", |
|
||
func NewNodeQueryBankBalances() *cobra.Command { | ||
c := &cobra.Command{ | ||
Use: "balances [address]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use: "balances [address]", | |
Use: "balances [account-name|address]", |
Pagination: pagination, | ||
} | ||
|
||
resp, err := performQuery[*banktypes.QueryAllBalancesResponse](c, func() (*banktypes.QueryAllBalancesResponse, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool generics!
|
||
commit, err := node.Commit(ctx, &height) | ||
func (c Client) GenerateTx(accountName string, msgs ...sdktypes.Msg) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (c Client) GenerateTx(accountName string, msgs ...sdktypes.Msg) (string, error) { |
What if we
- drop this func
- rename/refactor
BroadcastTxWithProvision
toCreateTx
(because it doesn't really broadcast by default)
func CreateTx(accountName string, msgs ...sdktypes.Msg) (txService TxService, err error)
type TxService struct {
client.TxBuilder
}
// Gas is gas decided to use for this tx.
// either calculated or configured by the caller.
func (s TxService) Gas() uint64 {}
// Broadcast signs and broadcasts this tx.
func (s TxService) Broadcast() error {}
func (s TxService) EncodeJSON() []byte {}
And we call CreateTx
in the cmd, then string(TxService.EncodeJSON())
Can you please check if we really need an accountName
param in CreateTx
? I see in the code that we use it to set these before preparing the broadcast func. Looks like this has to be set anyway even if we just want to create an unsigned tx, can you please confirm that? Otherwise we can move the accountName
param to TxService.Broadcast(accountName string)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good idea. I was indeed confused by that naming, so cleaning this up would be great. Will do!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilgooz I did most of the work for this and there is one thing that is making accountName necessary in the current design.
It is needed for the gas simulation (it will fail without it because of sequence mismatch).
So the question becomes: should we
- Pre-calculate gas in CreateTx similar to what has been done now
or - Not (if so, should we do it only when asked in Gas()?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I think let's stick with the current API, option 1, where we get the accountName in CreateTx and calculate the gas beforehand. Otherwise the API will be a bit more complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ilgooz I made the changes. Take a look at the design and see if it makes sense to you.
func (c Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { | ||
return c.RPC.Status(ctx) | ||
} | ||
func performQuery[T any](c Client, q func() (T, error)) (T, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool!
@@ -143,6 +150,18 @@ func WithUseFaucet(faucetAddress, denom string, minAmount uint64) Option { | |||
} | |||
} | |||
|
|||
func WithGas(gas string) Option { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add comments to the method, same for WithGasPrices
|
||
// Bech32Address returns the bech32 address, with the correct prefix, from account name or address. | ||
func (c Client) Bech32Address(accountNameOrAddress string) (string, error) { | ||
unlockFn := c.lockBech32Prefix() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unlockFn := c.lockBech32Prefix() | |
defer c.lockBech32Prefix()() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this. I'll do it, but I just wasn't sure if this really reads very clearly (it sort of looks like we're deferring the locking).
return c.RPC.Status(ctx) | ||
} | ||
func performQuery[T any](c Client, q func() (T, error)) (T, error) { | ||
unlockFn := c.lockBech32Prefix() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unlockFn := c.lockBech32Prefix() | |
defer c.lockBech32Prefix()() |
defer mconf.Unlock() | ||
config := sdktypes.GetConfig() | ||
config.SetBech32PrefixForAccount(c.addressPrefix, c.addressPrefix+"pub") | ||
unlockFn := c.lockBech32Prefix() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unlockFn := c.lockBech32Prefix() | |
defer c.lockBech32Prefix()() |
return err | ||
} | ||
|
||
session.Println("Transaction broadcast successful!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
session.Println("Transaction broadcast successful!") | |
session.StopSpinner() | |
session.Println("Transaction broadcast successful!") |
At this point spinner should be stopped manually
rows = append(rows, []string{fmt.Sprintf("%s", b.Amount), b.Denom}) | ||
} | ||
|
||
return session.PrintTable([]string{"Amount", "Denom"}, rows...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return session.PrintTable([]string{"Amount", "Denom"}, rows...) | |
session.StopSpinner() | |
return session.PrintTable([]string{"Amount", "Denom"}, rows...) |
ignite/pkg/cosmosclient/txservice.go
Outdated
|
||
// EncodeJSON encodes the transaction as a json string | ||
func (s TxService) EncodeJSON() ([]byte, error) { | ||
json, err := s.client.context.TxConfig.TxJSONEncoder()(s.txBuilder.GetTx()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json, err := s.client.context.TxConfig.TxJSONEncoder()(s.txBuilder.GetTx()) | |
return s.client.context.TxConfig.TxJSONEncoder()(s.txBuilder.GetTx()) |
@ilgooz Just to make sure, you're not waiting for me to do anything here right? |
Hey Gjermund! I'm refactoring some bits, will push some commits soon! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not require address prefix when querying, if the account address is used while querying
I don't think we are. I just tested it and it seems to work fine without the prefix. Updating the tests to show this now. |
@bjaanes oh okay, that comment was more like a comment to remind to myself during review, sorry for the confusion! |
I was making some fixes and improvements on this PR and also tweaking the integration package's API. My changes are in this branch within a50618c commit. @jeronimoalbi @tbruyelle can you please take a look and maybe continue from here? So we can add those changes into this PR and finally merge it. |
Can we close this? |
Bounty address: cosmos1zra3wz596n0qc898myceka3q23x9rk8fuw65c7
Closes #2489