Skip to content

Commit

Permalink
Merge branch 'main' into reece/more-cosmos-test
Browse files Browse the repository at this point in the history
  • Loading branch information
Reecepbcups committed Oct 16, 2023
2 parents 523efc4 + 2c47fa0 commit b30da7b
Show file tree
Hide file tree
Showing 97 changed files with 8,598 additions and 215 deletions.
23 changes: 22 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,25 @@ jobs:
with:
version: v1.54
only-new-issues: true
args: --timeout=5m
args: --timeout=10m

clippy-lint:
defaults:
run:
working-directory: local-interchain/rust/localic-std
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install stable with clippy and rustfmt
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
components: rustfmt, clippy
- name: Install clippy
run: rustup component add clippy
- name: Update
run: cargo update
- name: Run clippy
run: make lint

54 changes: 53 additions & 1 deletion .github/workflows/local-interchain.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ jobs:
build:
runs-on: ubuntu-latest
name: build
defaults:
run:
working-directory: ./local-interchain
steps:
- name: Checkout interchaintest
uses: actions/checkout@v4
Expand All @@ -24,4 +27,53 @@ jobs:
with:
go-version: ${{ env.GO_VERSION }}

- run: cd local-interchain && go mod tidy && make install
- name: build local-interchain
run: go mod tidy && make install

- name: Upload localic artifact
uses: actions/upload-artifact@v3
with:
name: local-ic
path: ~/go/bin/local-ic

# TOOO: put the python workflow here. (https://github.com/strangelove-ventures/interchaintest/pull/775)

rust-e2e:
name: rust e2e
needs: build
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./local-interchain
strategy:
fail-fast: false

steps:
- name: checkout chain
uses: actions/checkout@v3

- name: Install latest toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
target: wasm32-unknown-unknown
override: true

- name: Download Tarball Artifact
uses: actions/download-artifact@v3
with:
name: local-ic
path: /tmp

- name: Make local-ic executable
run: chmod +x /tmp/local-ic

- name: Start background ibc local-interchain
run: /tmp/local-ic start juno_ibc --api-port 8080 &

- name: Run Rust Script
run: cd rust && cargo run --package localic-bin --bin localic-bin

- name: Cleanup
run: killall local-ic && exit 0
35 changes: 35 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: release binary

on:
release:
types: [created]

env:
GO_VERSION: 1.21

jobs:
release-static-binary:
permissions: write-all
runs-on: ubuntu-latest
steps:
- name: Checkout interchaintest
uses: actions/checkout@v4

- name: Setup go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}

# This must be go install vs make install as to not statically link the binary
# to the worker node.
- run: cd local-interchain && go mod tidy && go install ./...

- run: cp $HOME/go/bin/local-ic ./local-ic
- run: chmod +x ./local-ic

