Skip to content

docs: Using agd to make queries and transactions #901

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

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 4 additions & 1 deletion main/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ module.exports = {
title: 'Agoric CLI',
path: '/guides/agoric-cli/',
collapsible: false,
children: ['/guides/agoric-cli/'],
children: [
'/guides/agoric-cli/',
'/guides/agoric-cli/agd-query-tx.html',
],
},
{
title: 'JavaScript Framework',
Expand Down
188 changes: 188 additions & 0 deletions main/guides/agoric-cli/agd-query-tx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Using `agd` to make queries and transactions

`agd` is the Agoric Cosmos App, analagous to `simd` in the [Cosmos SDK](https://docs.cosmos.network/) simapp or `gaiad` in
the Cosmos hub. Most of the `simd` [query commands](https://docs.cosmos.network/v0.46/core/cli.html#query-commands) and [transaction commands](https://docs.cosmos.network/v0.46/core/cli.html#transaction-commands) work similarly in `agd`.

::: tip agd for Building Dapps

This section focusses on commands relevant to developing and deploying smart contracts and dapps. See also:

- [Validators topics \- Agoric Community Forum](https://community.agoric.com/c/validators/9)
- [Governance topics \- Agoric Community Forum](https://community.agoric.com/c/governance/6)
- [Delegator Guide \(CLI\) \| Cosmos Hub](https://hub.cosmos.network/main/delegators/delegator-guide-cli.html)

:::

::: tip Installing agd

Options include:

- Use the [basic dapp local chain](../getting-started/#starting-a-local-agoric-blockchain) docker container: to run `agd status`, enter `yarn docker:bash` followed by `agd status`; or use `docker-compose exec agd agd status`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for me, yarn docker:bash gave some errors, I had to run yarn start:docker first for it to work. Likely because some time passed, or my laptop restarted since I went through Your First Agoric Dapp section

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You folks might've already thought about this but would it be possible to create a separate repo that contains all of the docker compose stuff and make all other Dapp sample repos include/reference the same docker compose repo?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for me, yarn docker:bash gave some errors, I had to run yarn start:docker first for it to work.

Were the errors / diagnostics straightforward to understand? You evidently figured out how to proceed. It's not practical to make yarn docker:bash work without yarn start:docker first, but if the diagnostics aren't clear, we could perhaps address that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re separate repo: it's worth considering

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re errors / diagnostics, I was getting a pretty generic error

Error: post failed: Post "http://localhost:26657": dial tcp 127.0.0.1:26657: connect: connection refused

And I figured it out by backtracking my way through Your First Agoric Dapp section and run the docker related command preceding yarn docker:bash

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you got that error in response to yarn docker:bash? that seems unlikely. Perhaps in response to agd status? That's possible, but it would mean you have agd available outside the container.

- Install from an [agoric-sdk release](https://github.com/Agoric/agoric-sdk/releases).

:::

If we invoke `agd` without arguments, it prints a list of available commands including:

```
Available Commands:

help Help about any command
keys Manage your application's keys
query Querying subcommands
status Query remote node for status
tx Transactions subcommands
version Print the application binary version information

Flags:
-h, --help help for agd
--home string directory for config and data (default $HOME)
```

## Query Commands

In most cases, `agd query ...` is followed by a module name such as `bank`. An exception is `agd status`:

### agd status

Query remote node for status

Example:

```console
$ agd status
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion

Pipe the output to jq for readability? I tested in the docker container and it does have jq installed already

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting that we inform our readers about the jq technique?

Or that the output currently in the docs is less readable than it should be?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm suggesting we inform our readers about the jq technique, because the output of this command is a json blob without any formatting or whitespaces in between.

{"NodeInfo":{"protocol_version":{"p2p":"8","block":"11" ... }}}
```

::: tip Formatting with jq

For pretty-printed JSON, or to select parts, pipe the output through [jq](https://jqlang.github.io/jq/).

```console
$ agd status | jq .ValidatorInfo
```

```json
{
"Address": "B4167E20C19D9B30ACD93865B854555D3823B31C",
"PubKey": {
"type": "tendermint/PubKeyEd25519",
"value": "F9rO2FZ5sliRSRUVYnwWYVS0Ptf8Ll1dIOb6SQkgmTA="
},
"VotingPower": "5000"
}
```

:::

The query goes to a local node at `tcp://localhost:26657` by default. To use another node:

```console
$ agd status --node https://devnet.rpc.agoric.net:443
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like once is enough to teach the technique.

{"NodeInfo":{"protocol_version":{"p2p":"8","block":"11" ... }}}
```

::: tip Port is required

Typically, `:443` can be left implicit in `https` URLs.
But not here. Without it, we get:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for my own curiosity

Why is it? Was it because we need to specify port 443 for gRPC to work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why cosmos SDK requires it. I just know that it does.
@JimLarson ? @michaelfig ? Do you know? Should we open an issue?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling for the --node $rpcUri option is client, err := NewClientFromNode(rpcURI), where NewClientFromNode(nodeURI string) returns rpchttp.New(nodeURI, "/websocket") and rpchttp is now cometbft rpc/client/http/http.go but was formerly tendermint rpc/client/http/http.go. Both use url.Parse to parse the input string into a parsedUrl struct "u" and return an http.Client with a Transport whose Dial function is implemented to return net.Dial(protocol, u.GetDialAddress()) [CometBFT, Tendermint], where GetDialAddress() for a URL destination [as opposed to the path of a Unix domain socket] returns the parsed Host (causing failure in the absence of a port because net.Dial is low-level and requires that).

Bottom line, this could easily be fixed by updating func (u parsedURL) GetDialAddress() to pay attention to URL Scheme, e.g.

 // GetDialAddress returns the endpoint to dial for the parsed URL.
 func (u parsedURL) GetDialAddress() string {
-	// if it's not a unix socket we return the host, example: localhost:443
+	// if it's not a unix socket we return the host with port, example: localhost:443
 	if !u.isUnixSocket {
+		hasPort, err := regexp.MatchString(`:[0-9]+$`, u.Host)
+		if err == nil && !hasPort {
+			if u.Scheme == protoHTTP || u.Scheme == protoWS {
+				return u.Host + `:80`
+			} else if u.Scheme == protoHTTPS || u.scheme == protoWSS {
+				return u.Host + `:443`
+			}
+		}
 		return u.Host
 	}
 	// otherwise we return the path of the unix socket, ex /tmp/socket
 	return u.GetHostWithPath()
 }

I think it makes sense to report upstream.

Copy link
Member

@gibson042 gibson042 Dec 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing that since they're using the URL format, they don't want to mess with the assumption that 80 is the implicit port number. Since they don't want to squat on the webserver's favorite port, it would make sense to pick a different standard port number, then make it explicit in the node argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: cometbft no longer requires an explicit port for http/https or ws/wss URLs.


```
Error: post failed: Post "https://devnet.rpc.agoric.net": dial tcp: address devnet.rpc.agoric.net: missing port in address
```

:::

### agd query bank balances

Query for account balances by address

Example:

```
$ addr=agoric14pfrxg63jn6ha0cp6wxkm4nlvswtscrh2pymwm
$ agd query bank balances $addr
balances:
- amount: "331000000"
denom: ubld
- amount: "4854000000"
denom: uist
```

To get **JSON output** rather than YAML:

```console
$ agd query bank balances $addr -o json
{"balances":[{"denom":"ubld","amount":"331000000"},{"denom":"uist","amount":"4854000000"}],...}
```

### agd query gov proposals

Query for a all paginated proposals that match optional filters:

Example:

```
$ agd query gov proposals --output json | \
jq -c '.proposals[] | [.proposal_id,.voting_end_time,.status]'
["1","2023-11-14T17:32:16.665791640Z","PROPOSAL_STATUS_PASSED"]
["2","2023-11-14T17:40:16.450879296Z","PROPOSAL_STATUS_PASSED"]
["3","2023-11-14T17:44:37.432643476Z","PROPOSAL_STATUS_PASSED"]
```

## Transaction Commands

Making transactions requires setting up an **account** with a private key for signing. The [basic dapp local chain](../getting-started/#starting-a-local-agoric-blockchain) container has a number of keys set up for use with `--keyring-backend=test`. Use `agd keys list --keyring-backend=test` to see them.

For accounts that control real negotiable assets, using
a consumer grade wallet such as Keplr is more straightforward.
_Consider a hardware wallet such as a Ledger as well._

### agd tx bank send

Send funds from one account to another.

```
$ src=agoric14pfrxg63jn6ha0cp6wxkm4nlvswtscrh2pymwm
$ dest=agoric1a3zu5aqw255q0tuxzy9aftvgheekw2wedz3xwq
$ amt=12000000ubld
$ agd tx bank send $src $dest $amt \
--keyring-backend=test --chain-id=agoriclocal \
--gas=auto --gas-adjustment=1.2 \
--yes -b block
```

As usual, use `agd tx bank send --help` for documentation on
flags such as `--yes`, `-b`, etc.

### agd tx swingset install-bundle

```
agd tx swingset install-bundle --compress "@bundle1.json" \
--from user1 --keyring-backend=test --gas=auto \
--chain-id=agoriclocal -bblock --yes -o json
```

See also the [Agoric Gov Proposal Builder](https://cosgov.org/) web interface, especially for understanding storage fees.

### agd tx gov submit-proposal swingset-core-eval

Usage:

```sh
agd tx gov submit-proposal swingset-core-eval [[permit.json] [code.js]]... [flags]
```

Example:

```
$ SCRIPT=start-game1.js
$ PERMIT=start-game1-permit.json
agd tx gov submit-proposal swingset-core-eval "$PERMIT" "$SCRIPT" \
--title="Start Game Place Contract" --description="Evaluate $SCRIPT" \
--deposit=10000000ubld --gas=auto --gas-adjustment=1.2 \
--from user1 --chain-id agoriclocal --keyring-backend=test \
--yes -b block
```

The [Agoric Gov Proposal Builder](https://cosgov.org/) web interface provides a nice interface for this as well.