- name: Release
uses: softprops/action-gh-release@v1
with:
token: ${{ github.token }}
files: |
local-ic
44 changes: 34 additions & 10 deletions chain/cosmos/chain_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,16 +444,19 @@ func (tn *ChainNode) FindTxs(ctx context.Context, height uint64) ([]blockdb.Tx,
// with the chain node binary.
func (tn *ChainNode) TxCommand(keyName string, command ...string) []string {
command = append([]string{"tx"}, command...)
var gasPriceFound, gasAdjustmentFound = false, false
var gasPriceFound, gasAdjustmentFound, feesFound = false, false, false
for i := 0; i < len(command); i++ {
if command[i] == "--gas-prices" {
gasPriceFound = true
}
if command[i] == "--gas-adjustment" {
gasAdjustmentFound = true
}
if command[i] == "--fees" {
feesFound = true
}
}
if !gasPriceFound {
if !gasPriceFound && !feesFound {
command = append(command, "--gas-prices", tn.Chain.Config().GasPrices)
}
if !gasAdjustmentFound {
Expand Down Expand Up @@ -779,14 +782,17 @@ type CodeInfosResponse struct {
}

// StoreContract takes a file path to smart contract and stores it on-chain. Returns the contracts code id.
func (tn *ChainNode) StoreContract(ctx context.Context, keyName string, fileName string) (string, error) {
func (tn *ChainNode) StoreContract(ctx context.Context, keyName string, fileName string, extraExecTxArgs ...string) (string, error) {
_, file := filepath.Split(fileName)
err := tn.CopyFile(ctx, fileName, file)
if err != nil {
return "", fmt.Errorf("writing contract file to docker volume: %w", err)
}

if _, err := tn.ExecTx(ctx, keyName, "wasm", "store", path.Join(tn.HomeDir(), file), "--gas", "auto"); err != nil {
cmd := []string{"wasm", "store", path.Join(tn.HomeDir(), file), "--gas", "auto"}
cmd = append(cmd, extraExecTxArgs...)

if _, err := tn.ExecTx(ctx, keyName, cmd...); err != nil {
return "", err
}

Expand Down Expand Up @@ -955,10 +961,11 @@ func (tn *ChainNode) InstantiateContract(ctx context.Context, keyName string, co
}

// ExecuteContract executes a contract transaction with a message using it's address.
func (tn *ChainNode) ExecuteContract(ctx context.Context, keyName string, contractAddress string, message string) (txHash string, err error) {
return tn.ExecTx(ctx, keyName,
"wasm", "execute", contractAddress, message,
)
func (tn *ChainNode) ExecuteContract(ctx context.Context, keyName string, contractAddress string, message string, extraExecTxArgs ...string) (txHash string, err error) {
cmd := []string{"wasm", "execute", contractAddress, message}
cmd = append(cmd, extraExecTxArgs...)

return tn.ExecTx(ctx, keyName, cmd...)
}

// QueryContract performs a smart query, taking in a query struct and returning a error with the response struct populated.
Expand All @@ -976,7 +983,7 @@ func (tn *ChainNode) QueryContract(ctx context.Context, contractAddress string,
}

// StoreClientContract takes a file path to a client smart contract and stores it on-chain. Returns the contracts code id.
func (tn *ChainNode) StoreClientContract(ctx context.Context, keyName string, fileName string) (string, error) {
func (tn *ChainNode) StoreClientContract(ctx context.Context, keyName string, fileName string, extraExecTxArgs ...string) (string, error) {
content, err := os.ReadFile(fileName)
if err != nil {
return "", err
Expand All @@ -987,7 +994,10 @@ func (tn *ChainNode) StoreClientContract(ctx context.Context, keyName string, fi
return "", fmt.Errorf("writing contract file to docker volume: %w", err)
}

_, err = tn.ExecTx(ctx, keyName, "ibc-wasm", "store-code", path.Join(tn.HomeDir(), file), "--gas", "auto")
cmd := []string{"ibc-wasm", "store-code", path.Join(tn.HomeDir(), file), "--gas", "auto"}
cmd = append(cmd, extraExecTxArgs...)

_, err = tn.ExecTx(ctx, keyName, cmd...)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -1125,6 +1135,20 @@ func (tn *ChainNode) QueryParam(ctx context.Context, subspace, key string) (*Par
return &param, nil
}

// QueryBankMetadata returns the bank metadata of a token denomination.
func (tn *ChainNode) QueryBankMetadata(ctx context.Context, denom string) (*BankMetaData, error) {
stdout, _, err := tn.ExecQuery(ctx, "bank", "denom-metadata", "--denom", denom)
if err != nil {
return nil, err
}
var meta BankMetaData
err = json.Unmarshal(stdout, &meta)
if err != nil {
return nil, err
}
return &meta, nil
}

// DumpContractState dumps the state of a contract at a block height.
func (tn *ChainNode) DumpContractState(ctx context.Context, contractAddress string, height int64) (*DumpContractStateResponse, error) {
stdout, _, err := tn.ExecQuery(ctx,
Expand Down
17 changes: 11 additions & 6 deletions chain/cosmos/cosmos_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,11 @@ func (c *CosmosChain) QueryParam(ctx context.Context, subspace, key string) (*Pa
return c.getFullNode().QueryParam(ctx, subspace, key)
}

// QueryBankMetadata returns the metadata of a given token denomination.
func (c *CosmosChain) QueryBankMetadata(ctx context.Context, denom string) (*BankMetaData, error) {
return c.getFullNode().QueryBankMetadata(ctx, denom)
}

func (c *CosmosChain) txProposal(txHash string) (tx TxProposal, _ error) {
txResp, err := c.getTransaction(txHash)
if err != nil {
Expand All @@ -497,8 +502,8 @@ func (c *CosmosChain) txProposal(txHash string) (tx TxProposal, _ error) {
}

// StoreContract takes a file path to smart contract and stores it on-chain. Returns the contracts code id.
func (c *CosmosChain) StoreContract(ctx context.Context, keyName string, fileName string) (string, error) {
return c.getFullNode().StoreContract(ctx, keyName, fileName)
func (c *CosmosChain) StoreContract(ctx context.Context, keyName string, fileName string, extraExecTxArgs ...string) (string, error) {
return c.getFullNode().StoreContract(ctx, keyName, fileName, extraExecTxArgs...)
}

// InstantiateContract takes a code id for a smart contract and initialization message and returns the instantiated contract address.
Expand All @@ -507,8 +512,8 @@ func (c *CosmosChain) InstantiateContract(ctx context.Context, keyName string, c
}

// ExecuteContract executes a contract transaction with a message using it's address.
func (c *CosmosChain) ExecuteContract(ctx context.Context, keyName string, contractAddress string, message string) (txHash string, err error) {
return c.getFullNode().ExecuteContract(ctx, keyName, contractAddress, message)
func (c *CosmosChain) ExecuteContract(ctx context.Context, keyName string, contractAddress string, message string, extraExecTxArgs ...string) (txHash string, err error) {
return c.getFullNode().ExecuteContract(ctx, keyName, contractAddress, message, extraExecTxArgs...)
}

// QueryContract performs a smart query, taking in a query struct and returning a error with the response struct populated.
Expand All @@ -522,8 +527,8 @@ func (c *CosmosChain) DumpContractState(ctx context.Context, contractAddress str
}

// StoreClientContract takes a file path to a client smart contract and stores it on-chain. Returns the contracts code id.
func (c *CosmosChain) StoreClientContract(ctx context.Context, keyName string, fileName string) (string, error) {
return c.getFullNode().StoreClientContract(ctx, keyName, fileName)
func (c *CosmosChain) StoreClientContract(ctx context.Context, keyName string, fileName string, extraExecTxArgs ...string) (string, error) {
return c.getFullNode().StoreClientContract(ctx, keyName, fileName, extraExecTxArgs...)
}

// QueryClientContractCode performs a query with the contract codeHash as the input and code as the output
Expand Down
104 changes: 104 additions & 0 deletions chain/cosmos/tokenfactory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package cosmos

import (
"context"
"encoding/json"
"fmt"
"strconv"

"github.com/strangelove-ventures/interchaintest/v8/ibc"
)

// TokenFactoryCreateDenom creates a new tokenfactory token in the format 'factory/accountaddress/name'.
// This token will be viewable by standard bank balance queries and send functionality.
// Depending on the chain parameters, this may require a lot of gas (Juno, Osmosis) if the DenomCreationGasConsume param is enabled.
// If not, the default implementation cost 10,000,000 micro tokens (utoken) of the chain's native token.
func TokenFactoryCreateDenom(c *CosmosChain, ctx context.Context, user ibc.Wallet, denomName string, gas uint64) (string, string, error) {
cmd := []string{"tokenfactory", "create-denom", denomName}

if gas != 0 {
cmd = append(cmd, "--gas", strconv.FormatUint(gas, 10))
}

txHash, err := c.getFullNode().ExecTx(ctx, user.KeyName(), cmd...)
if err != nil {
return "", "", err
}

return "factory/" + user.FormattedAddress() + "/" + denomName, txHash, nil
}

// TokenFactoryBurnDenom burns a tokenfactory denomination from the holders account.
func TokenFactoryBurnDenom(c *CosmosChain, ctx context.Context, keyName, fullDenom string, amount uint64) (string, error) {
coin := strconv.FormatUint(amount, 10) + fullDenom
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "burn", coin,
)
}

// TokenFactoryBurnDenomFrom burns a tokenfactory denomination from any other users account.
// Only the admin of the token can perform this action.
func TokenFactoryBurnDenomFrom(c *CosmosChain, ctx context.Context, keyName, fullDenom string, amount uint64, fromAddr string) (string, error) {
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "burn-from", fromAddr, convertToCoin(amount, fullDenom),
)
}

// TokenFactoryChangeAdmin moves the admin of a tokenfactory token to a new address.
func TokenFactoryChangeAdmin(c *CosmosChain, ctx context.Context, keyName, fullDenom, newAdmin string) (string, error) {
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "change-admin", fullDenom, newAdmin,
)
}

// TokenFactoryForceTransferDenom force moves a token from 1 account to another.
// Only the admin of the token can perform this action.
func TokenFactoryForceTransferDenom(c *CosmosChain, ctx context.Context, keyName, fullDenom string, amount uint64, fromAddr, toAddr string) (string, error) {
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "force-transfer", convertToCoin(amount, fullDenom), fromAddr, toAddr,
)
}

// TokenFactoryMintDenom mints a tokenfactory denomination to the admins account.
// Only the admin of the token can perform this action.
func TokenFactoryMintDenom(c *CosmosChain, ctx context.Context, keyName, fullDenom string, amount uint64) (string, error) {
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "mint", convertToCoin(amount, fullDenom),
)
}

// TokenFactoryMintDenomTo mints a token to any external account.
// Only the admin of the token can perform this action.
func TokenFactoryMintDenomTo(c *CosmosChain, ctx context.Context, keyName, fullDenom string, amount uint64, toAddr string) (string, error) {
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "mint-to", toAddr, convertToCoin(amount, fullDenom),
)
}

// TokenFactoryMetadata sets the x/bank metadata for a tokenfactory token. This gives the token more detailed information to be queried
// by frontend UIs and other applications.
// Only the admin of the token can perform this action.
func TokenFactoryMetadata(c *CosmosChain, ctx context.Context, keyName, fullDenom, ticker, description string, exponent uint64) (string, error) {
return c.getFullNode().ExecTx(ctx, keyName,
"tokenfactory", "modify-metadata", fullDenom, ticker, description, strconv.FormatUint(exponent, 10),
)
}

// TokenFactoryGetAdmin returns the admin of a tokenfactory token.
func TokenFactoryGetAdmin(c *CosmosChain, ctx context.Context, fullDenom string) (*QueryDenomAuthorityMetadataResponse, error) {
res := &QueryDenomAuthorityMetadataResponse{}
stdout, stderr, err := c.getFullNode().ExecQuery(ctx, "tokenfactory", "denom-authority-metadata", fullDenom)
if err != nil {
return nil, fmt.Errorf("failed to query tokenfactory denom-authority-metadata: %w\nstdout: %s\nstderr: %s", err, stdout, stderr)
}

if err := json.Unmarshal(stdout, res); err != nil {
return nil, err
}

return res, nil
}

func convertToCoin(amount uint64, denom string) string {
return strconv.FormatUint(amount, 10) + denom
}
Loading

0 comments on commit b30da7b

Please sign in to comment.